diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll index 6647dda4072a..d84dd49e1666 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -629,14 +629,25 @@ private predicate exprToExprStep_nocfg(Expr fromExpr, Expr toExpr) { // `ClassAggregateLiteral` (`{ capture1, ..., captureN }`). toExpr.(LambdaExpression).getInitializer() = fromExpr or + // Data flow through a function model. toExpr = any(Call call | - exists(DataFlowFunction f, FunctionInput inModel, FunctionOutput outModel, int iIn | - call.getTarget() = f and + exists(DataFlowFunction f, FunctionInput inModel, FunctionOutput outModel | f.hasDataFlow(inModel, outModel) and - outModel.isReturnValue() and - inModel.isParameter(iIn) and - fromExpr = call.getArgument(iIn) + ( + exists(int iIn | + inModel.isParameter(iIn) and + fromExpr = call.getArgument(iIn) + ) + or + inModel.isQualifierObject() and + fromExpr = call.getQualifier() + or + inModel.isQualifierAddress() and + fromExpr = call.getQualifier() + ) and + call.getTarget() = f and + outModel.isReturnValue() ) ) } 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 8d4fdd8700c7..f5fc470a42cb 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -296,10 +296,11 @@ class StdBasicOStream extends TemplateClass { } /** - * The `std::ostream` function `operator<<` (defined as a member function). + * The `std::ostream` functions `operator<<` (defined as a member function), + * `put` and `write`. */ class StdOStreamOut extends DataFlowFunction, TaintFunction { - StdOStreamOut() { this.hasQualifiedName("std", "basic_ostream", "operator<<") } + StdOStreamOut() { this.hasQualifiedName("std", "basic_ostream", ["operator<<", "put", "write"]) } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to return value @@ -308,14 +309,20 @@ class StdOStreamOut extends DataFlowFunction, TaintFunction { } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // flow from parameter to qualifier + // flow from first parameter (value or pointer) to qualifier input.isParameter(0) and output.isQualifierObject() or - // flow from parameter to return value + input.isParameterDeref(0) and + output.isQualifierObject() + or + // flow from first parameter (value or pointer) to return value input.isParameter(0) and output.isReturnValueDeref() or + input.isParameterDeref(0) and + output.isReturnValueDeref() + or // reverse flow from returned reference to the qualifier input.isReturnValueDeref() and output.isQualifierObject() @@ -352,3 +359,43 @@ class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction { output.isParameterDeref(0) } } + +/** + * Additional model for `std::stringstream` constructors that take a string + * input parameter. + */ +class StdStringStreamConstructor extends Constructor, TaintFunction { + StdStringStreamConstructor() { + this.getDeclaringType().hasQualifiedName("std", "basic_stringstream") + } + + /** + * Gets the index of a parameter to this function that is a string. + */ + int getAStringParameterIndex() { + getParameter(result).getType() instanceof ReferenceType // `const std::basic_string &` + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // taint flow from any parameter of string type to the returned object + input.isParameterDeref(getAStringParameterIndex()) and + output.isReturnValue() // TODO: this should be `isQualifierObject` by our current definitions, but that flow is not yet supported. + } +} + +/** + * The `std::stringstream` function `str`. + */ +class StdStringStreamStr extends TaintFunction { + StdStringStreamStr() { this.hasQualifiedName("std", "basic_stringstream", "str") } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from qualifier to return value (if any) + input.isQualifierObject() and + output.isReturnValue() + or + // flow from first parameter (if any) to qualifier + input.isParameterDeref(0) 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 08d0a3216390..ea4d5438614e 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -444,19 +444,19 @@ | standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:42:14:42:20 | source1 | | | standalone_iterators.cpp:40:11:40:17 | source1 | standalone_iterators.cpp:40:10:40:10 | call to operator* | TAINT | | standalone_iterators.cpp:41:12:41:18 | ref arg source1 | standalone_iterators.cpp:42:14:42:20 | source1 | | -| standalone_iterators.cpp:41:12:41:18 | source1 | standalone_iterators.cpp:41:19:41:19 | call to operator++ | TAINT | +| standalone_iterators.cpp:41:12:41:18 | source1 | standalone_iterators.cpp:41:19:41:19 | call to operator++ | | | standalone_iterators.cpp:41:19:41:19 | call to operator++ | standalone_iterators.cpp:41:10:41:10 | call to operator* | TAINT | | standalone_iterators.cpp:42:12:42:12 | call to operator++ | standalone_iterators.cpp:42:10:42:10 | call to operator* | TAINT | -| standalone_iterators.cpp:42:14:42:20 | source1 | standalone_iterators.cpp:42:12:42:12 | call to operator++ | TAINT | +| standalone_iterators.cpp:42:14:42:20 | source1 | standalone_iterators.cpp:42:12:42:12 | call to operator++ | | | standalone_iterators.cpp:45:39:45:45 | source1 | standalone_iterators.cpp:46:11:46:17 | source1 | | | standalone_iterators.cpp:45:39:45:45 | source1 | standalone_iterators.cpp:47:12:47:18 | source1 | | | standalone_iterators.cpp:45:39:45:45 | source1 | standalone_iterators.cpp:48:14:48:20 | source1 | | | standalone_iterators.cpp:46:11:46:17 | source1 | standalone_iterators.cpp:46:10:46:10 | call to operator* | TAINT | | standalone_iterators.cpp:47:12:47:18 | ref arg source1 | standalone_iterators.cpp:48:14:48:20 | source1 | | -| standalone_iterators.cpp:47:12:47:18 | source1 | standalone_iterators.cpp:47:19:47:19 | call to operator++ | TAINT | +| standalone_iterators.cpp:47:12:47:18 | source1 | standalone_iterators.cpp:47:19:47:19 | call to operator++ | | | standalone_iterators.cpp:47:19:47:19 | call to operator++ | standalone_iterators.cpp:47:10:47:10 | call to operator* | TAINT | | standalone_iterators.cpp:48:12:48:12 | call to operator++ | standalone_iterators.cpp:48:10:48:10 | call to operator* | TAINT | -| standalone_iterators.cpp:48:14:48:20 | source1 | standalone_iterators.cpp:48:12:48:12 | call to operator++ | TAINT | +| standalone_iterators.cpp:48:14:48:20 | source1 | standalone_iterators.cpp:48:12:48:12 | call to operator++ | | | standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:52:11:52:17 | source1 | | | 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 | | @@ -528,7 +528,7 @@ | string.cpp:119:16:119:24 | call to basic_string | string.cpp:124:50:124:50 | s | | | string.cpp:119:16:119:24 | call to basic_string | string.cpp:128:16:128:16 | s | | | string.cpp:120:15:120:15 | (__begin) | string.cpp:120:15:120:15 | call to operator* | TAINT | -| string.cpp:120:15:120:15 | (__begin) | string.cpp:120:15:120:15 | call to operator++ | TAINT | +| string.cpp:120:15:120:15 | (__begin) | string.cpp:120:15:120:15 | call to operator++ | | | string.cpp:120:15:120:15 | (__end) | string.cpp:120:15:120:15 | call to iterator | | | string.cpp:120:15:120:15 | (__range) | string.cpp:120:15:120:15 | call to begin | TAINT | | string.cpp:120:15:120:15 | (__range) | string.cpp:120:15:120:15 | call to end | TAINT | @@ -553,13 +553,13 @@ | string.cpp:124:50:124:50 | ref arg s | string.cpp:124:50:124:50 | s | | | string.cpp:124:50:124:50 | ref arg s | string.cpp:128:16:128:16 | s | | | string.cpp:124:50:124:50 | s | string.cpp:124:52:124:54 | call to end | TAINT | -| string.cpp:124:61:124:62 | it | string.cpp:124:59:124:59 | call to operator++ | TAINT | +| string.cpp:124:61:124:62 | it | string.cpp:124:59:124:59 | call to operator++ | | | string.cpp:124:61:124:62 | ref arg it | string.cpp:124:44:124:45 | it | | | string.cpp:124:61:124:62 | ref arg it | string.cpp:124:61:124:62 | it | | | string.cpp:124:61:124:62 | ref arg it | string.cpp:125:9:125:10 | it | | | string.cpp:125:9:125:10 | it | string.cpp:125:8:125:8 | call to operator* | TAINT | | string.cpp:128:16:128:16 | (__begin) | string.cpp:128:16:128:16 | call to operator* | TAINT | -| string.cpp:128:16:128:16 | (__begin) | string.cpp:128:16:128:16 | call to operator++ | TAINT | +| string.cpp:128:16:128:16 | (__begin) | string.cpp:128:16:128:16 | call to operator++ | | | string.cpp:128:16:128:16 | (__end) | string.cpp:128:16:128:16 | call to iterator | | | string.cpp:128:16:128:16 | (__range) | string.cpp:128:16:128:16 | call to begin | TAINT | | string.cpp:128:16:128:16 | (__range) | string.cpp:128:16:128:16 | call to end | TAINT | @@ -578,7 +578,7 @@ | string.cpp:132:28:132:33 | call to source | string.cpp:132:28:132:36 | call to basic_string | TAINT | | string.cpp:132:28:132:36 | call to basic_string | string.cpp:133:22:133:28 | const_s | | | string.cpp:133:22:133:22 | (__begin) | string.cpp:133:22:133:22 | call to operator* | TAINT | -| string.cpp:133:22:133:22 | (__begin) | string.cpp:133:22:133:22 | call to operator++ | TAINT | +| string.cpp:133:22:133:22 | (__begin) | string.cpp:133:22:133:22 | call to operator++ | | | string.cpp:133:22:133:22 | (__range) | string.cpp:133:22:133:22 | call to begin | TAINT | | string.cpp:133:22:133:22 | (__range) | string.cpp:133:22:133:22 | call to end | TAINT | | string.cpp:133:22:133:22 | call to begin | string.cpp:133:22:133:22 | (__begin) | | @@ -981,38 +981,38 @@ | string.cpp:396:8:396:9 | i2 | string.cpp:396:3:396:9 | ... = ... | | | string.cpp:396:8:396:9 | i2 | string.cpp:397:12:397:13 | i3 | | | string.cpp:397:10:397:10 | call to operator++ | string.cpp:397:8:397:8 | call to operator* | TAINT | -| string.cpp:397:12:397:13 | i3 | string.cpp:397:10:397:10 | call to operator++ | TAINT | +| string.cpp:397:12:397:13 | i3 | string.cpp:397:10:397:10 | call to operator++ | | | string.cpp:398:8:398:9 | i2 | string.cpp:398:3:398:9 | ... = ... | | | string.cpp:398:8:398:9 | i2 | string.cpp:399:12:399:13 | i4 | | | string.cpp:399:10:399:10 | call to operator-- | string.cpp:399:8:399:8 | call to operator* | TAINT | -| string.cpp:399:12:399:13 | i4 | string.cpp:399:10:399:10 | call to operator-- | TAINT | +| string.cpp:399:12:399:13 | i4 | string.cpp:399:10:399:10 | call to operator-- | | | string.cpp:400:8:400:9 | i2 | string.cpp:400:3:400:9 | ... = ... | | | string.cpp:400:8:400:9 | i2 | string.cpp:401:3:401:4 | i5 | | | string.cpp:400:8:400:9 | i2 | string.cpp:402:9:402:10 | i5 | | -| string.cpp:401:3:401:4 | i5 | string.cpp:401:5:401:5 | call to operator++ | TAINT | +| string.cpp:401:3:401:4 | i5 | string.cpp:401:5:401:5 | call to operator++ | | | string.cpp:401:3:401:4 | ref arg i5 | string.cpp:402:9:402:10 | i5 | | | string.cpp:402:9:402:10 | i5 | string.cpp:402:8:402:8 | call to operator* | TAINT | | string.cpp:403:8:403:9 | i2 | string.cpp:403:3:403:9 | ... = ... | | | string.cpp:403:8:403:9 | i2 | string.cpp:404:3:404:4 | i6 | | | string.cpp:403:8:403:9 | i2 | string.cpp:405:9:405:10 | i6 | | -| string.cpp:404:3:404:4 | i6 | string.cpp:404:5:404:5 | call to operator-- | TAINT | +| string.cpp:404:3:404:4 | i6 | string.cpp:404:5:404:5 | call to operator-- | | | string.cpp:404:3:404:4 | ref arg i6 | string.cpp:405:9:405:10 | i6 | | | string.cpp:405:9:405:10 | i6 | string.cpp:405:8:405:8 | call to operator* | TAINT | | string.cpp:406:8:406:9 | i2 | string.cpp:406:3:406:9 | ... = ... | | | string.cpp:406:8:406:9 | i2 | string.cpp:407:10:407:11 | i7 | | -| string.cpp:407:10:407:11 | i7 | string.cpp:407:12:407:12 | call to operator+= | TAINT | +| string.cpp:407:10:407:11 | i7 | string.cpp:407:12:407:12 | call to operator+= | | | string.cpp:407:12:407:12 | call to operator+= | string.cpp:407:8:407:8 | call to operator* | TAINT | | string.cpp:407:14:407:14 | 1 | string.cpp:407:12:407:12 | call to operator+= | | | string.cpp:408:8:408:9 | i2 | string.cpp:408:3:408:9 | ... = ... | | | string.cpp:408:8:408:9 | i2 | string.cpp:409:10:409:11 | i8 | | -| string.cpp:409:10:409:11 | i8 | string.cpp:409:12:409:12 | call to operator-= | TAINT | +| string.cpp:409:10:409:11 | i8 | string.cpp:409:12:409:12 | call to operator-= | | | string.cpp:409:12:409:12 | call to operator-= | string.cpp:409:8:409:8 | call to operator* | TAINT | | string.cpp:409:14:409:14 | 1 | string.cpp:409:12:409:12 | call to operator-= | | | string.cpp:411:8:411:9 | s2 | string.cpp:411:11:411:13 | call to end | TAINT | | string.cpp:411:11:411:13 | call to end | string.cpp:411:3:411:15 | ... = ... | | | string.cpp:411:11:411:13 | call to end | string.cpp:412:5:412:6 | i9 | | | string.cpp:411:11:411:13 | call to end | string.cpp:413:9:413:10 | i9 | | -| string.cpp:412:5:412:6 | i9 | string.cpp:412:3:412:3 | call to operator-- | TAINT | +| string.cpp:412:5:412:6 | i9 | string.cpp:412:3:412:3 | call to operator-- | | | string.cpp:412:5:412:6 | ref arg i9 | string.cpp:413:9:413:10 | i9 | | | string.cpp:413:9:413:10 | i9 | string.cpp:413:8:413:8 | call to operator* | TAINT | | string.cpp:419:17:419:20 | aa | string.cpp:419:17:419:21 | call to basic_string | TAINT | @@ -1425,22 +1425,69 @@ | stringstream.cpp:35:7:35:9 | ss5 | stringstream.cpp:35:11:35:11 | call to operator<< | | | stringstream.cpp:35:14:35:14 | t | stringstream.cpp:35:7:35:9 | ref arg ss5 | TAINT | | stringstream.cpp:35:14:35:14 | t | stringstream.cpp:35:11:35:11 | call to operator<< | TAINT | +| stringstream.cpp:42:7:42:9 | ss1 | stringstream.cpp:42:11:42:13 | call to str | TAINT | +| stringstream.cpp:43:7:43:9 | ss2 | stringstream.cpp:43:11:43:13 | call to str | TAINT | +| stringstream.cpp:44:7:44:9 | ss3 | stringstream.cpp:44:11:44:13 | call to str | TAINT | +| stringstream.cpp:45:7:45:9 | ss4 | stringstream.cpp:45:11:45:13 | call to str | TAINT | +| stringstream.cpp:46:7:46:9 | ss5 | stringstream.cpp:46:11:46:13 | call to str | TAINT | | stringstream.cpp:48:2:48:4 | ref arg ss6 | stringstream.cpp:49:2:49:4 | ss6 | | | stringstream.cpp:48:2:48:4 | ref arg ss6 | stringstream.cpp:52:7:52:9 | ss6 | | +| stringstream.cpp:48:2:48:4 | ss6 | stringstream.cpp:48:6:48:8 | call to str | TAINT | | stringstream.cpp:48:10:48:14 | abc | stringstream.cpp:48:10:48:14 | call to basic_string | TAINT | +| stringstream.cpp:48:10:48:14 | call to basic_string | stringstream.cpp:48:2:48:4 | ref arg ss6 | TAINT | | stringstream.cpp:49:2:49:4 | ref arg ss6 | stringstream.cpp:52:7:52:9 | ss6 | | +| stringstream.cpp:49:2:49:4 | ss6 | stringstream.cpp:49:6:49:8 | call to str | TAINT | | stringstream.cpp:49:10:49:15 | call to source | stringstream.cpp:49:10:49:17 | call to basic_string | TAINT | +| stringstream.cpp:49:10:49:17 | call to basic_string | stringstream.cpp:49:2:49:4 | ref arg ss6 | TAINT | | stringstream.cpp:50:2:50:4 | ref arg ss7 | stringstream.cpp:51:2:51:4 | ss7 | | | stringstream.cpp:50:2:50:4 | ref arg ss7 | stringstream.cpp:53:7:53:9 | ss7 | | +| stringstream.cpp:50:2:50:4 | ss7 | stringstream.cpp:50:6:50:8 | call to str | TAINT | | stringstream.cpp:50:10:50:15 | call to source | stringstream.cpp:50:10:50:17 | call to basic_string | TAINT | +| stringstream.cpp:50:10:50:17 | call to basic_string | stringstream.cpp:50:2:50:4 | ref arg ss7 | TAINT | | stringstream.cpp:51:2:51:4 | ref arg ss7 | stringstream.cpp:53:7:53:9 | ss7 | | +| stringstream.cpp:51:2:51:4 | ss7 | stringstream.cpp:51:6:51:8 | call to str | TAINT | | stringstream.cpp:51:10:51:14 | abc | stringstream.cpp:51:10:51:14 | call to basic_string | TAINT | +| stringstream.cpp:51:10:51:14 | call to basic_string | stringstream.cpp:51:2:51:4 | ref arg ss7 | TAINT | | stringstream.cpp:55:7:55:9 | ref arg ss8 | stringstream.cpp:58:7:58:9 | ss8 | | +| stringstream.cpp:55:7:55:9 | ss8 | stringstream.cpp:55:11:55:13 | call to put | | +| stringstream.cpp:55:15:55:17 | 97 | stringstream.cpp:55:7:55:9 | ref arg ss8 | TAINT | +| stringstream.cpp:55:15:55:17 | 97 | stringstream.cpp:55:11:55:13 | call to put | TAINT | | stringstream.cpp:56:7:56:9 | ref arg ss9 | stringstream.cpp:59:7:59:9 | ss9 | | +| stringstream.cpp:56:7:56:9 | ss9 | stringstream.cpp:56:11:56:13 | call to put | | +| stringstream.cpp:56:15:56:29 | call to source | stringstream.cpp:56:7:56:9 | ref arg ss9 | TAINT | +| stringstream.cpp:56:15:56:29 | call to source | stringstream.cpp:56:11:56:13 | call to put | TAINT | | stringstream.cpp:57:7:57:10 | ref arg ss10 | stringstream.cpp:60:7:60:10 | ss10 | | +| stringstream.cpp:57:7:57:10 | ss10 | stringstream.cpp:57:12:57:14 | call to put | | +| stringstream.cpp:57:12:57:14 | call to put | stringstream.cpp:57:21:57:23 | call to put | | +| stringstream.cpp:57:12:57:14 | ref arg call to put | stringstream.cpp:57:7:57:10 | ref arg ss10 | TAINT | +| stringstream.cpp:57:16:57:18 | 97 | stringstream.cpp:57:7:57:10 | ref arg ss10 | TAINT | +| stringstream.cpp:57:16:57:18 | 97 | stringstream.cpp:57:12:57:14 | call to put | TAINT | +| stringstream.cpp:57:21:57:23 | call to put | stringstream.cpp:57:44:57:46 | call to put | | +| stringstream.cpp:57:21:57:23 | ref arg call to put | stringstream.cpp:57:12:57:14 | ref arg call to put | TAINT | +| stringstream.cpp:57:25:57:39 | call to source | stringstream.cpp:57:12:57:14 | ref arg call to put | TAINT | +| stringstream.cpp:57:25:57:39 | call to source | stringstream.cpp:57:21:57:23 | call to put | TAINT | +| stringstream.cpp:57:48:57:50 | 122 | stringstream.cpp:57:21:57:23 | ref arg call to put | TAINT | +| stringstream.cpp:57:48:57:50 | 122 | stringstream.cpp:57:44:57:46 | call to put | TAINT | | stringstream.cpp:62:7:62:10 | ref arg ss11 | stringstream.cpp:65:7:65:10 | ss11 | | +| stringstream.cpp:62:7:62:10 | ss11 | stringstream.cpp:62:12:62:16 | call to write | | +| stringstream.cpp:62:18:62:24 | begin | stringstream.cpp:62:7:62:10 | ref arg ss11 | TAINT | +| stringstream.cpp:62:18:62:24 | begin | stringstream.cpp:62:12:62:16 | call to write | TAINT | | stringstream.cpp:63:7:63:10 | ref arg ss12 | stringstream.cpp:66:7:66:10 | ss12 | | +| stringstream.cpp:63:7:63:10 | ss12 | stringstream.cpp:63:12:63:16 | call to write | | +| stringstream.cpp:63:18:63:23 | call to source | stringstream.cpp:63:7:63:10 | ref arg ss12 | TAINT | +| stringstream.cpp:63:18:63:23 | call to source | stringstream.cpp:63:12:63:16 | call to write | TAINT | | stringstream.cpp:64:7:64:10 | ref arg ss13 | stringstream.cpp:67:7:67:10 | ss13 | | +| stringstream.cpp:64:7:64:10 | ss13 | stringstream.cpp:64:12:64:16 | call to write | | +| stringstream.cpp:64:12:64:16 | call to write | stringstream.cpp:64:30:64:34 | call to write | | +| stringstream.cpp:64:12:64:16 | ref arg call to write | stringstream.cpp:64:7:64:10 | ref arg ss13 | TAINT | +| stringstream.cpp:64:18:64:24 | begin | stringstream.cpp:64:7:64:10 | ref arg ss13 | TAINT | +| stringstream.cpp:64:18:64:24 | begin | stringstream.cpp:64:12:64:16 | call to write | TAINT | +| stringstream.cpp:64:30:64:34 | call to write | stringstream.cpp:64:54:64:58 | call to write | | +| stringstream.cpp:64:30:64:34 | ref arg call to write | stringstream.cpp:64:12:64:16 | ref arg call to write | TAINT | +| stringstream.cpp:64:36:64:41 | call to source | stringstream.cpp:64:12:64:16 | ref arg call to write | TAINT | +| stringstream.cpp:64:36:64:41 | call to source | stringstream.cpp:64:30:64:34 | call to write | TAINT | +| stringstream.cpp:64:60:64:64 | end | stringstream.cpp:64:30:64:34 | ref arg call to write | TAINT | +| stringstream.cpp:64:60:64:64 | end | stringstream.cpp:64:54:64:58 | call to write | TAINT | | stringstream.cpp:70:32:70:37 | source | stringstream.cpp:76:14:76:19 | source | | | stringstream.cpp:72:20:72:22 | call to basic_stringstream | stringstream.cpp:75:7:75:9 | ss1 | | | stringstream.cpp:72:20:72:22 | call to basic_stringstream | stringstream.cpp:77:7:77:9 | ss1 | | @@ -1457,11 +1504,13 @@ | stringstream.cpp:75:7:75:9 | ref arg ss1 | stringstream.cpp:77:7:77:9 | ss1 | | | stringstream.cpp:75:7:75:9 | ref arg ss1 | stringstream.cpp:80:7:80:9 | ss1 | | | stringstream.cpp:75:7:75:9 | ref arg ss1 | stringstream.cpp:82:7:82:9 | ss1 | | +| stringstream.cpp:75:7:75:9 | ss1 | stringstream.cpp:75:11:75:11 | call to operator<< | | | stringstream.cpp:75:14:75:17 | 1234 | stringstream.cpp:75:7:75:9 | ref arg ss1 | TAINT | | stringstream.cpp:75:14:75:17 | 1234 | stringstream.cpp:75:11:75:11 | call to operator<< | TAINT | | stringstream.cpp:76:7:76:9 | ref arg ss2 | stringstream.cpp:78:7:78:9 | ss2 | | | stringstream.cpp:76:7:76:9 | ref arg ss2 | stringstream.cpp:81:7:81:9 | ss2 | | | stringstream.cpp:76:7:76:9 | ref arg ss2 | stringstream.cpp:83:7:83:9 | ss2 | | +| stringstream.cpp:76:7:76:9 | ss2 | stringstream.cpp:76:11:76:11 | call to operator<< | | | stringstream.cpp:76:14:76:19 | source | stringstream.cpp:76:7:76:9 | ref arg ss2 | TAINT | | stringstream.cpp:76:14:76:19 | source | stringstream.cpp:76:11:76:11 | call to operator<< | TAINT | | stringstream.cpp:77:7:77:9 | ref arg ss1 | stringstream.cpp:80:7:80:9 | ss1 | | @@ -1470,16 +1519,22 @@ | stringstream.cpp:78:7:78:9 | ref arg ss2 | stringstream.cpp:81:7:81:9 | ss2 | | | stringstream.cpp:78:7:78:9 | ref arg ss2 | stringstream.cpp:83:7:83:9 | ss2 | | | stringstream.cpp:78:14:78:15 | ref arg v2 | stringstream.cpp:85:7:85:8 | v2 | | +| stringstream.cpp:82:7:82:9 | ss1 | stringstream.cpp:82:11:82:13 | call to str | TAINT | +| stringstream.cpp:83:7:83:9 | ss2 | stringstream.cpp:83:11:83:13 | call to str | TAINT | | stringstream.cpp:90:18:90:23 | call to basic_string | stringstream.cpp:92:24:92:25 | s1 | | | stringstream.cpp:90:19:90:23 | abc | stringstream.cpp:90:18:90:23 | call to basic_string | TAINT | | stringstream.cpp:91:18:91:26 | call to basic_string | stringstream.cpp:93:24:93:25 | s2 | | | stringstream.cpp:91:19:91:24 | call to source | stringstream.cpp:91:18:91:26 | call to basic_string | TAINT | +| stringstream.cpp:92:24:92:25 | s1 | stringstream.cpp:92:24:92:26 | call to basic_stringstream | TAINT | | stringstream.cpp:92:24:92:26 | call to basic_stringstream | stringstream.cpp:102:7:102:9 | ss1 | | +| stringstream.cpp:93:24:93:25 | s2 | stringstream.cpp:93:24:93:26 | call to basic_stringstream | TAINT | | stringstream.cpp:93:24:93:26 | call to basic_stringstream | stringstream.cpp:103:7:103:9 | ss2 | | | stringstream.cpp:94:25:94:49 | call to basic_stringstream | stringstream.cpp:104:7:104:9 | ss3 | | | stringstream.cpp:94:44:94:48 | abc | stringstream.cpp:94:44:94:48 | call to basic_string | TAINT | +| stringstream.cpp:94:44:94:48 | call to basic_string | stringstream.cpp:94:25:94:49 | call to basic_stringstream | TAINT | | stringstream.cpp:95:25:95:52 | call to basic_stringstream | stringstream.cpp:105:7:105:9 | ss4 | | | stringstream.cpp:95:44:95:49 | call to source | stringstream.cpp:95:44:95:51 | call to basic_string | TAINT | +| stringstream.cpp:95:44:95:51 | call to basic_string | stringstream.cpp:95:25:95:52 | call to basic_stringstream | TAINT | | stringstream.cpp:96:20:96:22 | call to basic_stringstream | stringstream.cpp:99:7:99:9 | ss5 | | | stringstream.cpp:96:20:96:22 | call to basic_stringstream | stringstream.cpp:106:7:106:9 | ss5 | | | stringstream.cpp:97:20:97:22 | call to basic_stringstream | stringstream.cpp:100:7:100:9 | ss6 | | @@ -1488,20 +1543,26 @@ | stringstream.cpp:99:13:99:36 | call to basic_stringstream | stringstream.cpp:99:7:99:9 | ref arg ss5 | TAINT | | stringstream.cpp:99:13:99:36 | call to basic_stringstream | stringstream.cpp:99:11:99:11 | call to operator= | TAINT | | stringstream.cpp:99:31:99:35 | abc | stringstream.cpp:99:31:99:35 | call to basic_string | TAINT | +| stringstream.cpp:99:31:99:35 | call to basic_string | stringstream.cpp:99:13:99:36 | call to basic_stringstream | TAINT | | stringstream.cpp:100:7:100:9 | ref arg ss6 | stringstream.cpp:107:7:107:9 | ss6 | | | stringstream.cpp:100:13:100:39 | call to basic_stringstream | stringstream.cpp:100:7:100:9 | ref arg ss6 | TAINT | | stringstream.cpp:100:13:100:39 | call to basic_stringstream | stringstream.cpp:100:11:100:11 | call to operator= | TAINT | | stringstream.cpp:100:31:100:36 | call to source | stringstream.cpp:100:31:100:38 | call to basic_string | TAINT | +| stringstream.cpp:100:31:100:38 | call to basic_string | stringstream.cpp:100:13:100:39 | call to basic_stringstream | TAINT | | stringstream.cpp:112:24:112:28 | abc | stringstream.cpp:112:24:112:28 | call to basic_string | TAINT | +| stringstream.cpp:112:24:112:28 | call to basic_string | stringstream.cpp:112:24:112:29 | call to basic_stringstream | TAINT | | stringstream.cpp:112:24:112:29 | call to basic_stringstream | stringstream.cpp:117:2:117:4 | ss1 | | | stringstream.cpp:112:24:112:29 | call to basic_stringstream | stringstream.cpp:120:7:120:9 | ss1 | | | stringstream.cpp:113:24:113:29 | call to source | stringstream.cpp:113:24:113:31 | call to basic_string | TAINT | +| stringstream.cpp:113:24:113:31 | call to basic_string | stringstream.cpp:113:24:113:32 | call to basic_stringstream | TAINT | | stringstream.cpp:113:24:113:32 | call to basic_stringstream | stringstream.cpp:117:11:117:13 | ss2 | | | stringstream.cpp:113:24:113:32 | call to basic_stringstream | stringstream.cpp:121:7:121:9 | ss2 | | | stringstream.cpp:114:24:114:28 | abc | stringstream.cpp:114:24:114:28 | call to basic_string | TAINT | +| stringstream.cpp:114:24:114:28 | call to basic_string | stringstream.cpp:114:24:114:29 | call to basic_stringstream | TAINT | | stringstream.cpp:114:24:114:29 | call to basic_stringstream | stringstream.cpp:118:11:118:13 | ss3 | | | stringstream.cpp:114:24:114:29 | call to basic_stringstream | stringstream.cpp:122:7:122:9 | ss3 | | | stringstream.cpp:115:24:115:29 | call to source | stringstream.cpp:115:24:115:31 | call to basic_string | TAINT | +| stringstream.cpp:115:24:115:31 | call to basic_string | stringstream.cpp:115:24:115:32 | call to basic_stringstream | TAINT | | stringstream.cpp:115:24:115:32 | call to basic_stringstream | stringstream.cpp:118:2:118:4 | ss4 | | | stringstream.cpp:115:24:115:32 | call to basic_stringstream | stringstream.cpp:123:7:123:9 | ss4 | | | stringstream.cpp:117:2:117:4 | ref arg ss1 | stringstream.cpp:120:7:120:9 | ss1 | | @@ -1712,6 +1773,9 @@ | stringstream.cpp:192:7:192:8 | ref arg ss | stringstream.cpp:195:7:195:8 | ss | | | stringstream.cpp:192:7:192:8 | ref arg ss | stringstream.cpp:196:7:196:8 | ss | | | stringstream.cpp:192:7:192:8 | ref arg ss | stringstream.cpp:197:7:197:8 | ss | | +| stringstream.cpp:192:7:192:8 | ss | stringstream.cpp:192:10:192:12 | call to put | | +| stringstream.cpp:192:14:192:16 | 97 | stringstream.cpp:192:7:192:8 | ref arg ss | TAINT | +| stringstream.cpp:192:14:192:16 | 97 | stringstream.cpp:192:10:192:12 | call to put | TAINT | | stringstream.cpp:193:7:193:8 | ref arg ss | stringstream.cpp:194:7:194:8 | ss | | | stringstream.cpp:193:7:193:8 | ref arg ss | stringstream.cpp:195:7:195:8 | ss | | | stringstream.cpp:193:7:193:8 | ref arg ss | stringstream.cpp:196:7:196:8 | ss | | @@ -2546,7 +2610,7 @@ | vector.cpp:17:21:17:33 | call to vector | vector.cpp:35:1:35:1 | v | | | vector.cpp:17:26:17:32 | source1 | vector.cpp:17:21:17:33 | call to vector | TAINT | | vector.cpp:19:14:19:14 | (__begin) | vector.cpp:19:14:19:14 | call to operator* | TAINT | -| vector.cpp:19:14:19:14 | (__begin) | vector.cpp:19:14:19:14 | call to operator++ | TAINT | +| vector.cpp:19:14:19:14 | (__begin) | vector.cpp:19:14:19:14 | call to operator++ | | | vector.cpp:19:14:19:14 | (__end) | vector.cpp:19:14:19:14 | call to iterator | | | vector.cpp:19:14:19:14 | (__range) | vector.cpp:19:14:19:14 | call to begin | TAINT | | vector.cpp:19:14:19:14 | (__range) | vector.cpp:19:14:19:14 | call to end | TAINT | @@ -2573,13 +2637,13 @@ | vector.cpp:23:55:23:55 | ref arg v | vector.cpp:27:15:27:15 | v | | | vector.cpp:23:55:23:55 | ref arg v | vector.cpp:35:1:35:1 | v | | | vector.cpp:23:55:23:55 | v | vector.cpp:23:57:23:59 | call to end | TAINT | -| vector.cpp:23:66:23:67 | it | vector.cpp:23:64:23:64 | call to operator++ | TAINT | +| vector.cpp:23:66:23:67 | it | vector.cpp:23:64:23:64 | call to operator++ | | | vector.cpp:23:66:23:67 | ref arg it | vector.cpp:23:49:23:50 | it | | | vector.cpp:23:66:23:67 | ref arg it | vector.cpp:23:66:23:67 | it | | | vector.cpp:23:66:23:67 | ref arg it | vector.cpp:24:9:24:10 | it | | | vector.cpp:24:9:24:10 | it | vector.cpp:24:8:24:8 | call to operator* | TAINT | | vector.cpp:27:15:27:15 | (__begin) | vector.cpp:27:15:27:15 | call to operator* | TAINT | -| vector.cpp:27:15:27:15 | (__begin) | vector.cpp:27:15:27:15 | call to operator++ | TAINT | +| vector.cpp:27:15:27:15 | (__begin) | vector.cpp:27:15:27:15 | call to operator++ | | | vector.cpp:27:15:27:15 | (__end) | vector.cpp:27:15:27:15 | call to iterator | | | vector.cpp:27:15:27:15 | (__range) | vector.cpp:27:15:27:15 | call to begin | TAINT | | vector.cpp:27:15:27:15 | (__range) | vector.cpp:27:15:27:15 | call to end | TAINT | @@ -2599,7 +2663,7 @@ | vector.cpp:31:33:31:45 | call to vector | vector.cpp:35:1:35:1 | const_v | | | vector.cpp:31:38:31:44 | source1 | vector.cpp:31:33:31:45 | call to vector | TAINT | | vector.cpp:32:21:32:21 | (__begin) | vector.cpp:32:21:32:21 | call to operator* | TAINT | -| vector.cpp:32:21:32:21 | (__begin) | vector.cpp:32:21:32:21 | call to operator++ | TAINT | +| vector.cpp:32:21:32:21 | (__begin) | vector.cpp:32:21:32:21 | call to operator++ | | | vector.cpp:32:21:32:21 | (__range) | vector.cpp:32:21:32:21 | call to begin | TAINT | | vector.cpp:32:21:32:21 | (__range) | vector.cpp:32:21:32:21 | call to end | TAINT | | vector.cpp:32:21:32:21 | call to begin | vector.cpp:32:21:32:21 | (__begin) | | @@ -3280,7 +3344,7 @@ | vector.cpp:251:11:251:15 | call to begin | vector.cpp:253:8:253:9 | i1 | | | vector.cpp:251:11:251:15 | call to begin | vector.cpp:255:13:255:14 | i1 | | | vector.cpp:251:11:251:15 | call to begin | vector.cpp:259:8:259:9 | i1 | | -| vector.cpp:252:3:252:4 | i1 | vector.cpp:252:5:252:5 | call to operator++ | TAINT | +| vector.cpp:252:3:252:4 | i1 | vector.cpp:252:5:252:5 | call to operator++ | | | vector.cpp:252:3:252:4 | ref arg i1 | vector.cpp:253:8:253:9 | i1 | | | vector.cpp:252:3:252:4 | ref arg i1 | vector.cpp:255:13:255:14 | i1 | | | vector.cpp:252:3:252:4 | ref arg i1 | vector.cpp:259:8:259:9 | i1 | | @@ -3288,7 +3352,7 @@ | vector.cpp:253:8:253:9 | i1 | vector.cpp:254:3:254:4 | i2 | | | vector.cpp:253:8:253:9 | i1 | vector.cpp:255:17:255:18 | i2 | | | vector.cpp:253:8:253:9 | i1 | vector.cpp:260:8:260:9 | i2 | | -| vector.cpp:254:3:254:4 | i2 | vector.cpp:254:5:254:5 | call to operator++ | TAINT | +| vector.cpp:254:3:254:4 | i2 | vector.cpp:254:5:254:5 | call to operator++ | | | vector.cpp:254:3:254:4 | ref arg i2 | vector.cpp:255:17:255:18 | i2 | | | vector.cpp:254:3:254:4 | ref arg i2 | vector.cpp:260:8:260:9 | i2 | | | vector.cpp:255:3:255:4 | ref arg v6 | vector.cpp:261:8:261:9 | v6 | | 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 e656277c5671..d9b35b4a9e4a 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp @@ -40,31 +40,31 @@ void test_stringstream_string(int amount) sink(ss4); // tainted sink(ss5); // tainted sink(ss1.str()); - sink(ss2.str()); // tainted [NOT DETECTED] - sink(ss3.str()); // tainted [NOT DETECTED] - sink(ss4.str()); // tainted [NOT DETECTED] - sink(ss5.str()); // tainted [NOT DETECTED] + sink(ss2.str()); // tainted + sink(ss3.str()); // tainted + sink(ss4.str()); // tainted + sink(ss5.str()); // tainted ss6.str("abc"); ss6.str(source()); // (overwrites) ss7.str(source()); ss7.str("abc"); // (overwrites) - sink(ss6); // tainted [NOT DETECTED] - sink(ss7); + sink(ss6); // tainted + sink(ss7); // [FALSE POSITIVE] sink(ss8.put('a')); - sink(ss9.put(ns_char::source())); // tainted [NOT DETECTED] - sink(ss10.put('a').put(ns_char::source()).put('z')); // tainted [NOT DETECTED] + sink(ss9.put(ns_char::source())); // tainted + sink(ss10.put('a').put(ns_char::source()).put('z')); // tainted sink(ss8); - sink(ss9); // tainted [NOT DETECTED] - sink(ss10); // tainted [NOT DETECTED] + sink(ss9); // tainted + sink(ss10); // tainted sink(ss11.write("begin", 5)); - sink(ss12.write(source(), 5)); // tainted [NOT DETECTED] - sink(ss13.write("begin", 5).write(source(), amount).write("end", 3)); // tainted [NOT DETECTED] + sink(ss12.write(source(), 5)); // tainted + sink(ss13.write("begin", 5).write(source(), amount).write("end", 3)); // tainted sink(ss11); - sink(ss12); // tainted [NOT DETECTED] - sink(ss13); // tainted [NOT DETECTED] + sink(ss12); // tainted + sink(ss13); // tainted } void test_stringstream_int(int source) @@ -80,7 +80,7 @@ void test_stringstream_int(int source) sink(ss1); sink(ss2); // tainted sink(ss1.str()); - sink(ss2.str()); // tainted [NOT DETECTED] + sink(ss2.str()); // tainted sink(v1); sink(v2); // tainted [NOT DETECTED] } @@ -97,14 +97,14 @@ void test_stringstream_constructors() std::stringstream ss6; sink(ss5 = std::stringstream("abc")); - sink(ss6 = std::stringstream(source())); // tainted [NOT DETECTED] + sink(ss6 = std::stringstream(source())); // tainted sink(ss1); - sink(ss2); // tainted [NOT DETECTED] + sink(ss2); // tainted sink(ss3); - sink(ss4); // tainted [NOT DETECTED] + sink(ss4); // tainted sink(ss5); - sink(ss6); // tainted [NOT DETECTED] + sink(ss6); // tainted } void test_stringstream_swap() @@ -118,9 +118,9 @@ void test_stringstream_swap() ss4.swap(ss3); sink(ss1); // tainted [NOT DETECTED] - sink(ss2); + sink(ss2); // [FALSE POSITIVE] sink(ss3); // tainted [NOT DETECTED] - sink(ss4); + sink(ss4); // [FALSE POSITIVE] } void test_stringstream_in() 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 7e0006fb3adf..4e8a7255feb4 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -164,8 +164,29 @@ | stringstream.cpp:39:7:39:9 | ss3 | stringstream.cpp:33:23:33:28 | call to source | | stringstream.cpp:40:7:40:9 | ss4 | stringstream.cpp:34:14:34:19 | call to source | | stringstream.cpp:41:7:41:9 | ss5 | stringstream.cpp:29:16:29:21 | call to source | +| stringstream.cpp:43:11:43:13 | call to str | stringstream.cpp:32:14:32:19 | call to source | +| stringstream.cpp:44:11:44:13 | call to str | stringstream.cpp:33:23:33:28 | call to source | +| stringstream.cpp:45:11:45:13 | call to str | stringstream.cpp:34:14:34:19 | call to source | +| stringstream.cpp:46:11:46:13 | call to str | stringstream.cpp:29:16:29:21 | call to source | +| stringstream.cpp:52:7:52:9 | ss6 | stringstream.cpp:49:10:49:15 | call to source | +| stringstream.cpp:53:7:53:9 | ss7 | stringstream.cpp:50:10:50:15 | call to source | +| stringstream.cpp:56:11:56:13 | call to put | stringstream.cpp:56:15:56:29 | call to source | +| stringstream.cpp:57:44:57:46 | call to put | stringstream.cpp:57:25:57:39 | call to source | +| stringstream.cpp:59:7:59:9 | ss9 | stringstream.cpp:56:15:56:29 | call to source | +| stringstream.cpp:60:7:60:10 | ss10 | stringstream.cpp:57:25:57:39 | call to source | +| stringstream.cpp:63:12:63:16 | call to write | stringstream.cpp:63:18:63:23 | call to source | +| stringstream.cpp:64:54:64:58 | call to write | stringstream.cpp:64:36:64:41 | call to source | +| stringstream.cpp:66:7:66:10 | ss12 | stringstream.cpp:63:18:63:23 | call to source | +| stringstream.cpp:67:7:67:10 | ss13 | stringstream.cpp:64:36:64:41 | call to source | | stringstream.cpp:76:11:76:11 | call to operator<< | stringstream.cpp:70:32:70:37 | source | | stringstream.cpp:81:7:81:9 | ss2 | stringstream.cpp:70:32:70:37 | source | +| stringstream.cpp:83:11:83:13 | call to str | stringstream.cpp:70:32:70:37 | source | +| stringstream.cpp:100:11:100:11 | call to operator= | stringstream.cpp:100:31:100:36 | call to source | +| stringstream.cpp:103:7:103:9 | ss2 | stringstream.cpp:91:19:91:24 | call to source | +| stringstream.cpp:105:7:105:9 | ss4 | stringstream.cpp:95:44:95:49 | call to source | +| stringstream.cpp:107:7:107:9 | ss6 | stringstream.cpp:100:31:100:36 | call to source | +| stringstream.cpp:121:7:121:9 | ss2 | stringstream.cpp:113:24:113:29 | call to source | +| stringstream.cpp:123:7:123:9 | ss4 | stringstream.cpp:115:24:115:29 | call to source | | stringstream.cpp:143:11:143:11 | call to operator<< | stringstream.cpp:143:14:143:19 | 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 | 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 6c497b79e1e3..bc4213cb3dfb 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 @@ -180,8 +180,29 @@ | stringstream.cpp:39:7:39:9 | stringstream.cpp:33:23:33:28 | AST only | | stringstream.cpp:40:7:40:9 | stringstream.cpp:34:14:34:19 | AST only | | stringstream.cpp:41:7:41:9 | stringstream.cpp:29:16:29:21 | AST only | +| stringstream.cpp:43:11:43:13 | stringstream.cpp:32:14:32:19 | AST only | +| stringstream.cpp:44:11:44:13 | stringstream.cpp:33:23:33:28 | AST only | +| stringstream.cpp:45:11:45:13 | stringstream.cpp:34:14:34:19 | AST only | +| stringstream.cpp:46:11:46:13 | stringstream.cpp:29:16:29:21 | AST only | +| stringstream.cpp:52:7:52:9 | stringstream.cpp:49:10:49:15 | AST only | +| stringstream.cpp:53:7:53:9 | stringstream.cpp:50:10:50:15 | AST only | +| stringstream.cpp:56:11:56:13 | stringstream.cpp:56:15:56:29 | AST only | +| stringstream.cpp:57:44:57:46 | stringstream.cpp:57:25:57:39 | AST only | +| stringstream.cpp:59:7:59:9 | stringstream.cpp:56:15:56:29 | AST only | +| stringstream.cpp:60:7:60:10 | stringstream.cpp:57:25:57:39 | AST only | +| stringstream.cpp:63:12:63:16 | stringstream.cpp:63:18:63:23 | AST only | +| stringstream.cpp:64:54:64:58 | stringstream.cpp:64:36:64:41 | AST only | +| stringstream.cpp:66:7:66:10 | stringstream.cpp:63:18:63:23 | AST only | +| stringstream.cpp:67:7:67:10 | stringstream.cpp:64:36:64:41 | AST only | | stringstream.cpp:76:11:76:11 | stringstream.cpp:70:32:70:37 | AST only | | stringstream.cpp:81:7:81:9 | stringstream.cpp:70:32:70:37 | AST only | +| stringstream.cpp:83:11:83:13 | stringstream.cpp:70:32:70:37 | AST only | +| stringstream.cpp:100:11:100:11 | stringstream.cpp:100:31:100:36 | AST only | +| stringstream.cpp:103:7:103:9 | stringstream.cpp:91:19:91:24 | AST only | +| stringstream.cpp:105:7:105:9 | stringstream.cpp:95:44:95:49 | AST only | +| stringstream.cpp:107:7:107:9 | stringstream.cpp:100:31:100:36 | AST only | +| stringstream.cpp:121:7:121:9 | stringstream.cpp:113:24:113:29 | AST only | +| stringstream.cpp:123:7:123:9 | stringstream.cpp:115:24:115:29 | AST only | | stringstream.cpp:143:11:143:11 | stringstream.cpp:143:14:143:21 | IR only | | stringstream.cpp:143:11:143:22 | stringstream.cpp:143:14:143:19 | IR only | | stringstream.cpp:143:11:143:22 | stringstream.cpp:143:14:143:21 | IR only |