Skip to content

Commit 7cc60a3

Browse files
committed
C++: Flow through get, peek, read, readsome.
1 parent 56390c1 commit 7cc60a3

File tree

5 files changed

+109
-11
lines changed

5 files changed

+109
-11
lines changed

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

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,61 @@ class StdIStreamInNonMember extends DataFlowFunction, TaintFunction {
345345
}
346346
}
347347

348+
/**
349+
* The `std::istream` functions `get` (without parameters) and `peek`.
350+
*/
351+
class StdIStreamGet extends TaintFunction {
352+
StdIStreamGet() {
353+
this.hasQualifiedName("std", "basic_istream", ["get", "peek"]) and
354+
this.getNumberOfParameters() = 0
355+
}
356+
357+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
358+
// flow from qualifier to return value
359+
input.isQualifierObject() and
360+
output.isReturnValue()
361+
}
362+
}
363+
364+
/**
365+
* The `std::istream` functions `get` (with parameters) and `read`.
366+
*/
367+
class StdIStreamRead extends DataFlowFunction, TaintFunction {
368+
StdIStreamRead() {
369+
this.hasQualifiedName("std", "basic_istream", ["get", "read"]) and
370+
this.getNumberOfParameters() > 0
371+
}
372+
373+
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
374+
// flow from qualifier to return value
375+
input.isQualifierObject() and
376+
output.isReturnValue()
377+
}
378+
379+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
380+
// flow from qualifier to first parameter
381+
input.isQualifierObject() and
382+
output.isParameterDeref(0)
383+
or
384+
// reverse flow from returned reference to the qualifier
385+
input.isReturnValueDeref() and
386+
output.isQualifierObject()
387+
}
388+
}
389+
390+
/**
391+
* The `std::istream` function `readsome`.
392+
*/
393+
class StdIStreamReadSome extends TaintFunction {
394+
StdIStreamReadSome() { this.hasQualifiedName("std", "basic_istream", "readsome") }
395+
396+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
397+
// flow from qualifier to first parameter
398+
input.isQualifierObject() and
399+
output.isParameterDeref(0)
400+
}
401+
}
402+
348403
/**
349404
* The `std::basic_ostream` template class.
350405
*/

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1790,30 +1790,40 @@
17901790
| stringstream.cpp:161:7:161:9 | ref arg ss1 | stringstream.cpp:174:12:174:14 | ss1 | |
17911791
| stringstream.cpp:161:7:161:9 | ref arg ss1 | stringstream.cpp:176:12:176:14 | ss1 | |
17921792
| stringstream.cpp:161:7:161:9 | ref arg ss1 | stringstream.cpp:178:7:178:9 | ss1 | |
1793+
| stringstream.cpp:161:7:161:9 | ss1 | stringstream.cpp:161:11:161:14 | call to read | |
1794+
| stringstream.cpp:161:7:161:9 | ss1 | stringstream.cpp:161:16:161:17 | ref arg b5 | TAINT |
17931795
| stringstream.cpp:161:16:161:17 | ref arg b5 | stringstream.cpp:167:7:167:8 | b5 | |
17941796
| stringstream.cpp:162:7:162:9 | ref arg ss2 | stringstream.cpp:164:7:164:9 | ss2 | |
17951797
| stringstream.cpp:162:7:162:9 | ref arg ss2 | stringstream.cpp:166:7:166:9 | ss2 | |
17961798
| stringstream.cpp:162:7:162:9 | ref arg ss2 | stringstream.cpp:175:12:175:14 | ss2 | |
17971799
| stringstream.cpp:162:7:162:9 | ref arg ss2 | stringstream.cpp:177:12:177:14 | ss2 | |
17981800
| stringstream.cpp:162:7:162:9 | ref arg ss2 | stringstream.cpp:179:7:179:9 | ss2 | |
1801+
| stringstream.cpp:162:7:162:9 | ss2 | stringstream.cpp:162:11:162:14 | call to read | |
1802+
| stringstream.cpp:162:7:162:9 | ss2 | stringstream.cpp:162:16:162:17 | ref arg b6 | TAINT |
17991803
| stringstream.cpp:162:16:162:17 | ref arg b6 | stringstream.cpp:168:7:168:8 | b6 | |
18001804
| stringstream.cpp:163:7:163:9 | ref arg ss1 | stringstream.cpp:165:7:165:9 | ss1 | |
18011805
| stringstream.cpp:163:7:163:9 | ref arg ss1 | stringstream.cpp:174:12:174:14 | ss1 | |
18021806
| stringstream.cpp:163:7:163:9 | ref arg ss1 | stringstream.cpp:176:12:176:14 | ss1 | |
18031807
| stringstream.cpp:163:7:163:9 | ref arg ss1 | stringstream.cpp:178:7:178:9 | ss1 | |
1808+
| stringstream.cpp:163:7:163:9 | ss1 | stringstream.cpp:163:20:163:21 | ref arg b7 | TAINT |
18041809
| stringstream.cpp:163:20:163:21 | ref arg b7 | stringstream.cpp:169:7:169:8 | b7 | |
18051810
| stringstream.cpp:164:7:164:9 | ref arg ss2 | stringstream.cpp:166:7:166:9 | ss2 | |
18061811
| stringstream.cpp:164:7:164:9 | ref arg ss2 | stringstream.cpp:175:12:175:14 | ss2 | |
18071812
| stringstream.cpp:164:7:164:9 | ref arg ss2 | stringstream.cpp:177:12:177:14 | ss2 | |
18081813
| stringstream.cpp:164:7:164:9 | ref arg ss2 | stringstream.cpp:179:7:179:9 | ss2 | |
1814+
| stringstream.cpp:164:7:164:9 | ss2 | stringstream.cpp:164:20:164:21 | ref arg b8 | TAINT |
18091815
| stringstream.cpp:164:20:164:21 | ref arg b8 | stringstream.cpp:170:7:170:8 | b8 | |
18101816
| stringstream.cpp:165:7:165:9 | ref arg ss1 | stringstream.cpp:174:12:174:14 | ss1 | |
18111817
| stringstream.cpp:165:7:165:9 | ref arg ss1 | stringstream.cpp:176:12:176:14 | ss1 | |
18121818
| stringstream.cpp:165:7:165:9 | ref arg ss1 | stringstream.cpp:178:7:178:9 | ss1 | |
1819+
| stringstream.cpp:165:7:165:9 | ss1 | stringstream.cpp:165:11:165:13 | call to get | |
1820+
| stringstream.cpp:165:7:165:9 | ss1 | stringstream.cpp:165:15:165:16 | ref arg b9 | TAINT |
18131821
| stringstream.cpp:165:15:165:16 | ref arg b9 | stringstream.cpp:171:7:171:8 | b9 | |
18141822
| stringstream.cpp:166:7:166:9 | ref arg ss2 | stringstream.cpp:175:12:175:14 | ss2 | |
18151823
| stringstream.cpp:166:7:166:9 | ref arg ss2 | stringstream.cpp:177:12:177:14 | ss2 | |
18161824
| stringstream.cpp:166:7:166:9 | ref arg ss2 | stringstream.cpp:179:7:179:9 | ss2 | |
1825+
| stringstream.cpp:166:7:166:9 | ss2 | stringstream.cpp:166:11:166:13 | call to get | |
1826+
| stringstream.cpp:166:7:166:9 | ss2 | stringstream.cpp:166:15:166:17 | ref arg b10 | TAINT |
18171827
| stringstream.cpp:166:15:166:17 | ref arg b10 | stringstream.cpp:172:7:172:9 | b10 | |
18181828
| stringstream.cpp:167:7:167:8 | b5 | stringstream.cpp:167:7:167:8 | call to basic_string | TAINT |
18191829
| stringstream.cpp:168:7:168:8 | b6 | stringstream.cpp:168:7:168:8 | call to basic_string | TAINT |
@@ -1824,22 +1834,30 @@
18241834
| stringstream.cpp:174:7:174:8 | c1 | stringstream.cpp:174:7:174:20 | ... = ... | |
18251835
| stringstream.cpp:174:12:174:14 | ref arg ss1 | stringstream.cpp:176:12:176:14 | ss1 | |
18261836
| stringstream.cpp:174:12:174:14 | ref arg ss1 | stringstream.cpp:178:7:178:9 | ss1 | |
1837+
| stringstream.cpp:174:12:174:14 | ss1 | stringstream.cpp:174:16:174:18 | call to get | TAINT |
18271838
| stringstream.cpp:174:16:174:18 | call to get | stringstream.cpp:174:7:174:20 | ... = ... | |
18281839
| stringstream.cpp:174:16:174:18 | call to get | stringstream.cpp:180:7:180:8 | c1 | |
18291840
| stringstream.cpp:175:7:175:8 | c2 | stringstream.cpp:175:7:175:20 | ... = ... | |
18301841
| stringstream.cpp:175:12:175:14 | ref arg ss2 | stringstream.cpp:177:12:177:14 | ss2 | |
18311842
| stringstream.cpp:175:12:175:14 | ref arg ss2 | stringstream.cpp:179:7:179:9 | ss2 | |
1843+
| stringstream.cpp:175:12:175:14 | ss2 | stringstream.cpp:175:16:175:18 | call to get | TAINT |
18321844
| stringstream.cpp:175:16:175:18 | call to get | stringstream.cpp:175:7:175:20 | ... = ... | |
18331845
| stringstream.cpp:175:16:175:18 | call to get | stringstream.cpp:181:7:181:8 | c2 | |
18341846
| stringstream.cpp:176:7:176:8 | c3 | stringstream.cpp:176:7:176:21 | ... = ... | |
18351847
| stringstream.cpp:176:12:176:14 | ref arg ss1 | stringstream.cpp:178:7:178:9 | ss1 | |
1848+
| stringstream.cpp:176:12:176:14 | ss1 | stringstream.cpp:176:16:176:19 | call to peek | TAINT |
18361849
| stringstream.cpp:176:16:176:19 | call to peek | stringstream.cpp:176:7:176:21 | ... = ... | |
18371850
| stringstream.cpp:176:16:176:19 | call to peek | stringstream.cpp:182:7:182:8 | c3 | |
18381851
| stringstream.cpp:177:7:177:8 | c4 | stringstream.cpp:177:7:177:21 | ... = ... | |
18391852
| stringstream.cpp:177:12:177:14 | ref arg ss2 | stringstream.cpp:179:7:179:9 | ss2 | |
1853+
| stringstream.cpp:177:12:177:14 | ss2 | stringstream.cpp:177:16:177:19 | call to peek | TAINT |
18401854
| stringstream.cpp:177:16:177:19 | call to peek | stringstream.cpp:177:7:177:21 | ... = ... | |
18411855
| stringstream.cpp:177:16:177:19 | call to peek | stringstream.cpp:183:7:183:8 | c4 | |
1856+
| stringstream.cpp:178:7:178:9 | ss1 | stringstream.cpp:178:11:178:13 | call to get | |
1857+
| stringstream.cpp:178:7:178:9 | ss1 | stringstream.cpp:178:15:178:16 | ref arg c5 | TAINT |
18421858
| stringstream.cpp:178:15:178:16 | ref arg c5 | stringstream.cpp:184:7:184:8 | c5 | |
1859+
| stringstream.cpp:179:7:179:9 | ss2 | stringstream.cpp:179:11:179:13 | call to get | |
1860+
| stringstream.cpp:179:7:179:9 | ss2 | stringstream.cpp:179:15:179:16 | ref arg c6 | TAINT |
18431861
| stringstream.cpp:179:15:179:16 | ref arg c6 | stringstream.cpp:185:7:185:8 | c6 | |
18441862
| stringstream.cpp:190:20:190:21 | call to basic_stringstream | stringstream.cpp:192:7:192:8 | ss | |
18451863
| stringstream.cpp:190:20:190:21 | call to basic_stringstream | stringstream.cpp:193:7:193:8 | ss | |
@@ -1859,12 +1877,15 @@
18591877
| stringstream.cpp:193:7:193:8 | ref arg ss | stringstream.cpp:195:7:195:8 | ss | |
18601878
| stringstream.cpp:193:7:193:8 | ref arg ss | stringstream.cpp:196:7:196:8 | ss | |
18611879
| stringstream.cpp:193:7:193:8 | ref arg ss | stringstream.cpp:197:7:197:8 | ss | |
1880+
| stringstream.cpp:193:7:193:8 | ss | stringstream.cpp:193:10:193:12 | call to get | TAINT |
18621881
| stringstream.cpp:194:7:194:8 | ref arg ss | stringstream.cpp:195:7:195:8 | ss | |
18631882
| stringstream.cpp:194:7:194:8 | ref arg ss | stringstream.cpp:196:7:196:8 | ss | |
18641883
| stringstream.cpp:194:7:194:8 | ref arg ss | stringstream.cpp:197:7:197:8 | ss | |
18651884
| stringstream.cpp:195:7:195:8 | ref arg ss | stringstream.cpp:196:7:196:8 | ss | |
18661885
| stringstream.cpp:195:7:195:8 | ref arg ss | stringstream.cpp:197:7:197:8 | ss | |
1886+
| stringstream.cpp:195:7:195:8 | ss | stringstream.cpp:195:10:195:12 | call to get | TAINT |
18671887
| stringstream.cpp:196:7:196:8 | ref arg ss | stringstream.cpp:197:7:197:8 | ss | |
1888+
| stringstream.cpp:197:7:197:8 | ss | stringstream.cpp:197:10:197:12 | call to get | TAINT |
18681889
| structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT |
18691890
| structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT |
18701891
| structlikeclass.cpp:5:7:5:7 | this | structlikeclass.cpp:5:7:5:7 | constructor init of field v [pre-this] | |

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -159,30 +159,30 @@ void test_stringstream_in()
159159
sink(b4); // tainted
160160

161161
sink(ss1.read(b5, 100));
162-
sink(ss2.read(b6, 100)); // tainted [NOT DETECTED]
162+
sink(ss2.read(b6, 100)); // tainted
163163
sink(ss1.readsome(b7, 100));
164164
sink(ss2.readsome(b8, 100)); // (returns a length, not significantly tainted)
165165
sink(ss1.get(b9, 100));
166-
sink(ss2.get(b10, 100));
166+
sink(ss2.get(b10, 100)); // tainted
167167
sink(b5);
168-
sink(b6); // tainted [NOT DETECTED]
168+
sink(b6); // tainted
169169
sink(b7);
170-
sink(b8); // tainted [NOT DETECTED]
170+
sink(b8); // tainted
171171
sink(b9);
172-
sink(b10); // tainted [NOT DETECTED]
172+
sink(b10); // tainted
173173

174174
sink(c1 = ss1.get());
175-
sink(c2 = ss2.get()); // tainted [NOT DETECTED]
175+
sink(c2 = ss2.get()); // tainted
176176
sink(c3 = ss1.peek());
177-
sink(c4 = ss2.peek()); // tainted [NOT DETECTED]
177+
sink(c4 = ss2.peek()); // tainted
178178
sink(ss1.get(c5));
179-
sink(ss2.get(c6)); // tainted [NOT DETECTED]
179+
sink(ss2.get(c6)); // tainted
180180
sink(c1);
181-
sink(c2); // tainted [NOT DETECTED]
181+
sink(c2); // tainted
182182
sink(c3);
183-
sink(c4); // tainted [NOT DETECTED]
183+
sink(c4); // tainted
184184
sink(c5);
185-
sink(c6); // tainted [NOT DETECTED]
185+
sink(c6); // tainted
186186
}
187187

188188
void test_stringstream_putback()

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,17 @@
209209
| stringstream.cpp:157:7:157:8 | call to basic_string | stringstream.cpp:143:14:143:19 | call to source |
210210
| stringstream.cpp:158:7:158:8 | call to basic_string | stringstream.cpp:143:14:143:19 | call to source |
211211
| stringstream.cpp:159:7:159:8 | call to basic_string | stringstream.cpp:143:14:143:19 | call to source |
212+
| stringstream.cpp:162:11:162:14 | call to read | stringstream.cpp:143:14:143:19 | call to source |
213+
| stringstream.cpp:166:11:166:13 | call to get | stringstream.cpp:143:14:143:19 | call to source |
214+
| stringstream.cpp:168:7:168:8 | call to basic_string | stringstream.cpp:143:14:143:19 | call to source |
215+
| stringstream.cpp:170:7:170:8 | call to basic_string | stringstream.cpp:143:14:143:19 | call to source |
216+
| stringstream.cpp:172:7:172:9 | call to basic_string | stringstream.cpp:143:14:143:19 | call to source |
217+
| stringstream.cpp:175:7:175:20 | ... = ... | stringstream.cpp:143:14:143:19 | call to source |
218+
| stringstream.cpp:177:7:177:21 | ... = ... | stringstream.cpp:143:14:143:19 | call to source |
219+
| stringstream.cpp:179:11:179:13 | call to get | stringstream.cpp:143:14:143:19 | call to source |
220+
| stringstream.cpp:181:7:181:8 | c2 | stringstream.cpp:143:14:143:19 | call to source |
221+
| stringstream.cpp:183:7:183:8 | c4 | stringstream.cpp:143:14:143:19 | call to source |
222+
| stringstream.cpp:185:7:185:8 | c6 | stringstream.cpp:143:14:143:19 | call to source |
212223
| structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source |
213224
| structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source |
214225
| 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: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,17 @@
211211
| stringstream.cpp:157:7:157:8 | stringstream.cpp:143:14:143:21 | IR only |
212212
| stringstream.cpp:158:7:158:8 | stringstream.cpp:143:14:143:21 | IR only |
213213
| stringstream.cpp:159:7:159:8 | stringstream.cpp:143:14:143:19 | AST only |
214+
| stringstream.cpp:162:11:162:14 | stringstream.cpp:143:14:143:19 | AST only |
215+
| stringstream.cpp:166:11:166:13 | stringstream.cpp:143:14:143:19 | AST only |
216+
| stringstream.cpp:168:7:168:8 | stringstream.cpp:143:14:143:19 | AST only |
217+
| stringstream.cpp:170:7:170:8 | stringstream.cpp:143:14:143:19 | AST only |
218+
| stringstream.cpp:172:7:172:9 | stringstream.cpp:143:14:143:19 | AST only |
219+
| stringstream.cpp:175:7:175:20 | stringstream.cpp:143:14:143:19 | AST only |
220+
| stringstream.cpp:177:7:177:21 | stringstream.cpp:143:14:143:19 | AST only |
221+
| stringstream.cpp:179:11:179:13 | stringstream.cpp:143:14:143:19 | AST only |
222+
| stringstream.cpp:181:7:181:8 | stringstream.cpp:143:14:143:19 | AST only |
223+
| stringstream.cpp:183:7:183:8 | stringstream.cpp:143:14:143:19 | AST only |
224+
| stringstream.cpp:185:7:185:8 | stringstream.cpp:143:14:143:19 | AST only |
214225
| swap1.cpp:78:12:78:16 | swap1.cpp:69:23:69:23 | AST only |
215226
| swap1.cpp:87:13:87:17 | swap1.cpp:82:16:82:21 | AST only |
216227
| swap1.cpp:88:13:88:17 | swap1.cpp:81:27:81:28 | AST only |

0 commit comments

Comments
 (0)