diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index ddd813a62ae1..f2f975bd69f3 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -436,6 +436,52 @@ class StdIStreamPutBack extends DataFlowFunction, TaintFunction { } } +/** + * The `std::istream` function `getline`. + */ +class StdIStreamGetLine extends DataFlowFunction, TaintFunction { + StdIStreamGetLine() { this.hasQualifiedName("std", "basic_istream", "getline") } + + override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { + // returns reference to `*this` + input.isQualifierAddress() and + output.isReturnValue() + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from qualifier to first parameter + input.isQualifierObject() and + output.isParameterDeref(0) + or + // reverse flow from returned reference to the qualifier + input.isReturnValueDeref() and + output.isQualifierObject() + } +} + +/** + * The (non-member) function `std::getline`. + */ +class StdGetLine extends DataFlowFunction, TaintFunction { + StdGetLine() { this.hasQualifiedName("std", "getline") } + + override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { + // flow from first parameter to return value + input.isParameter(0) and + output.isReturnValue() + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from first parameter to second parameter + input.isParameterDeref(0) and + output.isParameterDeref(1) + or + // reverse flow from returned reference to first parameter + input.isReturnValueDeref() and + output.isParameterDeref(0) + } +} + /** * The `std::basic_ostream` template class. */ @@ -547,3 +593,27 @@ class StdStringStreamStr extends TaintFunction { output.isQualifierObject() } } + +/** + * A `std::` stream function that does not require a model, except that it + * returns a reference to `*this` and thus could be used in a chain. + */ +class StdStreamFunction extends DataFlowFunction, TaintFunction { + StdStreamFunction() { + this.hasQualifiedName("std", "basic_istream", ["ignore", "unget", "seekg"]) or + this.hasQualifiedName("std", "basic_ostream", ["seekp", "flush"]) or + this.hasQualifiedName("std", "basic_ios", "copyfmt") + } + + override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { + // returns reference to `*this` + input.isQualifierAddress() and + output.isReturnValue() + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // reverse flow from returned reference to the qualifier + input.isReturnValueDeref() and + output.isQualifierObject() + } +} 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 6736ae4a4408..87e4566b2d84 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -514,12 +514,12 @@ | standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:53:12:53:18 | source1 | | | standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:54:14:54:20 | source1 | | | standalone_iterators.cpp:53:12:53:18 | ref arg source1 | standalone_iterators.cpp:54:14:54:20 | source1 | | -| stl.h:204:30:204:40 | call to allocator | stl.h:204:21:204:41 | noexcept(...) | TAINT | -| stl.h:204:30:204:40 | call to allocator | stl.h:204:21:204:41 | noexcept(...) | TAINT | -| stl.h:204:30:204:40 | call to allocator | stl.h:204:21:204:41 | noexcept(...) | TAINT | -| stl.h:204:30:204:40 | call to allocator | stl.h:204:21:204:41 | noexcept(...) | TAINT | -| stl.h:204:30:204:40 | call to allocator | stl.h:204:21:204:41 | noexcept(...) | TAINT | -| stl.h:204:53:204:63 | 0 | stl.h:204:46:204:64 | (no string representation) | TAINT | +| stl.h:216:30:216:40 | call to allocator | stl.h:216:21:216:41 | noexcept(...) | TAINT | +| stl.h:216:30:216:40 | call to allocator | stl.h:216:21:216:41 | noexcept(...) | TAINT | +| stl.h:216:30:216:40 | call to allocator | stl.h:216:21:216:41 | noexcept(...) | TAINT | +| stl.h:216:30:216:40 | call to allocator | stl.h:216:21:216:41 | noexcept(...) | TAINT | +| stl.h:216:30:216:40 | call to allocator | stl.h:216:21:216:41 | noexcept(...) | TAINT | +| stl.h:216:53:216:63 | 0 | stl.h:216:46:216:64 | (no string representation) | TAINT | | string.cpp:24:12:24:17 | call to source | string.cpp:28:7:28:7 | a | | | string.cpp:25:16:25:20 | 123 | string.cpp:25:16:25:21 | call to basic_string | TAINT | | string.cpp:25:16:25:21 | call to basic_string | string.cpp:29:7:29:7 | b | | @@ -1896,6 +1896,257 @@ | stringstream.cpp:196:18:196:32 | call to source | stringstream.cpp:196:7:196:8 | ref arg ss | TAINT | | stringstream.cpp:196:18:196:32 | call to source | stringstream.cpp:196:10:196:16 | call to putback | TAINT | | stringstream.cpp:197:7:197:8 | ss | stringstream.cpp:197:10:197:12 | call to get | TAINT | +| stringstream.cpp:202:24:202:28 | abc | stringstream.cpp:202:24:202:28 | call to basic_string | TAINT | +| stringstream.cpp:202:24:202:28 | call to basic_string | stringstream.cpp:202:24:202:29 | call to basic_stringstream | TAINT | +| stringstream.cpp:202:24:202:29 | call to basic_stringstream | stringstream.cpp:214:7:214:9 | ss1 | | +| stringstream.cpp:202:24:202:29 | call to basic_stringstream | stringstream.cpp:217:7:217:9 | ss1 | | +| stringstream.cpp:202:24:202:29 | call to basic_stringstream | stringstream.cpp:222:7:222:9 | ss1 | | +| stringstream.cpp:202:24:202:29 | call to basic_stringstream | stringstream.cpp:225:7:225:9 | ss1 | | +| stringstream.cpp:202:24:202:29 | call to basic_stringstream | stringstream.cpp:234:15:234:17 | ss1 | | +| stringstream.cpp:202:24:202:29 | call to basic_stringstream | stringstream.cpp:237:15:237:17 | ss1 | | +| stringstream.cpp:202:24:202:29 | call to basic_stringstream | stringstream.cpp:242:15:242:17 | ss1 | | +| stringstream.cpp:202:24:202:29 | call to basic_stringstream | stringstream.cpp:245:15:245:17 | ss1 | | +| stringstream.cpp:203:24:203:29 | call to source | stringstream.cpp:203:24:203:31 | call to basic_string | TAINT | +| stringstream.cpp:203:24:203:31 | call to basic_string | stringstream.cpp:203:24:203:32 | call to basic_stringstream | TAINT | +| stringstream.cpp:203:24:203:32 | call to basic_stringstream | stringstream.cpp:215:7:215:9 | ss2 | | +| stringstream.cpp:203:24:203:32 | call to basic_stringstream | stringstream.cpp:216:7:216:9 | ss2 | | +| stringstream.cpp:203:24:203:32 | call to basic_stringstream | stringstream.cpp:223:7:223:9 | ss2 | | +| stringstream.cpp:203:24:203:32 | call to basic_stringstream | stringstream.cpp:224:7:224:9 | ss2 | | +| stringstream.cpp:203:24:203:32 | call to basic_stringstream | stringstream.cpp:230:7:230:9 | ss2 | | +| stringstream.cpp:203:24:203:32 | call to basic_stringstream | stringstream.cpp:235:15:235:17 | ss2 | | +| stringstream.cpp:203:24:203:32 | call to basic_stringstream | stringstream.cpp:236:15:236:17 | ss2 | | +| stringstream.cpp:203:24:203:32 | call to basic_stringstream | stringstream.cpp:243:15:243:17 | ss2 | | +| stringstream.cpp:203:24:203:32 | call to basic_stringstream | stringstream.cpp:244:15:244:17 | ss2 | | +| stringstream.cpp:203:24:203:32 | call to basic_stringstream | stringstream.cpp:250:23:250:25 | ss2 | | +| stringstream.cpp:204:17:204:20 | {...} | stringstream.cpp:214:19:214:20 | b1 | | +| stringstream.cpp:204:17:204:20 | {...} | stringstream.cpp:218:7:218:8 | b1 | | +| stringstream.cpp:204:19:204:19 | 0 | stringstream.cpp:204:17:204:20 | {...} | TAINT | +| stringstream.cpp:205:17:205:20 | {...} | stringstream.cpp:215:19:215:20 | b2 | | +| stringstream.cpp:205:17:205:20 | {...} | stringstream.cpp:219:7:219:8 | b2 | | +| stringstream.cpp:205:19:205:19 | 0 | stringstream.cpp:205:17:205:20 | {...} | TAINT | +| stringstream.cpp:206:17:206:20 | {...} | stringstream.cpp:216:19:216:20 | b3 | | +| stringstream.cpp:206:17:206:20 | {...} | stringstream.cpp:217:19:217:20 | b3 | | +| stringstream.cpp:206:17:206:20 | {...} | stringstream.cpp:220:7:220:8 | b3 | | +| stringstream.cpp:206:19:206:19 | 0 | stringstream.cpp:206:17:206:20 | {...} | TAINT | +| stringstream.cpp:207:17:207:20 | {...} | stringstream.cpp:222:19:222:20 | b4 | | +| stringstream.cpp:207:17:207:20 | {...} | stringstream.cpp:226:7:226:8 | b4 | | +| stringstream.cpp:207:19:207:19 | 0 | stringstream.cpp:207:17:207:20 | {...} | TAINT | +| stringstream.cpp:208:17:208:20 | {...} | stringstream.cpp:223:19:223:20 | b5 | | +| stringstream.cpp:208:17:208:20 | {...} | stringstream.cpp:227:7:227:8 | b5 | | +| stringstream.cpp:208:19:208:19 | 0 | stringstream.cpp:208:17:208:20 | {...} | TAINT | +| stringstream.cpp:209:17:209:20 | {...} | stringstream.cpp:224:19:224:20 | b6 | | +| stringstream.cpp:209:17:209:20 | {...} | stringstream.cpp:225:19:225:20 | b6 | | +| stringstream.cpp:209:17:209:20 | {...} | stringstream.cpp:228:7:228:8 | b6 | | +| stringstream.cpp:209:19:209:19 | 0 | stringstream.cpp:209:17:209:20 | {...} | TAINT | +| stringstream.cpp:210:17:210:20 | {...} | stringstream.cpp:230:19:230:20 | b7 | | +| stringstream.cpp:210:17:210:20 | {...} | stringstream.cpp:231:7:231:8 | b7 | | +| stringstream.cpp:210:19:210:19 | 0 | stringstream.cpp:210:17:210:20 | {...} | TAINT | +| stringstream.cpp:211:17:211:20 | {...} | stringstream.cpp:230:37:230:38 | b8 | | +| stringstream.cpp:211:17:211:20 | {...} | stringstream.cpp:232:7:232:8 | b8 | | +| stringstream.cpp:211:19:211:19 | 0 | stringstream.cpp:211:17:211:20 | {...} | TAINT | +| stringstream.cpp:212:14:212:15 | call to basic_string | stringstream.cpp:234:20:234:21 | s1 | | +| stringstream.cpp:212:14:212:15 | call to basic_string | stringstream.cpp:238:7:238:8 | s1 | | +| stringstream.cpp:212:18:212:19 | call to basic_string | stringstream.cpp:235:20:235:21 | s2 | | +| stringstream.cpp:212:18:212:19 | call to basic_string | stringstream.cpp:239:7:239:8 | s2 | | +| stringstream.cpp:212:22:212:23 | call to basic_string | stringstream.cpp:236:20:236:21 | s3 | | +| stringstream.cpp:212:22:212:23 | call to basic_string | stringstream.cpp:237:20:237:21 | s3 | | +| stringstream.cpp:212:22:212:23 | call to basic_string | stringstream.cpp:240:7:240:8 | s3 | | +| stringstream.cpp:212:26:212:27 | call to basic_string | stringstream.cpp:242:20:242:21 | s4 | | +| stringstream.cpp:212:26:212:27 | call to basic_string | stringstream.cpp:246:7:246:8 | s4 | | +| stringstream.cpp:212:30:212:31 | call to basic_string | stringstream.cpp:243:20:243:21 | s5 | | +| stringstream.cpp:212:30:212:31 | call to basic_string | stringstream.cpp:247:7:247:8 | s5 | | +| stringstream.cpp:212:34:212:35 | call to basic_string | stringstream.cpp:244:20:244:21 | s6 | | +| stringstream.cpp:212:34:212:35 | call to basic_string | stringstream.cpp:245:20:245:21 | s6 | | +| stringstream.cpp:212:34:212:35 | call to basic_string | stringstream.cpp:248:7:248:8 | s6 | | +| stringstream.cpp:212:38:212:39 | call to basic_string | stringstream.cpp:250:28:250:29 | s7 | | +| stringstream.cpp:212:38:212:39 | call to basic_string | stringstream.cpp:251:7:251:8 | s7 | | +| stringstream.cpp:212:42:212:43 | call to basic_string | stringstream.cpp:250:33:250:34 | s8 | | +| stringstream.cpp:212:42:212:43 | call to basic_string | stringstream.cpp:252:7:252:8 | s8 | | +| stringstream.cpp:214:7:214:9 | ref arg ss1 | stringstream.cpp:217:7:217:9 | ss1 | | +| stringstream.cpp:214:7:214:9 | ref arg ss1 | stringstream.cpp:222:7:222:9 | ss1 | | +| stringstream.cpp:214:7:214:9 | ref arg ss1 | stringstream.cpp:225:7:225:9 | ss1 | | +| stringstream.cpp:214:7:214:9 | ref arg ss1 | stringstream.cpp:234:15:234:17 | ss1 | | +| stringstream.cpp:214:7:214:9 | ref arg ss1 | stringstream.cpp:237:15:237:17 | ss1 | | +| stringstream.cpp:214:7:214:9 | ref arg ss1 | stringstream.cpp:242:15:242:17 | ss1 | | +| stringstream.cpp:214:7:214:9 | ref arg ss1 | stringstream.cpp:245:15:245:17 | ss1 | | +| stringstream.cpp:214:7:214:9 | ss1 | stringstream.cpp:214:11:214:17 | call to getline | | +| stringstream.cpp:214:7:214:9 | ss1 | stringstream.cpp:214:19:214:20 | ref arg b1 | TAINT | +| stringstream.cpp:214:19:214:20 | ref arg b1 | stringstream.cpp:218:7:218:8 | b1 | | +| stringstream.cpp:215:7:215:9 | ref arg ss2 | stringstream.cpp:216:7:216:9 | ss2 | | +| stringstream.cpp:215:7:215:9 | ref arg ss2 | stringstream.cpp:223:7:223:9 | ss2 | | +| stringstream.cpp:215:7:215:9 | ref arg ss2 | stringstream.cpp:224:7:224:9 | ss2 | | +| stringstream.cpp:215:7:215:9 | ref arg ss2 | stringstream.cpp:230:7:230:9 | ss2 | | +| stringstream.cpp:215:7:215:9 | ref arg ss2 | stringstream.cpp:235:15:235:17 | ss2 | | +| stringstream.cpp:215:7:215:9 | ref arg ss2 | stringstream.cpp:236:15:236:17 | ss2 | | +| stringstream.cpp:215:7:215:9 | ref arg ss2 | stringstream.cpp:243:15:243:17 | ss2 | | +| stringstream.cpp:215:7:215:9 | ref arg ss2 | stringstream.cpp:244:15:244:17 | ss2 | | +| stringstream.cpp:215:7:215:9 | ref arg ss2 | stringstream.cpp:250:23:250:25 | ss2 | | +| stringstream.cpp:215:7:215:9 | ss2 | stringstream.cpp:215:11:215:17 | call to getline | | +| stringstream.cpp:215:7:215:9 | ss2 | stringstream.cpp:215:19:215:20 | ref arg b2 | TAINT | +| stringstream.cpp:215:19:215:20 | ref arg b2 | stringstream.cpp:219:7:219:8 | b2 | | +| stringstream.cpp:216:7:216:9 | ref arg ss2 | stringstream.cpp:223:7:223:9 | ss2 | | +| stringstream.cpp:216:7:216:9 | ref arg ss2 | stringstream.cpp:224:7:224:9 | ss2 | | +| stringstream.cpp:216:7:216:9 | ref arg ss2 | stringstream.cpp:230:7:230:9 | ss2 | | +| stringstream.cpp:216:7:216:9 | ref arg ss2 | stringstream.cpp:235:15:235:17 | ss2 | | +| stringstream.cpp:216:7:216:9 | ref arg ss2 | stringstream.cpp:236:15:236:17 | ss2 | | +| stringstream.cpp:216:7:216:9 | ref arg ss2 | stringstream.cpp:243:15:243:17 | ss2 | | +| stringstream.cpp:216:7:216:9 | ref arg ss2 | stringstream.cpp:244:15:244:17 | ss2 | | +| stringstream.cpp:216:7:216:9 | ref arg ss2 | stringstream.cpp:250:23:250:25 | ss2 | | +| stringstream.cpp:216:7:216:9 | ss2 | stringstream.cpp:216:11:216:17 | call to getline | | +| stringstream.cpp:216:7:216:9 | ss2 | stringstream.cpp:216:19:216:20 | ref arg b3 | TAINT | +| stringstream.cpp:216:19:216:20 | ref arg b3 | stringstream.cpp:217:19:217:20 | b3 | | +| stringstream.cpp:216:19:216:20 | ref arg b3 | stringstream.cpp:220:7:220:8 | b3 | | +| stringstream.cpp:217:7:217:9 | ref arg ss1 | stringstream.cpp:222:7:222:9 | ss1 | | +| stringstream.cpp:217:7:217:9 | ref arg ss1 | stringstream.cpp:225:7:225:9 | ss1 | | +| stringstream.cpp:217:7:217:9 | ref arg ss1 | stringstream.cpp:234:15:234:17 | ss1 | | +| stringstream.cpp:217:7:217:9 | ref arg ss1 | stringstream.cpp:237:15:237:17 | ss1 | | +| stringstream.cpp:217:7:217:9 | ref arg ss1 | stringstream.cpp:242:15:242:17 | ss1 | | +| stringstream.cpp:217:7:217:9 | ref arg ss1 | stringstream.cpp:245:15:245:17 | ss1 | | +| stringstream.cpp:217:7:217:9 | ss1 | stringstream.cpp:217:11:217:17 | call to getline | | +| stringstream.cpp:217:7:217:9 | ss1 | stringstream.cpp:217:19:217:20 | ref arg b3 | TAINT | +| stringstream.cpp:217:19:217:20 | ref arg b3 | stringstream.cpp:220:7:220:8 | b3 | | +| stringstream.cpp:218:7:218:8 | b1 | stringstream.cpp:218:7:218:8 | call to basic_string | TAINT | +| stringstream.cpp:219:7:219:8 | b2 | stringstream.cpp:219:7:219:8 | call to basic_string | TAINT | +| stringstream.cpp:220:7:220:8 | b3 | stringstream.cpp:220:7:220:8 | call to basic_string | TAINT | +| stringstream.cpp:222:7:222:9 | ref arg ss1 | stringstream.cpp:225:7:225:9 | ss1 | | +| stringstream.cpp:222:7:222:9 | ref arg ss1 | stringstream.cpp:234:15:234:17 | ss1 | | +| stringstream.cpp:222:7:222:9 | ref arg ss1 | stringstream.cpp:237:15:237:17 | ss1 | | +| stringstream.cpp:222:7:222:9 | ref arg ss1 | stringstream.cpp:242:15:242:17 | ss1 | | +| stringstream.cpp:222:7:222:9 | ref arg ss1 | stringstream.cpp:245:15:245:17 | ss1 | | +| stringstream.cpp:222:7:222:9 | ss1 | stringstream.cpp:222:11:222:17 | call to getline | | +| stringstream.cpp:222:7:222:9 | ss1 | stringstream.cpp:222:19:222:20 | ref arg b4 | TAINT | +| stringstream.cpp:222:19:222:20 | ref arg b4 | stringstream.cpp:226:7:226:8 | b4 | | +| stringstream.cpp:223:7:223:9 | ref arg ss2 | stringstream.cpp:224:7:224:9 | ss2 | | +| stringstream.cpp:223:7:223:9 | ref arg ss2 | stringstream.cpp:230:7:230:9 | ss2 | | +| stringstream.cpp:223:7:223:9 | ref arg ss2 | stringstream.cpp:235:15:235:17 | ss2 | | +| stringstream.cpp:223:7:223:9 | ref arg ss2 | stringstream.cpp:236:15:236:17 | ss2 | | +| stringstream.cpp:223:7:223:9 | ref arg ss2 | stringstream.cpp:243:15:243:17 | ss2 | | +| stringstream.cpp:223:7:223:9 | ref arg ss2 | stringstream.cpp:244:15:244:17 | ss2 | | +| stringstream.cpp:223:7:223:9 | ref arg ss2 | stringstream.cpp:250:23:250:25 | ss2 | | +| stringstream.cpp:223:7:223:9 | ss2 | stringstream.cpp:223:11:223:17 | call to getline | | +| stringstream.cpp:223:7:223:9 | ss2 | stringstream.cpp:223:19:223:20 | ref arg b5 | TAINT | +| stringstream.cpp:223:19:223:20 | ref arg b5 | stringstream.cpp:227:7:227:8 | b5 | | +| stringstream.cpp:224:7:224:9 | ref arg ss2 | stringstream.cpp:230:7:230:9 | ss2 | | +| stringstream.cpp:224:7:224:9 | ref arg ss2 | stringstream.cpp:235:15:235:17 | ss2 | | +| stringstream.cpp:224:7:224:9 | ref arg ss2 | stringstream.cpp:236:15:236:17 | ss2 | | +| stringstream.cpp:224:7:224:9 | ref arg ss2 | stringstream.cpp:243:15:243:17 | ss2 | | +| stringstream.cpp:224:7:224:9 | ref arg ss2 | stringstream.cpp:244:15:244:17 | ss2 | | +| stringstream.cpp:224:7:224:9 | ref arg ss2 | stringstream.cpp:250:23:250:25 | ss2 | | +| stringstream.cpp:224:7:224:9 | ss2 | stringstream.cpp:224:11:224:17 | call to getline | | +| stringstream.cpp:224:7:224:9 | ss2 | stringstream.cpp:224:19:224:20 | ref arg b6 | TAINT | +| stringstream.cpp:224:19:224:20 | ref arg b6 | stringstream.cpp:225:19:225:20 | b6 | | +| stringstream.cpp:224:19:224:20 | ref arg b6 | stringstream.cpp:228:7:228:8 | b6 | | +| stringstream.cpp:225:7:225:9 | ref arg ss1 | stringstream.cpp:234:15:234:17 | ss1 | | +| stringstream.cpp:225:7:225:9 | ref arg ss1 | stringstream.cpp:237:15:237:17 | ss1 | | +| stringstream.cpp:225:7:225:9 | ref arg ss1 | stringstream.cpp:242:15:242:17 | ss1 | | +| stringstream.cpp:225:7:225:9 | ref arg ss1 | stringstream.cpp:245:15:245:17 | ss1 | | +| stringstream.cpp:225:7:225:9 | ss1 | stringstream.cpp:225:11:225:17 | call to getline | | +| stringstream.cpp:225:7:225:9 | ss1 | stringstream.cpp:225:19:225:20 | ref arg b6 | TAINT | +| stringstream.cpp:225:19:225:20 | ref arg b6 | stringstream.cpp:228:7:228:8 | b6 | | +| stringstream.cpp:226:7:226:8 | b4 | stringstream.cpp:226:7:226:8 | call to basic_string | TAINT | +| stringstream.cpp:227:7:227:8 | b5 | stringstream.cpp:227:7:227:8 | call to basic_string | TAINT | +| stringstream.cpp:228:7:228:8 | b6 | stringstream.cpp:228:7:228:8 | call to basic_string | TAINT | +| stringstream.cpp:230:7:230:9 | ref arg ss2 | stringstream.cpp:235:15:235:17 | ss2 | | +| stringstream.cpp:230:7:230:9 | ref arg ss2 | stringstream.cpp:236:15:236:17 | ss2 | | +| stringstream.cpp:230:7:230:9 | ref arg ss2 | stringstream.cpp:243:15:243:17 | ss2 | | +| stringstream.cpp:230:7:230:9 | ref arg ss2 | stringstream.cpp:244:15:244:17 | ss2 | | +| stringstream.cpp:230:7:230:9 | ref arg ss2 | stringstream.cpp:250:23:250:25 | ss2 | | +| stringstream.cpp:230:7:230:9 | ss2 | stringstream.cpp:230:11:230:17 | call to getline | | +| stringstream.cpp:230:7:230:9 | ss2 | stringstream.cpp:230:19:230:20 | ref arg b7 | TAINT | +| stringstream.cpp:230:11:230:17 | call to getline | stringstream.cpp:230:29:230:35 | call to getline | | +| stringstream.cpp:230:11:230:17 | call to getline | stringstream.cpp:230:37:230:38 | ref arg b8 | TAINT | +| stringstream.cpp:230:11:230:17 | ref arg call to getline | stringstream.cpp:230:7:230:9 | ref arg ss2 | TAINT | +| stringstream.cpp:230:19:230:20 | ref arg b7 | stringstream.cpp:231:7:231:8 | b7 | | +| stringstream.cpp:230:37:230:38 | ref arg b8 | stringstream.cpp:232:7:232:8 | b8 | | +| stringstream.cpp:231:7:231:8 | b7 | stringstream.cpp:231:7:231:8 | call to basic_string | TAINT | +| stringstream.cpp:232:7:232:8 | b8 | stringstream.cpp:232:7:232:8 | call to basic_string | TAINT | +| stringstream.cpp:234:15:234:17 | ref arg ss1 | stringstream.cpp:237:15:237:17 | ss1 | | +| stringstream.cpp:234:15:234:17 | ref arg ss1 | stringstream.cpp:242:15:242:17 | ss1 | | +| stringstream.cpp:234:15:234:17 | ref arg ss1 | stringstream.cpp:245:15:245:17 | ss1 | | +| stringstream.cpp:234:15:234:17 | ss1 | stringstream.cpp:234:7:234:13 | call to getline | | +| stringstream.cpp:234:15:234:17 | ss1 | stringstream.cpp:234:20:234:21 | ref arg s1 | TAINT | +| stringstream.cpp:234:20:234:21 | ref arg s1 | stringstream.cpp:238:7:238:8 | s1 | | +| stringstream.cpp:235:15:235:17 | ref arg ss2 | stringstream.cpp:236:15:236:17 | ss2 | | +| stringstream.cpp:235:15:235:17 | ref arg ss2 | stringstream.cpp:243:15:243:17 | ss2 | | +| stringstream.cpp:235:15:235:17 | ref arg ss2 | stringstream.cpp:244:15:244:17 | ss2 | | +| stringstream.cpp:235:15:235:17 | ref arg ss2 | stringstream.cpp:250:23:250:25 | ss2 | | +| stringstream.cpp:235:15:235:17 | ss2 | stringstream.cpp:235:7:235:13 | call to getline | | +| stringstream.cpp:235:15:235:17 | ss2 | stringstream.cpp:235:20:235:21 | ref arg s2 | TAINT | +| stringstream.cpp:235:20:235:21 | ref arg s2 | stringstream.cpp:239:7:239:8 | s2 | | +| stringstream.cpp:236:15:236:17 | ref arg ss2 | stringstream.cpp:243:15:243:17 | ss2 | | +| stringstream.cpp:236:15:236:17 | ref arg ss2 | stringstream.cpp:244:15:244:17 | ss2 | | +| stringstream.cpp:236:15:236:17 | ref arg ss2 | stringstream.cpp:250:23:250:25 | ss2 | | +| stringstream.cpp:236:15:236:17 | ss2 | stringstream.cpp:236:7:236:13 | call to getline | | +| stringstream.cpp:236:15:236:17 | ss2 | stringstream.cpp:236:20:236:21 | ref arg s3 | TAINT | +| stringstream.cpp:236:20:236:21 | ref arg s3 | stringstream.cpp:237:20:237:21 | s3 | | +| stringstream.cpp:236:20:236:21 | ref arg s3 | stringstream.cpp:240:7:240:8 | s3 | | +| stringstream.cpp:237:15:237:17 | ref arg ss1 | stringstream.cpp:242:15:242:17 | ss1 | | +| stringstream.cpp:237:15:237:17 | ref arg ss1 | stringstream.cpp:245:15:245:17 | ss1 | | +| stringstream.cpp:237:15:237:17 | ss1 | stringstream.cpp:237:7:237:13 | call to getline | | +| stringstream.cpp:237:15:237:17 | ss1 | stringstream.cpp:237:20:237:21 | ref arg s3 | TAINT | +| stringstream.cpp:237:20:237:21 | ref arg s3 | stringstream.cpp:240:7:240:8 | s3 | | +| stringstream.cpp:242:15:242:17 | ref arg ss1 | stringstream.cpp:245:15:245:17 | ss1 | | +| stringstream.cpp:242:15:242:17 | ss1 | stringstream.cpp:242:7:242:13 | call to getline | | +| stringstream.cpp:242:15:242:17 | ss1 | stringstream.cpp:242:20:242:21 | ref arg s4 | TAINT | +| stringstream.cpp:242:20:242:21 | ref arg s4 | stringstream.cpp:246:7:246:8 | s4 | | +| stringstream.cpp:243:15:243:17 | ref arg ss2 | stringstream.cpp:244:15:244:17 | ss2 | | +| stringstream.cpp:243:15:243:17 | ref arg ss2 | stringstream.cpp:250:23:250:25 | ss2 | | +| stringstream.cpp:243:15:243:17 | ss2 | stringstream.cpp:243:7:243:13 | call to getline | | +| stringstream.cpp:243:15:243:17 | ss2 | stringstream.cpp:243:20:243:21 | ref arg s5 | TAINT | +| stringstream.cpp:243:20:243:21 | ref arg s5 | stringstream.cpp:247:7:247:8 | s5 | | +| stringstream.cpp:244:15:244:17 | ref arg ss2 | stringstream.cpp:250:23:250:25 | ss2 | | +| stringstream.cpp:244:15:244:17 | ss2 | stringstream.cpp:244:7:244:13 | call to getline | | +| stringstream.cpp:244:15:244:17 | ss2 | stringstream.cpp:244:20:244:21 | ref arg s6 | TAINT | +| stringstream.cpp:244:20:244:21 | ref arg s6 | stringstream.cpp:245:20:245:21 | s6 | | +| stringstream.cpp:244:20:244:21 | ref arg s6 | stringstream.cpp:248:7:248:8 | s6 | | +| stringstream.cpp:245:15:245:17 | ss1 | stringstream.cpp:245:7:245:13 | call to getline | | +| stringstream.cpp:245:15:245:17 | ss1 | stringstream.cpp:245:20:245:21 | ref arg s6 | TAINT | +| stringstream.cpp:245:20:245:21 | ref arg s6 | stringstream.cpp:248:7:248:8 | s6 | | +| stringstream.cpp:250:15:250:21 | call to getline | stringstream.cpp:250:7:250:13 | call to getline | | +| stringstream.cpp:250:15:250:21 | call to getline | stringstream.cpp:250:33:250:34 | ref arg s8 | TAINT | +| stringstream.cpp:250:15:250:21 | ref arg call to getline | stringstream.cpp:250:23:250:25 | ref arg ss2 | TAINT | +| stringstream.cpp:250:23:250:25 | ss2 | stringstream.cpp:250:15:250:21 | call to getline | | +| stringstream.cpp:250:23:250:25 | ss2 | stringstream.cpp:250:28:250:29 | ref arg s7 | TAINT | +| stringstream.cpp:250:28:250:29 | ref arg s7 | stringstream.cpp:251:7:251:8 | s7 | | +| stringstream.cpp:250:33:250:34 | ref arg s8 | stringstream.cpp:252:7:252:8 | s8 | | +| stringstream.cpp:257:24:257:29 | call to source | stringstream.cpp:257:24:257:31 | call to basic_string | TAINT | +| stringstream.cpp:257:24:257:31 | call to basic_string | stringstream.cpp:257:24:257:32 | call to basic_stringstream | TAINT | +| stringstream.cpp:257:24:257:32 | call to basic_stringstream | stringstream.cpp:262:7:262:9 | ss1 | | +| stringstream.cpp:258:20:258:22 | call to basic_stringstream | stringstream.cpp:266:7:266:9 | ss2 | | +| stringstream.cpp:258:20:258:22 | call to basic_stringstream | stringstream.cpp:267:7:267:9 | ss2 | | +| stringstream.cpp:259:17:259:20 | {...} | stringstream.cpp:262:15:262:16 | b1 | | +| stringstream.cpp:259:17:259:20 | {...} | stringstream.cpp:263:7:263:8 | b1 | | +| stringstream.cpp:259:19:259:19 | 0 | stringstream.cpp:259:17:259:20 | {...} | TAINT | +| stringstream.cpp:260:17:260:20 | {...} | stringstream.cpp:262:36:262:37 | b2 | | +| stringstream.cpp:260:17:260:20 | {...} | stringstream.cpp:264:7:264:8 | b2 | | +| stringstream.cpp:260:19:260:19 | 0 | stringstream.cpp:260:17:260:20 | {...} | TAINT | +| stringstream.cpp:262:7:262:9 | ss1 | stringstream.cpp:262:11:262:13 | call to get | | +| stringstream.cpp:262:7:262:9 | ss1 | stringstream.cpp:262:15:262:16 | ref arg b1 | TAINT | +| stringstream.cpp:262:11:262:13 | call to get | stringstream.cpp:262:24:262:28 | call to unget | | +| stringstream.cpp:262:11:262:13 | ref arg call to get | stringstream.cpp:262:7:262:9 | ref arg ss1 | TAINT | +| stringstream.cpp:262:15:262:16 | ref arg b1 | stringstream.cpp:263:7:263:8 | b1 | | +| stringstream.cpp:262:24:262:28 | call to unget | stringstream.cpp:262:32:262:34 | call to get | | +| stringstream.cpp:262:24:262:28 | call to unget | stringstream.cpp:262:36:262:37 | ref arg b2 | TAINT | +| stringstream.cpp:262:24:262:28 | ref arg call to unget | stringstream.cpp:262:11:262:13 | ref arg call to get | TAINT | +| stringstream.cpp:262:36:262:37 | ref arg b2 | stringstream.cpp:264:7:264:8 | b2 | | +| stringstream.cpp:263:7:263:8 | b1 | stringstream.cpp:263:7:263:8 | call to basic_string | TAINT | +| stringstream.cpp:264:7:264:8 | b2 | stringstream.cpp:264:7:264:8 | call to basic_string | TAINT | +| stringstream.cpp:266:7:266:9 | ref arg ss2 | stringstream.cpp:267:7:267:9 | ss2 | | +| stringstream.cpp:266:7:266:9 | ss2 | stringstream.cpp:266:11:266:15 | call to write | | +| stringstream.cpp:266:11:266:15 | call to write | stringstream.cpp:266:27:266:31 | call to flush | | +| stringstream.cpp:266:11:266:15 | ref arg call to write | stringstream.cpp:266:7:266:9 | ref arg ss2 | TAINT | +| stringstream.cpp:266:17:266:21 | abc | stringstream.cpp:266:7:266:9 | ref arg ss2 | TAINT | +| stringstream.cpp:266:17:266:21 | abc | stringstream.cpp:266:11:266:15 | call to write | TAINT | +| stringstream.cpp:266:27:266:31 | call to flush | stringstream.cpp:266:35:266:39 | call to write | | +| stringstream.cpp:266:27:266:31 | ref arg call to flush | stringstream.cpp:266:11:266:15 | ref arg call to write | TAINT | +| stringstream.cpp:266:35:266:39 | call to write | stringstream.cpp:266:54:266:58 | call to flush | | +| stringstream.cpp:266:35:266:39 | ref arg call to write | stringstream.cpp:266:27:266:31 | ref arg call to flush | TAINT | +| stringstream.cpp:266:41:266:46 | call to source | stringstream.cpp:266:27:266:31 | ref arg call to flush | TAINT | +| stringstream.cpp:266:41:266:46 | call to source | stringstream.cpp:266:35:266:39 | call to write | TAINT | +| stringstream.cpp:266:54:266:58 | call to flush | stringstream.cpp:266:62:266:66 | call to write | | +| stringstream.cpp:266:54:266:58 | ref arg call to flush | stringstream.cpp:266:35:266:39 | ref arg call to write | TAINT | +| stringstream.cpp:266:68:266:72 | xyz | stringstream.cpp:266:54:266:58 | ref arg call to flush | TAINT | +| stringstream.cpp:266:68:266:72 | xyz | stringstream.cpp:266:62:266:66 | call to write | TAINT | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | this | structlikeclass.cpp:5:7:5:7 | constructor init of field v [pre-this] | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h index 6392b42e4b43..f04eb5a01d4a 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h @@ -144,12 +144,18 @@ namespace std basic_istream& read (char_type* s, streamsize n); streamsize readsome(char_type* s, streamsize n); basic_istream& putback(char_type c); + basic_istream& unget(); - }; + basic_istream& getline(char_type* s, streamsize n); + basic_istream& getline(char_type* s, streamsize n, char_type delim); + }; template basic_istream& operator>>(basic_istream&, charT*); template basic_istream& operator>>(basic_istream& is, basic_string& str); + template basic_istream& getline(basic_istream& is, basic_string& str, charT delim); + template basic_istream& getline(basic_istream& is, basic_string& str); + template > class basic_ostream /*: virtual public basic_ios - not needed for this test */ { public: @@ -159,6 +165,7 @@ namespace std basic_ostream& put(char_type c); basic_ostream& write(const char_type* s, streamsize n); + basic_ostream& flush(); }; template basic_ostream& operator<<(basic_ostream&, const charT*); @@ -185,6 +192,11 @@ namespace std void str(const basic_string& str); }; + typedef basic_istream istream; + typedef basic_ostream ostream; + extern istream cin; + extern ostream cout; + using stringstream = basic_stringstream; } diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp index 3131fe2d132e..04b88922c3f0 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp @@ -14,10 +14,10 @@ char *user_input() { return source(); } -void sink(const char *s) {}; -void sink(const std::string &s) {}; +void sink(const char *s); +void sink(const std::string &s); void sink(const char *filename, const char *mode); -void sink(char) {} +void sink(char); void test_string() { diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp index f2563ba9277e..e700bccb9300 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp @@ -10,18 +10,18 @@ namespace ns_char char source(); } -void sink(int i) {}; +void sink(int i); -void sink(const std::string &s) {}; +void sink(const std::string &s); template -void sink(const std::basic_ostream &s) {}; +void sink(const std::basic_ostream &s); template -void sink(const std::basic_istream &s) {}; +void sink(const std::basic_istream &s); template -void sink(const std::basic_iostream &s) {}; +void sink(const std::basic_iostream &s); void test_stringstream_string(int amount) { @@ -196,3 +196,73 @@ void test_stringstream_putback() sink(ss.putback(ns_char::source())); // tainted sink(ss.get()); // tainted } + +void test_getline() +{ + std::stringstream ss1("abc"); + std::stringstream ss2(source()); + char b1[1000] = {0}; + char b2[1000] = {0}; + char b3[1000] = {0}; + char b4[1000] = {0}; + char b5[1000] = {0}; + char b6[1000] = {0}; + char b7[1000] = {0}; + char b8[1000] = {0}; + std::string s1, s2, s3, s4, s5, s6, s7, s8; + + sink(ss1.getline(b1, 1000)); + sink(ss2.getline(b2, 1000)); // tainted + sink(ss2.getline(b3, 1000)); // tainted + sink(ss1.getline(b3, 1000)); + sink(b1); + sink(b2); // tainted + sink(b3); // [FALSE POSITIVE] + + sink(ss1.getline(b4, 1000, ' ')); + sink(ss2.getline(b5, 1000, ' ')); // tainted + sink(ss2.getline(b6, 1000, ' ')); // tainted + sink(ss1.getline(b6, 1000, ' ')); + sink(b4); + sink(b5); // tainted + sink(b6); // [FALSE POSITIVE] + + sink(ss2.getline(b7, 1000).getline(b8, 1000)); // tainted + sink(b7); // tainted + sink(b8); // tainted + + sink(getline(ss1, s1)); + sink(getline(ss2, s2)); // tainted + sink(getline(ss2, s3)); // tainted + sink(getline(ss1, s3)); + sink(s1); + sink(s2); // tainted + sink(s3); // [FALSE POSITIVE] + + sink(getline(ss1, s4, ' ')); + sink(getline(ss2, s5, ' ')); // tainted + sink(getline(ss2, s6, ' ')); // tainted + sink(getline(ss1, s6, ' ')); + sink(s4); + sink(s5); // tainted + sink(s6); // [FALSE POSITIVE] + + sink(getline(getline(ss2, s7), s8)); // tainted + sink(s7); // tainted + sink(s8); // tainted +} + +void test_chaining() +{ + std::stringstream ss1(source()); + std::stringstream ss2; + char b1[1000] = {0}; + char b2[1000] = {0}; + + sink(ss1.get(b1, 100).unget().get(b2, 100)); // tainted + sink(b1); // tainted + sink(b2); // tainted + + sink(ss2.write("abc", 3).flush().write(source(), 3).flush().write("xyz", 3)); // tainted + sink(ss2); // 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 25e0b950352f..69d57d3bab01 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -224,6 +224,33 @@ | stringstream.cpp:185:7:185:8 | c6 | stringstream.cpp:143:14:143:19 | call to source | | stringstream.cpp:196:10:196:16 | call to putback | stringstream.cpp:196:18:196:32 | call to source | | stringstream.cpp:197:10:197:12 | call to get | stringstream.cpp:196:18:196:32 | call to source | +| stringstream.cpp:215:11:215:17 | call to getline | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:216:11:216:17 | call to getline | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:219:7:219:8 | call to basic_string | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:220:7:220:8 | call to basic_string | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:223:11:223:17 | call to getline | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:224:11:224:17 | call to getline | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:227:7:227:8 | call to basic_string | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:228:7:228:8 | call to basic_string | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:230:29:230:35 | call to getline | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:231:7:231:8 | call to basic_string | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:232:7:232:8 | call to basic_string | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:235:7:235:13 | call to getline | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:236:7:236:13 | call to getline | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:239:7:239:8 | s2 | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:240:7:240:8 | s3 | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:243:7:243:13 | call to getline | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:244:7:244:13 | call to getline | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:247:7:247:8 | s5 | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:248:7:248:8 | s6 | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:250:7:250:13 | call to getline | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:251:7:251:8 | s7 | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:252:7:252:8 | s8 | stringstream.cpp:203:24:203:29 | call to source | +| stringstream.cpp:262:32:262:34 | call to get | stringstream.cpp:257:24:257:29 | call to source | +| stringstream.cpp:263:7:263:8 | call to basic_string | stringstream.cpp:257:24:257:29 | call to source | +| stringstream.cpp:264:7:264:8 | call to basic_string | stringstream.cpp:257:24:257:29 | call to source | +| stringstream.cpp:266:62:266:66 | call to write | stringstream.cpp:266:41:266:46 | call to source | +| stringstream.cpp:267:7:267:9 | ss2 | stringstream.cpp:266:41:266:46 | call to source | | structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source | | structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source | | structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29: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 f1b10f110228..1ada09c80812 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 @@ -226,6 +226,33 @@ | stringstream.cpp:185:7:185:8 | stringstream.cpp:143:14:143:19 | AST only | | stringstream.cpp:196:10:196:16 | stringstream.cpp:196:18:196:32 | AST only | | stringstream.cpp:197:10:197:12 | stringstream.cpp:196:18:196:32 | AST only | +| stringstream.cpp:215:11:215:17 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:216:11:216:17 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:219:7:219:8 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:220:7:220:8 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:223:11:223:17 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:224:11:224:17 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:227:7:227:8 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:228:7:228:8 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:230:29:230:35 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:231:7:231:8 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:232:7:232:8 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:235:7:235:13 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:236:7:236:13 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:239:7:239:8 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:240:7:240:8 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:243:7:243:13 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:244:7:244:13 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:247:7:247:8 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:248:7:248:8 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:250:7:250:13 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:251:7:251:8 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:252:7:252:8 | stringstream.cpp:203:24:203:29 | AST only | +| stringstream.cpp:262:32:262:34 | stringstream.cpp:257:24:257:29 | AST only | +| stringstream.cpp:263:7:263:8 | stringstream.cpp:257:24:257:29 | AST only | +| stringstream.cpp:264:7:264:8 | stringstream.cpp:257:24:257:29 | AST only | +| stringstream.cpp:266:62:266:66 | stringstream.cpp:266:41:266:46 | AST only | +| stringstream.cpp:267:7:267:9 | stringstream.cpp:266:41:266:46 | AST only | | swap1.cpp:78:12:78:16 | swap1.cpp:69:23:69:23 | AST only | | swap1.cpp:87:13:87:17 | swap1.cpp:82:16:82:21 | AST only | | swap1.cpp:88:13:88:17 | swap1.cpp:81:27:81:28 | AST only |