From fde6227fb62a11bb580b869f7757e65fc1408fbc Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 18 Jul 2019 17:48:38 +0100 Subject: [PATCH 01/10] CPP: Add taint tests for std::string etc. --- .../dataflow/taint-tests/localTaint.expected | 26 ++++++ .../dataflow/taint-tests/stl.cpp | 92 +++++++++++++++++++ .../dataflow/taint-tests/taint.expected | 1 + .../dataflow/taint-tests/test_ir.expected | 1 + 4 files changed, 120 insertions(+) create mode 100644 cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp 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 ab23866fe0e6..3b448596cb84 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -1,3 +1,29 @@ +| stl.cpp:63:12:63:17 | call to source | stl.cpp:67:7:67:7 | a | | +| stl.cpp:64:16:64:21 | call to basic_string | stl.cpp:68:7:68:7 | b | | +| stl.cpp:64:16:64:21 | call to basic_string | stl.cpp:70:7:70:7 | b | | +| stl.cpp:65:16:65:24 | call to basic_string | stl.cpp:69:7:69:7 | c | | +| stl.cpp:65:16:65:24 | call to basic_string | stl.cpp:71:7:71:7 | c | | +| stl.cpp:76:20:76:22 | call to basic_stringstream | stl.cpp:79:2:79:4 | ss1 | | +| stl.cpp:76:20:76:22 | call to basic_stringstream | stl.cpp:84:7:84:9 | ss1 | | +| stl.cpp:76:20:76:22 | call to basic_stringstream | stl.cpp:88:7:88:9 | ss1 | | +| stl.cpp:76:25:76:27 | call to basic_stringstream | stl.cpp:80:2:80:4 | ss2 | | +| stl.cpp:76:25:76:27 | call to basic_stringstream | stl.cpp:85:7:85:9 | ss2 | | +| stl.cpp:76:25:76:27 | call to basic_stringstream | stl.cpp:89:7:89:9 | ss2 | | +| stl.cpp:76:30:76:32 | call to basic_stringstream | stl.cpp:81:2:81:4 | ss3 | | +| stl.cpp:76:30:76:32 | call to basic_stringstream | stl.cpp:86:7:86:9 | ss3 | | +| stl.cpp:76:30:76:32 | call to basic_stringstream | stl.cpp:90:7:90:9 | ss3 | | +| stl.cpp:76:35:76:37 | call to basic_stringstream | stl.cpp:82:2:82:4 | ss4 | | +| stl.cpp:76:35:76:37 | call to basic_stringstream | stl.cpp:87:7:87:9 | ss4 | | +| stl.cpp:76:35:76:37 | call to basic_stringstream | stl.cpp:91:7:91:9 | ss4 | | +| stl.cpp:77:16:77:24 | call to basic_string | stl.cpp:82:9:82:9 | t | | +| stl.cpp:79:2:79:4 | ref arg ss1 | stl.cpp:84:7:84:9 | ss1 | | +| stl.cpp:79:2:79:4 | ref arg ss1 | stl.cpp:88:7:88:9 | ss1 | | +| stl.cpp:80:2:80:4 | ref arg ss2 | stl.cpp:85:7:85:9 | ss2 | | +| stl.cpp:80:2:80:4 | ref arg ss2 | stl.cpp:89:7:89:9 | ss2 | | +| stl.cpp:81:2:81:4 | ref arg ss3 | stl.cpp:86:7:86:9 | ss3 | | +| stl.cpp:81:2:81:4 | ref arg ss3 | stl.cpp:90:7:90:9 | ss3 | | +| stl.cpp:82:2:82:4 | ref arg ss4 | stl.cpp:87:7:87:9 | ss4 | | +| stl.cpp:82:2:82:4 | ref arg ss4 | stl.cpp:91:7:91:9 | ss4 | | | taint.cpp:4:27:4:33 | source1 | taint.cpp:6:13:6:19 | source1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:5:8:5:13 | clean1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:6:3:6:8 | clean1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp new file mode 100644 index 000000000000..9354313270bc --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -0,0 +1,92 @@ + +char *source(); +void sink(...) {}; + +typedef unsigned long size_t; + +namespace std +{ + template struct char_traits; + + typedef size_t streamsize; + + template class allocator { + public: + allocator() throw(); + }; + + template, class Allocator = allocator > + class basic_string { + public: + explicit basic_string(const Allocator& a = Allocator()); + basic_string(const charT* s, const Allocator& a = Allocator()); + + const charT* c_str() const; + }; + + typedef basic_string string; + + template > + class basic_istream /*: virtual public basic_ios - not needed for this test */ { + public: + basic_istream& operator>>(int& n); + }; + + template > + class basic_ostream /*: virtual public basic_ios - not needed for this test */ { + public: + typedef charT char_type; + basic_ostream& write(const char_type* s, streamsize n); + }; + + template basic_ostream& operator<<(basic_ostream&, const charT*); + template basic_ostream& operator<<(basic_ostream& os, const basic_string& str); + + template> + class basic_iostream : public basic_istream, public basic_ostream { + public: + }; + + template, class Allocator = allocator> + class basic_stringstream : public basic_iostream { + public: + explicit basic_stringstream(/*ios_base::openmode which = ios_base::out|ios_base::in - not needed for this test*/); + + basic_string str() const; + }; + + using stringstream = basic_stringstream; +} + +void test_string() +{ + char *a = source(); // * source -> sink causes the issue. + std::string b("123"); + std::string c(source()); + + sink(a); // tainted + sink(b); + sink(c); // tainted [NOT DETECTED] + sink(b.c_str()); + sink(c.c_str()); // tainted [NOT DETECTED] +} + +void test_stringstream() +{ + std::stringstream ss1, ss2, ss3, ss4; + std::string t(source()); + + ss1 << "1234"; + ss2 << source(); + ss3 << "123" << source(); + ss4 << t; + + sink(ss1); + sink(ss2); // tainted [NOT DETECTED] + sink(ss3); // tainted [NOT DETECTED] + sink(ss4); // tainted [NOT DETECTED] + sink(ss1.str()); + sink(ss2.str()); // tainted [NOT DETECTED] + sink(ss3.str()); // tainted [NOT DETECTED] + sink(ss4.str()); // tainted [NOT DETECTED] +} 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 0793bf29e199..915df921481b 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -1,3 +1,4 @@ +| stl.cpp:67:7:67:7 | a | stl.cpp:63:12:63:17 | call to source | | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected index b08cc19d0dfa..b6bde0ee9f9b 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected @@ -1,3 +1,4 @@ +| stl.cpp:67:7:67:7 | Load: a | stl.cpp:63:12:63:17 | Call: call to source | | taint.cpp:8:8:8:13 | Load: clean1 | taint.cpp:4:27:4:33 | InitializeParameter: source1 | | taint.cpp:16:8:16:14 | Load: source1 | taint.cpp:12:22:12:27 | Call: call to source | | taint.cpp:17:8:17:16 | Add: ++ ... | taint.cpp:12:22:12:27 | Call: call to source | From 0cabc3a9fb873ae364e1e78e145132050e877e1a Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 24 Jul 2019 17:44:01 +0100 Subject: [PATCH 02/10] CPP: Add models for std::string. --- cpp/ql/src/semmle/code/cpp/models/Models.qll | 1 + .../cpp/models/implementations/Strings.qll | 32 +++++++++++++++++++ .../dataflow/taint-tests/localTaint.expected | 3 ++ .../dataflow/taint-tests/stl.cpp | 2 +- .../dataflow/taint-tests/taint.expected | 1 + .../dataflow/taint-tests/test_diff.expected | 1 + 6 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll diff --git a/cpp/ql/src/semmle/code/cpp/models/Models.qll b/cpp/ql/src/semmle/code/cpp/models/Models.qll index 0747b00c48df..33d849271f00 100644 --- a/cpp/ql/src/semmle/code/cpp/models/Models.qll +++ b/cpp/ql/src/semmle/code/cpp/models/Models.qll @@ -6,4 +6,5 @@ private import implementations.Pure private import implementations.Strcat private import implementations.Strcpy private import implementations.Strftime +private import implementations.Strings private import implementations.Swap diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll new file mode 100644 index 000000000000..5d82f244af46 --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll @@ -0,0 +1,32 @@ +import semmle.code.cpp.models.interfaces.DataFlow +import semmle.code.cpp.models.interfaces.Taint + +/** + * The `std::basic_string` constructor(s). + */ +class StringConstructor extends DataFlowFunction { + StringConstructor() { + this.hasQualifiedName("std", "basic_string", "basic_string") + } + + override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { + // flow from any constructor argument to return value + input.isInParameter(_) and + output.isOutReturnValue() + } +} + +/** + * The standard function `std::string.c_str`. + */ +class StringCStr extends DataFlowFunction { + StringCStr() { + this.hasQualifiedName("std", "basic_string", "c_str") + } + + override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { + // flow from string itself (qualifier) to return value + input.isInQualifier() and + output.isOutReturnValue() + } +} 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 3b448596cb84..495613800d3c 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -1,6 +1,8 @@ | stl.cpp:63:12:63:17 | call to source | stl.cpp:67:7:67:7 | a | | +| stl.cpp:64:16:64:20 | 123 | stl.cpp:64:16:64:21 | call to basic_string | | | stl.cpp:64:16:64:21 | call to basic_string | stl.cpp:68:7:68:7 | b | | | stl.cpp:64:16:64:21 | call to basic_string | stl.cpp:70:7:70:7 | b | | +| stl.cpp:65:16:65:21 | call to source | stl.cpp:65:16:65:24 | call to basic_string | | | stl.cpp:65:16:65:24 | call to basic_string | stl.cpp:69:7:69:7 | c | | | stl.cpp:65:16:65:24 | call to basic_string | stl.cpp:71:7:71:7 | c | | | stl.cpp:76:20:76:22 | call to basic_stringstream | stl.cpp:79:2:79:4 | ss1 | | @@ -15,6 +17,7 @@ | stl.cpp:76:35:76:37 | call to basic_stringstream | stl.cpp:82:2:82:4 | ss4 | | | stl.cpp:76:35:76:37 | call to basic_stringstream | stl.cpp:87:7:87:9 | ss4 | | | stl.cpp:76:35:76:37 | call to basic_stringstream | stl.cpp:91:7:91:9 | ss4 | | +| stl.cpp:77:16:77:21 | call to source | stl.cpp:77:16:77:24 | call to basic_string | | | stl.cpp:77:16:77:24 | call to basic_string | stl.cpp:82:9:82:9 | t | | | stl.cpp:79:2:79:4 | ref arg ss1 | stl.cpp:84:7:84:9 | ss1 | | | stl.cpp:79:2:79:4 | ref arg ss1 | stl.cpp:88:7:88:9 | ss1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index 9354313270bc..6b40bd291fba 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -66,7 +66,7 @@ void test_string() sink(a); // tainted sink(b); - sink(c); // tainted [NOT DETECTED] + sink(c); // tainted sink(b.c_str()); sink(c.c_str()); // tainted [NOT DETECTED] } 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 915df921481b..c6bbfc5ccbf6 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -1,4 +1,5 @@ | stl.cpp:67:7:67:7 | a | stl.cpp:63:12:63:17 | call to source | +| stl.cpp:69:7:69:7 | c | stl.cpp:65:16:65:21 | call to source | | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12: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 45798f7ef062..9dfdde7ae469 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 @@ -1,3 +1,4 @@ +| stl.cpp:69:7:69:7 | stl.cpp:65:16:65:21 | AST only | | taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only | From 2cd6aa7dae369cecdd3c09dbfc3ec10c4bcc2d68 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 24 Jul 2019 17:54:11 +0100 Subject: [PATCH 03/10] CPP: Permit data flow from qualifier to return value. --- .../cpp/dataflow/internal/DataFlowUtil.qll | 21 ++++++++++++------- .../dataflow/taint-tests/localTaint.expected | 4 ++++ .../dataflow/taint-tests/stl.cpp | 2 +- .../dataflow/taint-tests/taint.expected | 1 + .../dataflow/taint-tests/test_diff.expected | 1 + 5 files changed, 21 insertions(+), 8 deletions(-) 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 13f5db09b6c8..350d42170aeb 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -545,15 +545,22 @@ private predicate exprToExprStep_nocfg(Expr fromExpr, Expr toExpr) { // `ClassAggregateLiteral` (`{ capture1, ..., captureN }`). toExpr.(LambdaExpression).getInitializer() = fromExpr or - toExpr = any(Call call | - exists(DataFlowFunction f, FunctionInput inModel, FunctionOutput outModel, int iIn | - call.getTarget() = f and - f.hasDataFlow(inModel, outModel) and - outModel.isOutReturnValue() and - inModel.isInParameter(iIn) and - fromExpr = call.getArgument(iIn) + exists(Call call, DataFlowFunction f, FunctionInput inModel, FunctionOutput outModel | + call.getTarget() = f and + f.hasDataFlow(inModel, outModel) and + ( + exists(int argInIndex | + inModel.isInParameter(argInIndex) and + fromExpr = call.getArgument(argInIndex) + ) or ( + inModel.isInQualifier() and + fromExpr = call.getQualifier() ) + ) and ( + outModel.isOutReturnValue() and + toExpr = call ) + ) } private predicate exprToDefinitionByReferenceStep(Expr exprIn, Expr argOut) { 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 495613800d3c..7624de35c431 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -5,6 +5,10 @@ | stl.cpp:65:16:65:21 | call to source | stl.cpp:65:16:65:24 | call to basic_string | | | stl.cpp:65:16:65:24 | call to basic_string | stl.cpp:69:7:69:7 | c | | | stl.cpp:65:16:65:24 | call to basic_string | stl.cpp:71:7:71:7 | c | | +| stl.cpp:70:7:70:7 | b | stl.cpp:70:9:70:13 | call to c_str | | +| stl.cpp:70:7:70:7 | b [post update] | stl.cpp:70:9:70:13 | call to c_str | | +| stl.cpp:71:7:71:7 | c | stl.cpp:71:9:71:13 | call to c_str | | +| stl.cpp:71:7:71:7 | c [post update] | stl.cpp:71:9:71:13 | call to c_str | | | stl.cpp:76:20:76:22 | call to basic_stringstream | stl.cpp:79:2:79:4 | ss1 | | | stl.cpp:76:20:76:22 | call to basic_stringstream | stl.cpp:84:7:84:9 | ss1 | | | stl.cpp:76:20:76:22 | call to basic_stringstream | stl.cpp:88:7:88:9 | ss1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index 6b40bd291fba..103f33314a36 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -68,7 +68,7 @@ void test_string() sink(b); sink(c); // tainted sink(b.c_str()); - sink(c.c_str()); // tainted [NOT DETECTED] + sink(c.c_str()); // tainted } void test_stringstream() 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 c6bbfc5ccbf6..d042069ebe28 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -1,5 +1,6 @@ | stl.cpp:67:7:67:7 | a | stl.cpp:63:12:63:17 | call to source | | stl.cpp:69:7:69:7 | c | stl.cpp:65:16:65:21 | call to source | +| stl.cpp:71:9:71:13 | call to c_str | stl.cpp:65:16:65:21 | call to source | | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12: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 9dfdde7ae469..4c92530a2651 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 @@ -1,4 +1,5 @@ | stl.cpp:69:7:69:7 | stl.cpp:65:16:65:21 | AST only | +| stl.cpp:71:9:71:13 | stl.cpp:65:16:65:21 | AST only | | taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only | From afcedcf7db44547d7af5fabe19eee8425fa7a5ab Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 24 Jul 2019 18:25:41 +0100 Subject: [PATCH 04/10] CPP: Add models for stringstream. --- .../cpp/models/implementations/Strings.qll | 36 +++++++++++++++++++ .../dataflow/taint-tests/localTaint.expected | 4 +++ .../dataflow/taint-tests/stl.cpp | 4 +-- .../dataflow/taint-tests/taint.expected | 2 ++ .../dataflow/taint-tests/test_diff.expected | 2 ++ 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll index 5d82f244af46..df6459acda91 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll @@ -30,3 +30,39 @@ class StringCStr extends DataFlowFunction { output.isOutReturnValue() } } + +/** + * The standard function `operator<<`, for example on `std::stringstream`. + */ +class InsertionOperator extends TaintFunction { + InsertionOperator() { + this.hasQualifiedName("std", "operator<<") + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + ( + // flow from second argument to first + input.isInParameterPointer(1) and + output.isOutParameterPointer(0) + ) or ( + // flow from first argument to return value + input.isInParameterPointer(0) and + output.isOutReturnValue() + ) + } +} + +/** + * The standard function `std::stringstream.str`. + */ +class StringStreamStr extends TaintFunction { + StringStreamStr() { + this.hasQualifiedName("std", "basic_stringstream", "str") + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from object itself (qualifier) to return value + input.isInQualifier() and + output.isOutReturnValue() + } +} 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 7624de35c431..dad73c3a09f8 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -25,12 +25,16 @@ | stl.cpp:77:16:77:24 | call to basic_string | stl.cpp:82:9:82:9 | t | | | stl.cpp:79:2:79:4 | ref arg ss1 | stl.cpp:84:7:84:9 | ss1 | | | stl.cpp:79:2:79:4 | ref arg ss1 | stl.cpp:88:7:88:9 | ss1 | | +| stl.cpp:79:9:79:14 | 1234 | stl.cpp:79:2:79:4 | ref arg ss1 | TAINT | | stl.cpp:80:2:80:4 | ref arg ss2 | stl.cpp:85:7:85:9 | ss2 | | | stl.cpp:80:2:80:4 | ref arg ss2 | stl.cpp:89:7:89:9 | ss2 | | +| stl.cpp:80:9:80:14 | call to source | stl.cpp:80:2:80:4 | ref arg ss2 | TAINT | | stl.cpp:81:2:81:4 | ref arg ss3 | stl.cpp:86:7:86:9 | ss3 | | | stl.cpp:81:2:81:4 | ref arg ss3 | stl.cpp:90:7:90:9 | ss3 | | +| stl.cpp:81:9:81:13 | 123 | stl.cpp:81:2:81:4 | ref arg ss3 | TAINT | | stl.cpp:82:2:82:4 | ref arg ss4 | stl.cpp:87:7:87:9 | ss4 | | | stl.cpp:82:2:82:4 | ref arg ss4 | stl.cpp:91:7:91:9 | ss4 | | +| stl.cpp:82:9:82:9 | t | stl.cpp:82:2:82:4 | ref arg ss4 | TAINT | | taint.cpp:4:27:4:33 | source1 | taint.cpp:6:13:6:19 | source1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:5:8:5:13 | clean1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:6:3:6:8 | clean1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index 103f33314a36..4cd3b166d4f6 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -82,9 +82,9 @@ void test_stringstream() ss4 << t; sink(ss1); - sink(ss2); // tainted [NOT DETECTED] + sink(ss2); // tainted sink(ss3); // tainted [NOT DETECTED] - sink(ss4); // tainted [NOT DETECTED] + sink(ss4); // tainted sink(ss1.str()); sink(ss2.str()); // tainted [NOT DETECTED] sink(ss3.str()); // tainted [NOT DETECTED] 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 d042069ebe28..26a0683ca090 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -1,6 +1,8 @@ | stl.cpp:67:7:67:7 | a | stl.cpp:63:12:63:17 | call to source | | stl.cpp:69:7:69:7 | c | stl.cpp:65:16:65:21 | call to source | | stl.cpp:71:9:71:13 | call to c_str | stl.cpp:65:16:65:21 | call to source | +| stl.cpp:85:7:85:9 | ss2 | stl.cpp:80:9:80:14 | call to source | +| stl.cpp:87:7:87:9 | ss4 | stl.cpp:77:16:77:21 | call to source | | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12: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 4c92530a2651..703173d64ceb 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 @@ -1,5 +1,7 @@ | stl.cpp:69:7:69:7 | stl.cpp:65:16:65:21 | AST only | | stl.cpp:71:9:71:13 | stl.cpp:65:16:65:21 | AST only | +| stl.cpp:85:7:85:9 | stl.cpp:80:9:80:14 | AST only | +| stl.cpp:87:7:87:9 | stl.cpp:77:16:77:21 | AST only | | taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only | From 23167c454c43a135a4fc10ea61388487ed26265c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 25 Jul 2019 12:06:42 +0100 Subject: [PATCH 05/10] CPP: Test to make models more visible. --- .../dataflow/taint-tests/models.expected | 38 +++++++++++++++++++ .../dataflow/taint-tests/models.ql | 19 ++++++++++ 2 files changed, 57 insertions(+) create mode 100644 cpp/ql/test/library-tests/dataflow/taint-tests/models.expected create mode 100644 cpp/ql/test/library-tests/dataflow/taint-tests/models.ql diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/models.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/models.expected new file mode 100644 index 000000000000..b52ccc352894 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/models.expected @@ -0,0 +1,38 @@ +| stl.cpp:64:16:64:21 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 0 | OutReturnValue | +| stl.cpp:64:16:64:21 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 1 | OutReturnValue | +| stl.cpp:64:16:64:21 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 2 | OutReturnValue | +| stl.cpp:65:16:65:24 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 0 | OutReturnValue | +| stl.cpp:65:16:65:24 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 1 | OutReturnValue | +| stl.cpp:65:16:65:24 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 2 | OutReturnValue | +| stl.cpp:70:9:70:13 | call to c_str | stl.cpp:24:16:24:20 | c_str | dataflow | InQualifier | OutReturnValue | +| stl.cpp:71:9:71:13 | call to c_str | stl.cpp:24:16:24:20 | c_str | dataflow | InQualifier | OutReturnValue | +| stl.cpp:77:16:77:24 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 0 | OutReturnValue | +| stl.cpp:77:16:77:24 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 1 | OutReturnValue | +| stl.cpp:77:16:77:24 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 2 | OutReturnValue | +| stl.cpp:79:6:79:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 0 | OutReturnValue | +| stl.cpp:79:6:79:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 1 | OutParameterPointer 0 | +| stl.cpp:80:6:80:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 0 | OutReturnValue | +| stl.cpp:80:6:80:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 1 | OutParameterPointer 0 | +| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 0 | OutReturnValue | +| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 1 | OutParameterPointer 0 | +| stl.cpp:81:15:81:15 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 0 | OutReturnValue | +| stl.cpp:81:15:81:15 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 1 | OutParameterPointer 0 | +| stl.cpp:82:6:82:6 | call to operator<< | stl.cpp:43:85:43:94 | operator<< | taint | InParameterPointer 0 | OutReturnValue | +| stl.cpp:82:6:82:6 | call to operator<< | stl.cpp:43:85:43:94 | operator<< | taint | InParameterPointer 1 | OutParameterPointer 0 | +| stl.cpp:88:11:88:13 | call to str | stl.cpp:55:42:55:44 | str | taint | InQualifier | OutReturnValue | +| stl.cpp:89:11:89:13 | call to str | stl.cpp:55:42:55:44 | str | taint | InQualifier | OutReturnValue | +| stl.cpp:90:11:90:13 | call to str | stl.cpp:55:42:55:44 | str | taint | InQualifier | OutReturnValue | +| stl.cpp:91:11:91:13 | call to str | stl.cpp:55:42:55:44 | str | taint | InQualifier | OutReturnValue | +| taint.cpp:170:3:170:8 | call to strcpy | taint.cpp:156:7:156:12 | strcpy | dataflow | InParameter 0 | OutReturnValue | +| taint.cpp:170:3:170:8 | call to strcpy | taint.cpp:156:7:156:12 | strcpy | dataflow | InParameterPointer 1 | OutParameterPointer 0 | +| taint.cpp:170:3:170:8 | call to strcpy | taint.cpp:156:7:156:12 | strcpy | dataflow | InParameterPointer 1 | OutReturnPointer | +| taint.cpp:172:3:172:8 | call to strcat | taint.cpp:157:7:157:12 | strcat | dataflow | InParameter 0 | OutReturnValue | +| taint.cpp:172:3:172:8 | call to strcat | taint.cpp:157:7:157:12 | strcat | taint | InParameter 1 | OutParameterPointer 0 | +| taint.cpp:172:3:172:8 | call to strcat | taint.cpp:157:7:157:12 | strcat | taint | InParameterPointer 0 | OutParameterPointer 0 | +| taint.cpp:194:2:194:7 | call to memcpy | taint.cpp:190:7:190:12 | memcpy | dataflow | InParameter 0 | OutReturnValue | +| taint.cpp:194:2:194:7 | call to memcpy | taint.cpp:190:7:190:12 | memcpy | dataflow | InParameterPointer 1 | OutParameterPointer 0 | +| taint.cpp:194:2:194:7 | call to memcpy | taint.cpp:190:7:190:12 | memcpy | dataflow | InParameterPointer 1 | OutReturnPointer | +| taint.cpp:194:2:194:7 | call to memcpy | taint.cpp:190:7:190:12 | memcpy | taint | InParameter 2 | OutParameterPointer 0 | +| taint.cpp:194:2:194:7 | call to memcpy | taint.cpp:190:7:190:12 | memcpy | taint | InParameter 2 | OutReturnPointer | +| taint.cpp:213:2:213:10 | call to swap | taint.cpp:201:35:201:38 | swap | dataflow | InParameterPointer 0 | OutParameterPointer 1 | +| taint.cpp:213:2:213:10 | call to swap | taint.cpp:201:35:201:38 | swap | dataflow | InParameterPointer 1 | OutParameterPointer 0 | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/models.ql b/cpp/ql/test/library-tests/dataflow/taint-tests/models.ql new file mode 100644 index 000000000000..64b3d99837b1 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/models.ql @@ -0,0 +1,19 @@ +import cpp +import semmle.code.cpp.dataflow.TaintTracking +import semmle.code.cpp.models.interfaces.DataFlow +import semmle.code.cpp.models.interfaces.Taint + +from FunctionCall fc, Function f, string str, FunctionInput inModel, FunctionOutput outModel +where + fc.getTarget() = f and + ( + ( + f.(TaintFunction).hasTaintFlow(inModel, outModel) and + str = "taint" + ) or ( + f.(DataFlowFunction).hasDataFlow(inModel, outModel) and + str = "dataflow" + ) + ) +select + fc, f, str, inModel, outModel From f90647a9e233813de95aab7a3adab9a4a7824d96 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 25 Jul 2019 12:22:39 +0100 Subject: [PATCH 06/10] CPP: Permit more taint flow cases. --- .../dataflow/internal/TaintTrackingUtil.qll | 59 ++++++++++++++----- .../dataflow/taint-tests/localTaint.expected | 9 +++ .../dataflow/taint-tests/stl.cpp | 4 +- .../dataflow/taint-tests/taint.expected | 2 + .../dataflow/taint-tests/test_diff.expected | 2 + 5 files changed, 60 insertions(+), 16 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll index e379157a6031..b9c8350cb7f0 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll @@ -69,6 +69,7 @@ predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeT ) or // Taint can flow through modeled functions + exprToExprStep(nodeFrom.asExpr(), nodeTo.asExpr()) or exprToDefinitionByReferenceStep(nodeFrom.asExpr(), nodeTo.asDefiningArgument()) } @@ -113,6 +114,31 @@ private predicate noFlowFromChildExpr(Expr e) { e instanceof FieldAccess } +private predicate exprToExprStep(Expr exprIn, Expr exprOut) { + exists(Call call, TaintFunction f, FunctionInput inModel, FunctionOutput outModel | + call.getTarget() = f and + f.hasTaintFlow(inModel, outModel) and + ( + exists(int argInIndex | + inModel.isInParameterPointer(argInIndex) and + exprIn = call.getArgument(argInIndex) + ) or exists(int argInIndex | + inModel.isInParameterPointer(argInIndex) and + call.passesByReference(argInIndex, exprIn) + ) or exists(int argInIndex | + inModel.isInParameter(argInIndex) and + exprIn = call.getArgument(argInIndex) + ) or ( + inModel.isInQualifier() and + exprIn = call.getQualifier() + ) + ) and ( + outModel.isOutReturnValue() and + exprOut = call + ) + ) +} + private predicate exprToDefinitionByReferenceStep(Expr exprIn, Expr argOut) { exists(DataFlowFunction f, Call call, FunctionOutput outModel, int argOutIndex | call.getTarget() = f and @@ -128,21 +154,26 @@ private predicate exprToDefinitionByReferenceStep(Expr exprIn, Expr argOut) { ) ) or - exists(TaintFunction f, Call call, FunctionOutput outModel, int argOutIndex | + exists(Call call, TaintFunction f, FunctionInput inModel, FunctionOutput outModel | call.getTarget() = f and - argOut = call.getArgument(argOutIndex) and - outModel.isOutParameterPointer(argOutIndex) and - exists(int argInIndex, FunctionInput inModel | - f.hasTaintFlow(inModel, outModel) - | - inModel.isInParameterPointer(argInIndex) and - exprIn = call.getArgument(argInIndex) - or - inModel.isInParameterPointer(argInIndex) and - call.passesByReference(argInIndex, exprIn) - or - inModel.isInParameter(argInIndex) and - exprIn = call.getArgument(argInIndex) + f.hasTaintFlow(inModel, outModel) and + ( + exists(int argInIndex | + inModel.isInParameterPointer(argInIndex) and + exprIn = call.getArgument(argInIndex) + ) or exists(int argInIndex | + inModel.isInParameterPointer(argInIndex) and + call.passesByReference(argInIndex, exprIn) + ) or exists(int argInIndex | + inModel.isInParameter(argInIndex) and + exprIn = call.getArgument(argInIndex) + ) or ( + inModel.isInQualifier() and + exprIn = call.getQualifier() + ) + ) and exists(int argOutIndex | + outModel.isOutParameterPointer(argOutIndex) and + argOut = call.getArgument(argOutIndex) ) ) } 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 dad73c3a09f8..b5d41789c5aa 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -25,16 +25,25 @@ | stl.cpp:77:16:77:24 | call to basic_string | stl.cpp:82:9:82:9 | t | | | stl.cpp:79:2:79:4 | ref arg ss1 | stl.cpp:84:7:84:9 | ss1 | | | stl.cpp:79:2:79:4 | ref arg ss1 | stl.cpp:88:7:88:9 | ss1 | | +| stl.cpp:79:2:79:4 | ss1 | stl.cpp:79:6:79:6 | call to operator<< | TAINT | | stl.cpp:79:9:79:14 | 1234 | stl.cpp:79:2:79:4 | ref arg ss1 | TAINT | | stl.cpp:80:2:80:4 | ref arg ss2 | stl.cpp:85:7:85:9 | ss2 | | | stl.cpp:80:2:80:4 | ref arg ss2 | stl.cpp:89:7:89:9 | ss2 | | +| stl.cpp:80:2:80:4 | ss2 | stl.cpp:80:6:80:6 | call to operator<< | TAINT | | stl.cpp:80:9:80:14 | call to source | stl.cpp:80:2:80:4 | ref arg ss2 | TAINT | | stl.cpp:81:2:81:4 | ref arg ss3 | stl.cpp:86:7:86:9 | ss3 | | | stl.cpp:81:2:81:4 | ref arg ss3 | stl.cpp:90:7:90:9 | ss3 | | +| stl.cpp:81:2:81:4 | ss3 | stl.cpp:81:6:81:6 | call to operator<< | TAINT | +| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:81:15:81:15 | call to operator<< | TAINT | | stl.cpp:81:9:81:13 | 123 | stl.cpp:81:2:81:4 | ref arg ss3 | TAINT | | stl.cpp:82:2:82:4 | ref arg ss4 | stl.cpp:87:7:87:9 | ss4 | | | stl.cpp:82:2:82:4 | ref arg ss4 | stl.cpp:91:7:91:9 | ss4 | | +| stl.cpp:82:2:82:4 | ss4 | stl.cpp:82:6:82:6 | call to operator<< | TAINT | | stl.cpp:82:9:82:9 | t | stl.cpp:82:2:82:4 | ref arg ss4 | TAINT | +| stl.cpp:88:7:88:9 | ss1 | stl.cpp:88:11:88:13 | call to str | TAINT | +| stl.cpp:89:7:89:9 | ss2 | stl.cpp:89:11:89:13 | call to str | TAINT | +| stl.cpp:90:7:90:9 | ss3 | stl.cpp:90:11:90:13 | call to str | TAINT | +| stl.cpp:91:7:91:9 | ss4 | stl.cpp:91:11:91:13 | call to str | TAINT | | taint.cpp:4:27:4:33 | source1 | taint.cpp:6:13:6:19 | source1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:5:8:5:13 | clean1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:6:3:6:8 | clean1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index 4cd3b166d4f6..62afca72e929 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -86,7 +86,7 @@ void test_stringstream() sink(ss3); // tainted [NOT DETECTED] sink(ss4); // tainted sink(ss1.str()); - sink(ss2.str()); // tainted [NOT DETECTED] + sink(ss2.str()); // tainted sink(ss3.str()); // tainted [NOT DETECTED] - sink(ss4.str()); // tainted [NOT DETECTED] + sink(ss4.str()); // 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 26a0683ca090..1bfa839d53ef 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -3,6 +3,8 @@ | stl.cpp:71:9:71:13 | call to c_str | stl.cpp:65:16:65:21 | call to source | | stl.cpp:85:7:85:9 | ss2 | stl.cpp:80:9:80:14 | call to source | | stl.cpp:87:7:87:9 | ss4 | stl.cpp:77:16:77:21 | call to source | +| stl.cpp:89:11:89:13 | call to str | stl.cpp:80:9:80:14 | call to source | +| stl.cpp:91:11:91:13 | call to str | stl.cpp:77:16:77:21 | call to source | | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12: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 703173d64ceb..0db509ce427d 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 @@ -2,6 +2,8 @@ | stl.cpp:71:9:71:13 | stl.cpp:65:16:65:21 | AST only | | stl.cpp:85:7:85:9 | stl.cpp:80:9:80:14 | AST only | | stl.cpp:87:7:87:9 | stl.cpp:77:16:77:21 | AST only | +| stl.cpp:89:11:89:13 | stl.cpp:80:9:80:14 | AST only | +| stl.cpp:91:11:91:13 | stl.cpp:77:16:77:21 | AST only | | taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only | From eabfd9f566aaf20046a5688624a144544d7ee1a6 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 25 Jul 2019 18:00:13 +0100 Subject: [PATCH 07/10] CPP: Add TInReturnValue and cover the last couple of cases. --- .../dataflow/internal/TaintTrackingUtil.qll | 17 +++++++++--- .../cpp/models/implementations/Strings.qll | 12 +++++---- .../interfaces/FunctionInputsAndOutputs.qll | 16 ++++++++++++ .../dataflow/taint-tests/localTaint.expected | 26 ++++++++++++------- .../dataflow/taint-tests/models.expected | 20 +++++++------- .../dataflow/taint-tests/stl.cpp | 4 +-- .../dataflow/taint-tests/taint.expected | 2 ++ .../dataflow/taint-tests/test_diff.expected | 2 ++ 8 files changed, 70 insertions(+), 29 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll index b9c8350cb7f0..d0767f2d2127 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll @@ -129,12 +129,20 @@ private predicate exprToExprStep(Expr exprIn, Expr exprOut) { inModel.isInParameter(argInIndex) and exprIn = call.getArgument(argInIndex) ) or ( - inModel.isInQualifier() and + inModel.isInQualifier() and exprIn = call.getQualifier() + ) or ( + inModel.isInReturnValue() and + exprIn = call ) ) and ( - outModel.isOutReturnValue() and - exprOut = call + ( + outModel.isOutReturnValue() and + exprOut = call + ) or exists(int argOutIndex | + outModel.isOutParameterPointer(argOutIndex) and + exprOut = call.getArgument(argOutIndex) + ) ) ) } @@ -170,6 +178,9 @@ private predicate exprToDefinitionByReferenceStep(Expr exprIn, Expr argOut) { ) or ( inModel.isInQualifier() and exprIn = call.getQualifier() + ) or ( + inModel.isInReturnValue() and + exprIn = call ) ) and exists(int argOutIndex | outModel.isOutParameterPointer(argOutIndex) and diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll index df6459acda91..69a869f3ef3f 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strings.qll @@ -41,13 +41,15 @@ class InsertionOperator extends TaintFunction { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { ( - // flow from second argument to first + // flow from second argument to return value input.isInParameterPointer(1) and - output.isOutParameterPointer(0) - ) or ( - // flow from first argument to return value - input.isInParameterPointer(0) and output.isOutReturnValue() + ) or ( + // flow from return value to first argument + // (this is a bit odd; another way to think of it is the sink effectively + // flowing from the first argument to the return value) + input.isInReturnValue() and + output.isOutParameterPointer(0) ) } } diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll index 4ee4dc962d23..ae916593c56b 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll @@ -19,6 +19,8 @@ newtype TFunctionInput = TInParameterPointer(ParameterIndex i) or TInQualifier() + or + TInReturnValue() class FunctionInput extends TFunctionInput { abstract string toString(); @@ -34,6 +36,10 @@ class FunctionInput extends TFunctionInput { predicate isInQualifier() { none() } + + predicate isInReturnValue() { + none() + } } class InParameter extends FunctionInput, TInParameter { @@ -86,6 +92,16 @@ class InQualifier extends FunctionInput, TInQualifier { } } +class InReturnValue extends FunctionInput, TInReturnValue { + override string toString() { + result = "InReturnValue" + } + + override predicate isInReturnValue() { + any() + } +} + newtype TFunctionOutput = TOutParameterPointer(ParameterIndex i) or 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 b5d41789c5aa..58c374b1806b 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -25,21 +25,26 @@ | stl.cpp:77:16:77:24 | call to basic_string | stl.cpp:82:9:82:9 | t | | | stl.cpp:79:2:79:4 | ref arg ss1 | stl.cpp:84:7:84:9 | ss1 | | | stl.cpp:79:2:79:4 | ref arg ss1 | stl.cpp:88:7:88:9 | ss1 | | -| stl.cpp:79:2:79:4 | ss1 | stl.cpp:79:6:79:6 | call to operator<< | TAINT | -| stl.cpp:79:9:79:14 | 1234 | stl.cpp:79:2:79:4 | ref arg ss1 | TAINT | +| stl.cpp:79:6:79:6 | call to operator<< | stl.cpp:79:2:79:4 | ref arg ss1 | TAINT | +| stl.cpp:79:6:79:6 | call to operator<< | stl.cpp:79:2:79:4 | ss1 | TAINT | +| stl.cpp:79:9:79:14 | 1234 | stl.cpp:79:6:79:6 | call to operator<< | TAINT | | stl.cpp:80:2:80:4 | ref arg ss2 | stl.cpp:85:7:85:9 | ss2 | | | stl.cpp:80:2:80:4 | ref arg ss2 | stl.cpp:89:7:89:9 | ss2 | | -| stl.cpp:80:2:80:4 | ss2 | stl.cpp:80:6:80:6 | call to operator<< | TAINT | -| stl.cpp:80:9:80:14 | call to source | stl.cpp:80:2:80:4 | ref arg ss2 | TAINT | +| stl.cpp:80:6:80:6 | call to operator<< | stl.cpp:80:2:80:4 | ref arg ss2 | TAINT | +| stl.cpp:80:6:80:6 | call to operator<< | stl.cpp:80:2:80:4 | ss2 | TAINT | +| stl.cpp:80:9:80:14 | call to source | stl.cpp:80:6:80:6 | call to operator<< | TAINT | | stl.cpp:81:2:81:4 | ref arg ss3 | stl.cpp:86:7:86:9 | ss3 | | | stl.cpp:81:2:81:4 | ref arg ss3 | stl.cpp:90:7:90:9 | ss3 | | -| stl.cpp:81:2:81:4 | ss3 | stl.cpp:81:6:81:6 | call to operator<< | TAINT | -| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:81:15:81:15 | call to operator<< | TAINT | -| stl.cpp:81:9:81:13 | 123 | stl.cpp:81:2:81:4 | ref arg ss3 | TAINT | +| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:81:2:81:4 | ref arg ss3 | TAINT | +| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:81:2:81:4 | ss3 | TAINT | +| stl.cpp:81:9:81:13 | 123 | stl.cpp:81:6:81:6 | call to operator<< | TAINT | +| stl.cpp:81:15:81:15 | call to operator<< | stl.cpp:81:6:81:6 | call to operator<< | TAINT | +| stl.cpp:81:18:81:23 | call to source | stl.cpp:81:15:81:15 | call to operator<< | TAINT | | stl.cpp:82:2:82:4 | ref arg ss4 | stl.cpp:87:7:87:9 | ss4 | | | stl.cpp:82:2:82:4 | ref arg ss4 | stl.cpp:91:7:91:9 | ss4 | | -| stl.cpp:82:2:82:4 | ss4 | stl.cpp:82:6:82:6 | call to operator<< | TAINT | -| stl.cpp:82:9:82:9 | t | stl.cpp:82:2:82:4 | ref arg ss4 | TAINT | +| stl.cpp:82:6:82:6 | call to operator<< | stl.cpp:82:2:82:4 | ref arg ss4 | TAINT | +| stl.cpp:82:6:82:6 | call to operator<< | stl.cpp:82:2:82:4 | ss4 | TAINT | +| stl.cpp:82:9:82:9 | t | stl.cpp:82:6:82:6 | call to operator<< | TAINT | | stl.cpp:88:7:88:9 | ss1 | stl.cpp:88:11:88:13 | call to str | TAINT | | stl.cpp:89:7:89:9 | ss2 | stl.cpp:89:11:89:13 | call to str | TAINT | | stl.cpp:90:7:90:9 | ss3 | stl.cpp:90:11:90:13 | call to str | TAINT | @@ -188,9 +193,11 @@ | taint.cpp:171:8:171:13 | ref arg buffer | taint.cpp:172:10:172:15 | buffer | | | taint.cpp:171:8:171:13 | ref arg buffer | taint.cpp:173:8:173:13 | buffer | | | taint.cpp:172:10:172:15 | buffer | taint.cpp:172:3:172:8 | call to strcat | | +| taint.cpp:172:10:172:15 | buffer | taint.cpp:172:10:172:15 | buffer | TAINT | | taint.cpp:172:10:172:15 | buffer | taint.cpp:172:10:172:15 | ref arg buffer | TAINT | | taint.cpp:172:10:172:15 | ref arg buffer | taint.cpp:172:3:172:8 | call to strcat | | | taint.cpp:172:10:172:15 | ref arg buffer | taint.cpp:173:8:173:13 | buffer | | +| taint.cpp:172:18:172:24 | tainted | taint.cpp:172:10:172:15 | buffer | TAINT | | taint.cpp:172:18:172:24 | tainted | taint.cpp:172:10:172:15 | ref arg buffer | TAINT | | taint.cpp:180:19:180:19 | p | taint.cpp:181:9:181:9 | p | | | taint.cpp:181:9:181:9 | p | taint.cpp:181:8:181:9 | * ... | TAINT | @@ -204,6 +211,7 @@ | taint.cpp:194:9:194:10 | ref arg & ... | taint.cpp:195:7:195:7 | x | | | taint.cpp:194:10:194:10 | x | taint.cpp:194:9:194:10 | & ... | TAINT | | taint.cpp:194:13:194:18 | source | taint.cpp:194:9:194:10 | ref arg & ... | TAINT | +| taint.cpp:194:21:194:31 | sizeof(int) | taint.cpp:194:9:194:10 | & ... | TAINT | | taint.cpp:194:21:194:31 | sizeof(int) | taint.cpp:194:9:194:10 | ref arg & ... | TAINT | | taint.cpp:207:6:207:11 | call to source | taint.cpp:207:2:207:13 | ... = ... | | | taint.cpp:207:6:207:11 | call to source | taint.cpp:210:7:210:7 | x | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/models.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/models.expected index b52ccc352894..ee1a760c472e 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/models.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/models.expected @@ -9,16 +9,16 @@ | stl.cpp:77:16:77:24 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 0 | OutReturnValue | | stl.cpp:77:16:77:24 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 1 | OutReturnValue | | stl.cpp:77:16:77:24 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 2 | OutReturnValue | -| stl.cpp:79:6:79:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 0 | OutReturnValue | -| stl.cpp:79:6:79:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 1 | OutParameterPointer 0 | -| stl.cpp:80:6:80:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 0 | OutReturnValue | -| stl.cpp:80:6:80:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 1 | OutParameterPointer 0 | -| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 0 | OutReturnValue | -| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 1 | OutParameterPointer 0 | -| stl.cpp:81:15:81:15 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 0 | OutReturnValue | -| stl.cpp:81:15:81:15 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 1 | OutParameterPointer 0 | -| stl.cpp:82:6:82:6 | call to operator<< | stl.cpp:43:85:43:94 | operator<< | taint | InParameterPointer 0 | OutReturnValue | -| stl.cpp:82:6:82:6 | call to operator<< | stl.cpp:43:85:43:94 | operator<< | taint | InParameterPointer 1 | OutParameterPointer 0 | +| stl.cpp:79:6:79:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 1 | OutReturnValue | +| stl.cpp:79:6:79:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InReturnValue | OutParameterPointer 0 | +| stl.cpp:80:6:80:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 1 | OutReturnValue | +| stl.cpp:80:6:80:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InReturnValue | OutParameterPointer 0 | +| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 1 | OutReturnValue | +| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InReturnValue | OutParameterPointer 0 | +| stl.cpp:81:15:81:15 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 1 | OutReturnValue | +| stl.cpp:81:15:81:15 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InReturnValue | OutParameterPointer 0 | +| stl.cpp:82:6:82:6 | call to operator<< | stl.cpp:43:85:43:94 | operator<< | taint | InParameterPointer 1 | OutReturnValue | +| stl.cpp:82:6:82:6 | call to operator<< | stl.cpp:43:85:43:94 | operator<< | taint | InReturnValue | OutParameterPointer 0 | | stl.cpp:88:11:88:13 | call to str | stl.cpp:55:42:55:44 | str | taint | InQualifier | OutReturnValue | | stl.cpp:89:11:89:13 | call to str | stl.cpp:55:42:55:44 | str | taint | InQualifier | OutReturnValue | | stl.cpp:90:11:90:13 | call to str | stl.cpp:55:42:55:44 | str | taint | InQualifier | OutReturnValue | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index 62afca72e929..8092ec24e544 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -83,10 +83,10 @@ void test_stringstream() sink(ss1); sink(ss2); // tainted - sink(ss3); // tainted [NOT DETECTED] + sink(ss3); // tainted sink(ss4); // tainted sink(ss1.str()); sink(ss2.str()); // tainted - sink(ss3.str()); // tainted [NOT DETECTED] + sink(ss3.str()); // tainted sink(ss4.str()); // 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 1bfa839d53ef..00b7976be26a 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -2,8 +2,10 @@ | stl.cpp:69:7:69:7 | c | stl.cpp:65:16:65:21 | call to source | | stl.cpp:71:9:71:13 | call to c_str | stl.cpp:65:16:65:21 | call to source | | stl.cpp:85:7:85:9 | ss2 | stl.cpp:80:9:80:14 | call to source | +| stl.cpp:86:7:86:9 | ss3 | stl.cpp:81:18:81:23 | call to source | | stl.cpp:87:7:87:9 | ss4 | stl.cpp:77:16:77:21 | call to source | | stl.cpp:89:11:89:13 | call to str | stl.cpp:80:9:80:14 | call to source | +| stl.cpp:90:11:90:13 | call to str | stl.cpp:81:18:81:23 | call to source | | stl.cpp:91:11:91:13 | call to str | stl.cpp:77:16:77:21 | call to source | | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12: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 0db509ce427d..b84715ebbfc5 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 @@ -1,8 +1,10 @@ | stl.cpp:69:7:69:7 | stl.cpp:65:16:65:21 | AST only | | stl.cpp:71:9:71:13 | stl.cpp:65:16:65:21 | AST only | | stl.cpp:85:7:85:9 | stl.cpp:80:9:80:14 | AST only | +| stl.cpp:86:7:86:9 | stl.cpp:81:18:81:23 | AST only | | stl.cpp:87:7:87:9 | stl.cpp:77:16:77:21 | AST only | | stl.cpp:89:11:89:13 | stl.cpp:80:9:80:14 | AST only | +| stl.cpp:90:11:90:13 | stl.cpp:81:18:81:23 | AST only | | stl.cpp:91:11:91:13 | stl.cpp:77:16:77:21 | AST only | | taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only | From 157c70735807df66a214f6b00b9f9b7bd63984a0 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 16 Aug 2019 15:22:12 +0100 Subject: [PATCH 08/10] CPP: Explicit sink parameters. --- .../dataflow/taint-tests/localTaint.expected | 102 +++++++++--------- .../dataflow/taint-tests/models.expected | 50 ++++----- .../dataflow/taint-tests/stl.cpp | 8 +- .../dataflow/taint-tests/taint.expected | 18 ++-- .../dataflow/taint-tests/test_diff.expected | 16 +-- .../dataflow/taint-tests/test_ir.expected | 3 +- 6 files changed, 100 insertions(+), 97 deletions(-) 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 58c374b1806b..dc422d01b7ba 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -1,54 +1,54 @@ -| stl.cpp:63:12:63:17 | call to source | stl.cpp:67:7:67:7 | a | | -| stl.cpp:64:16:64:20 | 123 | stl.cpp:64:16:64:21 | call to basic_string | | -| stl.cpp:64:16:64:21 | call to basic_string | stl.cpp:68:7:68:7 | b | | -| stl.cpp:64:16:64:21 | call to basic_string | stl.cpp:70:7:70:7 | b | | -| stl.cpp:65:16:65:21 | call to source | stl.cpp:65:16:65:24 | call to basic_string | | -| stl.cpp:65:16:65:24 | call to basic_string | stl.cpp:69:7:69:7 | c | | -| stl.cpp:65:16:65:24 | call to basic_string | stl.cpp:71:7:71:7 | c | | -| stl.cpp:70:7:70:7 | b | stl.cpp:70:9:70:13 | call to c_str | | -| stl.cpp:70:7:70:7 | b [post update] | stl.cpp:70:9:70:13 | call to c_str | | -| stl.cpp:71:7:71:7 | c | stl.cpp:71:9:71:13 | call to c_str | | -| stl.cpp:71:7:71:7 | c [post update] | stl.cpp:71:9:71:13 | call to c_str | | -| stl.cpp:76:20:76:22 | call to basic_stringstream | stl.cpp:79:2:79:4 | ss1 | | -| stl.cpp:76:20:76:22 | call to basic_stringstream | stl.cpp:84:7:84:9 | ss1 | | -| stl.cpp:76:20:76:22 | call to basic_stringstream | stl.cpp:88:7:88:9 | ss1 | | -| stl.cpp:76:25:76:27 | call to basic_stringstream | stl.cpp:80:2:80:4 | ss2 | | -| stl.cpp:76:25:76:27 | call to basic_stringstream | stl.cpp:85:7:85:9 | ss2 | | -| stl.cpp:76:25:76:27 | call to basic_stringstream | stl.cpp:89:7:89:9 | ss2 | | -| stl.cpp:76:30:76:32 | call to basic_stringstream | stl.cpp:81:2:81:4 | ss3 | | -| stl.cpp:76:30:76:32 | call to basic_stringstream | stl.cpp:86:7:86:9 | ss3 | | -| stl.cpp:76:30:76:32 | call to basic_stringstream | stl.cpp:90:7:90:9 | ss3 | | -| stl.cpp:76:35:76:37 | call to basic_stringstream | stl.cpp:82:2:82:4 | ss4 | | -| stl.cpp:76:35:76:37 | call to basic_stringstream | stl.cpp:87:7:87:9 | ss4 | | -| stl.cpp:76:35:76:37 | call to basic_stringstream | stl.cpp:91:7:91:9 | ss4 | | -| stl.cpp:77:16:77:21 | call to source | stl.cpp:77:16:77:24 | call to basic_string | | -| stl.cpp:77:16:77:24 | call to basic_string | stl.cpp:82:9:82:9 | t | | -| stl.cpp:79:2:79:4 | ref arg ss1 | stl.cpp:84:7:84:9 | ss1 | | -| stl.cpp:79:2:79:4 | ref arg ss1 | stl.cpp:88:7:88:9 | ss1 | | -| stl.cpp:79:6:79:6 | call to operator<< | stl.cpp:79:2:79:4 | ref arg ss1 | TAINT | -| stl.cpp:79:6:79:6 | call to operator<< | stl.cpp:79:2:79:4 | ss1 | TAINT | -| stl.cpp:79:9:79:14 | 1234 | stl.cpp:79:6:79:6 | call to operator<< | TAINT | -| stl.cpp:80:2:80:4 | ref arg ss2 | stl.cpp:85:7:85:9 | ss2 | | -| stl.cpp:80:2:80:4 | ref arg ss2 | stl.cpp:89:7:89:9 | ss2 | | -| stl.cpp:80:6:80:6 | call to operator<< | stl.cpp:80:2:80:4 | ref arg ss2 | TAINT | -| stl.cpp:80:6:80:6 | call to operator<< | stl.cpp:80:2:80:4 | ss2 | TAINT | -| stl.cpp:80:9:80:14 | call to source | stl.cpp:80:6:80:6 | call to operator<< | TAINT | -| stl.cpp:81:2:81:4 | ref arg ss3 | stl.cpp:86:7:86:9 | ss3 | | -| stl.cpp:81:2:81:4 | ref arg ss3 | stl.cpp:90:7:90:9 | ss3 | | -| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:81:2:81:4 | ref arg ss3 | TAINT | -| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:81:2:81:4 | ss3 | TAINT | -| stl.cpp:81:9:81:13 | 123 | stl.cpp:81:6:81:6 | call to operator<< | TAINT | -| stl.cpp:81:15:81:15 | call to operator<< | stl.cpp:81:6:81:6 | call to operator<< | TAINT | -| stl.cpp:81:18:81:23 | call to source | stl.cpp:81:15:81:15 | call to operator<< | TAINT | -| stl.cpp:82:2:82:4 | ref arg ss4 | stl.cpp:87:7:87:9 | ss4 | | -| stl.cpp:82:2:82:4 | ref arg ss4 | stl.cpp:91:7:91:9 | ss4 | | -| stl.cpp:82:6:82:6 | call to operator<< | stl.cpp:82:2:82:4 | ref arg ss4 | TAINT | -| stl.cpp:82:6:82:6 | call to operator<< | stl.cpp:82:2:82:4 | ss4 | TAINT | -| stl.cpp:82:9:82:9 | t | stl.cpp:82:6:82:6 | call to operator<< | TAINT | -| stl.cpp:88:7:88:9 | ss1 | stl.cpp:88:11:88:13 | call to str | TAINT | -| stl.cpp:89:7:89:9 | ss2 | stl.cpp:89:11:89:13 | call to str | TAINT | -| stl.cpp:90:7:90:9 | ss3 | stl.cpp:90:11:90:13 | call to str | TAINT | -| stl.cpp:91:7:91:9 | ss4 | stl.cpp:91:11:91:13 | call to str | TAINT | +| stl.cpp:65:12:65:17 | call to source | stl.cpp:69:7:69:7 | a | | +| stl.cpp:66:16:66:20 | 123 | stl.cpp:66:16:66:21 | call to basic_string | | +| stl.cpp:66:16:66:21 | call to basic_string | stl.cpp:70:7:70:7 | b | | +| stl.cpp:66:16:66:21 | call to basic_string | stl.cpp:72:7:72:7 | b | | +| stl.cpp:67:16:67:21 | call to source | stl.cpp:67:16:67:24 | call to basic_string | | +| stl.cpp:67:16:67:24 | call to basic_string | stl.cpp:71:7:71:7 | c | | +| stl.cpp:67:16:67:24 | call to basic_string | stl.cpp:73:7:73:7 | c | | +| stl.cpp:72:7:72:7 | b | stl.cpp:72:9:72:13 | call to c_str | | +| stl.cpp:72:7:72:7 | b [post update] | stl.cpp:72:9:72:13 | call to c_str | | +| stl.cpp:73:7:73:7 | c | stl.cpp:73:9:73:13 | call to c_str | | +| stl.cpp:73:7:73:7 | c [post update] | stl.cpp:73:9:73:13 | call to c_str | | +| stl.cpp:78:20:78:22 | call to basic_stringstream | stl.cpp:81:2:81:4 | ss1 | | +| stl.cpp:78:20:78:22 | call to basic_stringstream | stl.cpp:86:7:86:9 | ss1 | | +| stl.cpp:78:20:78:22 | call to basic_stringstream | stl.cpp:90:7:90:9 | ss1 | | +| stl.cpp:78:25:78:27 | call to basic_stringstream | stl.cpp:82:2:82:4 | ss2 | | +| stl.cpp:78:25:78:27 | call to basic_stringstream | stl.cpp:87:7:87:9 | ss2 | | +| stl.cpp:78:25:78:27 | call to basic_stringstream | stl.cpp:91:7:91:9 | ss2 | | +| stl.cpp:78:30:78:32 | call to basic_stringstream | stl.cpp:83:2:83:4 | ss3 | | +| stl.cpp:78:30:78:32 | call to basic_stringstream | stl.cpp:88:7:88:9 | ss3 | | +| stl.cpp:78:30:78:32 | call to basic_stringstream | stl.cpp:92:7:92:9 | ss3 | | +| stl.cpp:78:35:78:37 | call to basic_stringstream | stl.cpp:84:2:84:4 | ss4 | | +| stl.cpp:78:35:78:37 | call to basic_stringstream | stl.cpp:89:7:89:9 | ss4 | | +| stl.cpp:78:35:78:37 | call to basic_stringstream | stl.cpp:93:7:93:9 | ss4 | | +| stl.cpp:79:16:79:21 | call to source | stl.cpp:79:16:79:24 | call to basic_string | | +| stl.cpp:79:16:79:24 | call to basic_string | stl.cpp:84:9:84:9 | t | | +| stl.cpp:81:2:81:4 | ref arg ss1 | stl.cpp:86:7:86:9 | ss1 | | +| stl.cpp:81:2:81:4 | ref arg ss1 | stl.cpp:90:7:90:9 | ss1 | | +| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:81:2:81:4 | ref arg ss1 | TAINT | +| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:81:2:81:4 | ss1 | TAINT | +| stl.cpp:81:9:81:14 | 1234 | stl.cpp:81:6:81:6 | call to operator<< | TAINT | +| stl.cpp:82:2:82:4 | ref arg ss2 | stl.cpp:87:7:87:9 | ss2 | | +| stl.cpp:82:2:82:4 | ref arg ss2 | stl.cpp:91:7:91:9 | ss2 | | +| stl.cpp:82:6:82:6 | call to operator<< | stl.cpp:82:2:82:4 | ref arg ss2 | TAINT | +| stl.cpp:82:6:82:6 | call to operator<< | stl.cpp:82:2:82:4 | ss2 | TAINT | +| stl.cpp:82:9:82:14 | call to source | stl.cpp:82:6:82:6 | call to operator<< | TAINT | +| stl.cpp:83:2:83:4 | ref arg ss3 | stl.cpp:88:7:88:9 | ss3 | | +| stl.cpp:83:2:83:4 | ref arg ss3 | stl.cpp:92:7:92:9 | ss3 | | +| stl.cpp:83:6:83:6 | call to operator<< | stl.cpp:83:2:83:4 | ref arg ss3 | TAINT | +| stl.cpp:83:6:83:6 | call to operator<< | stl.cpp:83:2:83:4 | ss3 | TAINT | +| stl.cpp:83:9:83:13 | 123 | stl.cpp:83:6:83:6 | call to operator<< | TAINT | +| stl.cpp:83:15:83:15 | call to operator<< | stl.cpp:83:6:83:6 | call to operator<< | TAINT | +| stl.cpp:83:18:83:23 | call to source | stl.cpp:83:15:83:15 | call to operator<< | TAINT | +| stl.cpp:84:2:84:4 | ref arg ss4 | stl.cpp:89:7:89:9 | ss4 | | +| stl.cpp:84:2:84:4 | ref arg ss4 | stl.cpp:93:7:93:9 | ss4 | | +| stl.cpp:84:6:84:6 | call to operator<< | stl.cpp:84:2:84:4 | ref arg ss4 | TAINT | +| stl.cpp:84:6:84:6 | call to operator<< | stl.cpp:84:2:84:4 | ss4 | TAINT | +| stl.cpp:84:9:84:9 | t | stl.cpp:84:6:84:6 | call to operator<< | TAINT | +| stl.cpp:90:7:90:9 | ss1 | stl.cpp:90:11:90:13 | call to str | TAINT | +| stl.cpp:91:7:91:9 | ss2 | stl.cpp:91:11:91:13 | call to str | TAINT | +| stl.cpp:92:7:92:9 | ss3 | stl.cpp:92:11:92:13 | call to str | TAINT | +| stl.cpp:93:7:93:9 | ss4 | stl.cpp:93:11:93:13 | call to str | TAINT | | taint.cpp:4:27:4:33 | source1 | taint.cpp:6:13:6:19 | source1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:5:8:5:13 | clean1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:6:3:6:8 | clean1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/models.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/models.expected index ee1a760c472e..3c867073d3e3 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/models.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/models.expected @@ -1,28 +1,28 @@ -| stl.cpp:64:16:64:21 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 0 | OutReturnValue | -| stl.cpp:64:16:64:21 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 1 | OutReturnValue | -| stl.cpp:64:16:64:21 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 2 | OutReturnValue | -| stl.cpp:65:16:65:24 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 0 | OutReturnValue | -| stl.cpp:65:16:65:24 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 1 | OutReturnValue | -| stl.cpp:65:16:65:24 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 2 | OutReturnValue | -| stl.cpp:70:9:70:13 | call to c_str | stl.cpp:24:16:24:20 | c_str | dataflow | InQualifier | OutReturnValue | -| stl.cpp:71:9:71:13 | call to c_str | stl.cpp:24:16:24:20 | c_str | dataflow | InQualifier | OutReturnValue | -| stl.cpp:77:16:77:24 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 0 | OutReturnValue | -| stl.cpp:77:16:77:24 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 1 | OutReturnValue | -| stl.cpp:77:16:77:24 | call to basic_string | stl.cpp:22:3:22:14 | basic_string | dataflow | InParameter 2 | OutReturnValue | -| stl.cpp:79:6:79:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 1 | OutReturnValue | -| stl.cpp:79:6:79:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InReturnValue | OutParameterPointer 0 | -| stl.cpp:80:6:80:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 1 | OutReturnValue | -| stl.cpp:80:6:80:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InReturnValue | OutParameterPointer 0 | -| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 1 | OutReturnValue | -| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InReturnValue | OutParameterPointer 0 | -| stl.cpp:81:15:81:15 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InParameterPointer 1 | OutReturnValue | -| stl.cpp:81:15:81:15 | call to operator<< | stl.cpp:42:67:42:76 | operator<< | taint | InReturnValue | OutParameterPointer 0 | -| stl.cpp:82:6:82:6 | call to operator<< | stl.cpp:43:85:43:94 | operator<< | taint | InParameterPointer 1 | OutReturnValue | -| stl.cpp:82:6:82:6 | call to operator<< | stl.cpp:43:85:43:94 | operator<< | taint | InReturnValue | OutParameterPointer 0 | -| stl.cpp:88:11:88:13 | call to str | stl.cpp:55:42:55:44 | str | taint | InQualifier | OutReturnValue | -| stl.cpp:89:11:89:13 | call to str | stl.cpp:55:42:55:44 | str | taint | InQualifier | OutReturnValue | -| stl.cpp:90:11:90:13 | call to str | stl.cpp:55:42:55:44 | str | taint | InQualifier | OutReturnValue | -| stl.cpp:91:11:91:13 | call to str | stl.cpp:55:42:55:44 | str | taint | InQualifier | OutReturnValue | +| stl.cpp:66:16:66:21 | call to basic_string | stl.cpp:19:3:19:14 | basic_string | dataflow | InParameter 0 | OutReturnValue | +| stl.cpp:66:16:66:21 | call to basic_string | stl.cpp:19:3:19:14 | basic_string | dataflow | InParameter 1 | OutReturnValue | +| stl.cpp:66:16:66:21 | call to basic_string | stl.cpp:19:3:19:14 | basic_string | dataflow | InParameter 2 | OutReturnValue | +| stl.cpp:67:16:67:24 | call to basic_string | stl.cpp:19:3:19:14 | basic_string | dataflow | InParameter 0 | OutReturnValue | +| stl.cpp:67:16:67:24 | call to basic_string | stl.cpp:19:3:19:14 | basic_string | dataflow | InParameter 1 | OutReturnValue | +| stl.cpp:67:16:67:24 | call to basic_string | stl.cpp:19:3:19:14 | basic_string | dataflow | InParameter 2 | OutReturnValue | +| stl.cpp:72:9:72:13 | call to c_str | stl.cpp:21:16:21:20 | c_str | dataflow | InQualifier | OutReturnValue | +| stl.cpp:73:9:73:13 | call to c_str | stl.cpp:21:16:21:20 | c_str | dataflow | InQualifier | OutReturnValue | +| stl.cpp:79:16:79:24 | call to basic_string | stl.cpp:19:3:19:14 | basic_string | dataflow | InParameter 0 | OutReturnValue | +| stl.cpp:79:16:79:24 | call to basic_string | stl.cpp:19:3:19:14 | basic_string | dataflow | InParameter 1 | OutReturnValue | +| stl.cpp:79:16:79:24 | call to basic_string | stl.cpp:19:3:19:14 | basic_string | dataflow | InParameter 2 | OutReturnValue | +| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:39:67:39:76 | operator<< | taint | InParameterPointer 1 | OutReturnValue | +| stl.cpp:81:6:81:6 | call to operator<< | stl.cpp:39:67:39:76 | operator<< | taint | InReturnValue | OutParameterPointer 0 | +| stl.cpp:82:6:82:6 | call to operator<< | stl.cpp:39:67:39:76 | operator<< | taint | InParameterPointer 1 | OutReturnValue | +| stl.cpp:82:6:82:6 | call to operator<< | stl.cpp:39:67:39:76 | operator<< | taint | InReturnValue | OutParameterPointer 0 | +| stl.cpp:83:6:83:6 | call to operator<< | stl.cpp:39:67:39:76 | operator<< | taint | InParameterPointer 1 | OutReturnValue | +| stl.cpp:83:6:83:6 | call to operator<< | stl.cpp:39:67:39:76 | operator<< | taint | InReturnValue | OutParameterPointer 0 | +| stl.cpp:83:15:83:15 | call to operator<< | stl.cpp:39:67:39:76 | operator<< | taint | InParameterPointer 1 | OutReturnValue | +| stl.cpp:83:15:83:15 | call to operator<< | stl.cpp:39:67:39:76 | operator<< | taint | InReturnValue | OutParameterPointer 0 | +| stl.cpp:84:6:84:6 | call to operator<< | stl.cpp:40:85:40:94 | operator<< | taint | InParameterPointer 1 | OutReturnValue | +| stl.cpp:84:6:84:6 | call to operator<< | stl.cpp:40:85:40:94 | operator<< | taint | InReturnValue | OutParameterPointer 0 | +| stl.cpp:90:11:90:13 | call to str | stl.cpp:52:42:52:44 | str | taint | InQualifier | OutReturnValue | +| stl.cpp:91:11:91:13 | call to str | stl.cpp:52:42:52:44 | str | taint | InQualifier | OutReturnValue | +| stl.cpp:92:11:92:13 | call to str | stl.cpp:52:42:52:44 | str | taint | InQualifier | OutReturnValue | +| stl.cpp:93:11:93:13 | call to str | stl.cpp:52:42:52:44 | str | taint | InQualifier | OutReturnValue | | taint.cpp:170:3:170:8 | call to strcpy | taint.cpp:156:7:156:12 | strcpy | dataflow | InParameter 0 | OutReturnValue | | taint.cpp:170:3:170:8 | call to strcpy | taint.cpp:156:7:156:12 | strcpy | dataflow | InParameterPointer 1 | OutParameterPointer 0 | | taint.cpp:170:3:170:8 | call to strcpy | taint.cpp:156:7:156:12 | strcpy | dataflow | InParameterPointer 1 | OutReturnPointer | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp index 8092ec24e544..92b05d9f0cdd 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -1,7 +1,4 @@ -char *source(); -void sink(...) {}; - typedef unsigned long size_t; namespace std @@ -58,6 +55,11 @@ namespace std using stringstream = basic_stringstream; } +char *source(); +void sink(const char *s) {}; +void sink(const std::string &s) {}; +void sink(const std::stringstream &s) {}; + void test_string() { char *a = source(); // * source -> sink causes the issue. 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 00b7976be26a..781f138e5dd8 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -1,12 +1,12 @@ -| stl.cpp:67:7:67:7 | a | stl.cpp:63:12:63:17 | call to source | -| stl.cpp:69:7:69:7 | c | stl.cpp:65:16:65:21 | call to source | -| stl.cpp:71:9:71:13 | call to c_str | stl.cpp:65:16:65:21 | call to source | -| stl.cpp:85:7:85:9 | ss2 | stl.cpp:80:9:80:14 | call to source | -| stl.cpp:86:7:86:9 | ss3 | stl.cpp:81:18:81:23 | call to source | -| stl.cpp:87:7:87:9 | ss4 | stl.cpp:77:16:77:21 | call to source | -| stl.cpp:89:11:89:13 | call to str | stl.cpp:80:9:80:14 | call to source | -| stl.cpp:90:11:90:13 | call to str | stl.cpp:81:18:81:23 | call to source | -| stl.cpp:91:11:91:13 | call to str | stl.cpp:77:16:77:21 | call to source | +| stl.cpp:69:7:69:7 | a | stl.cpp:65:12:65:17 | call to source | +| stl.cpp:71:7:71:7 | c | stl.cpp:67:16:67:21 | call to source | +| stl.cpp:73:9:73:13 | call to c_str | stl.cpp:67:16:67:21 | call to source | +| stl.cpp:87:7:87:9 | ss2 | stl.cpp:82:9:82:14 | call to source | +| stl.cpp:88:7:88:9 | ss3 | stl.cpp:83:18:83:23 | call to source | +| stl.cpp:89:7:89:9 | ss4 | stl.cpp:79:16:79:21 | call to source | +| stl.cpp:91:11:91:13 | call to str | stl.cpp:82:9:82:14 | call to source | +| stl.cpp:92:11:92:13 | call to str | stl.cpp:83:18:83:23 | call to source | +| stl.cpp:93:11:93:13 | call to str | stl.cpp:79:16:79:21 | call to source | | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12: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 b84715ebbfc5..1dd45600a2bf 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 @@ -1,11 +1,11 @@ -| stl.cpp:69:7:69:7 | stl.cpp:65:16:65:21 | AST only | -| stl.cpp:71:9:71:13 | stl.cpp:65:16:65:21 | AST only | -| stl.cpp:85:7:85:9 | stl.cpp:80:9:80:14 | AST only | -| stl.cpp:86:7:86:9 | stl.cpp:81:18:81:23 | AST only | -| stl.cpp:87:7:87:9 | stl.cpp:77:16:77:21 | AST only | -| stl.cpp:89:11:89:13 | stl.cpp:80:9:80:14 | AST only | -| stl.cpp:90:11:90:13 | stl.cpp:81:18:81:23 | AST only | -| stl.cpp:91:11:91:13 | stl.cpp:77:16:77:21 | AST only | +| stl.cpp:71:7:71:7 | stl.cpp:67:16:67:21 | AST only | +| stl.cpp:73:9:73:13 | stl.cpp:67:16:67:21 | AST only | +| stl.cpp:87:7:87:9 | stl.cpp:82:9:82:14 | AST only | +| stl.cpp:88:7:88:9 | stl.cpp:83:18:83:23 | AST only | +| stl.cpp:89:7:89:9 | stl.cpp:79:16:79:21 | AST only | +| stl.cpp:91:11:91:13 | stl.cpp:82:9:82:14 | AST only | +| stl.cpp:92:11:92:13 | stl.cpp:83:18:83:23 | AST only | +| stl.cpp:93:11:93:13 | stl.cpp:79:16:79:21 | AST only | | taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected index b6bde0ee9f9b..b722161bf3ed 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected @@ -1,4 +1,5 @@ -| stl.cpp:67:7:67:7 | Load: a | stl.cpp:63:12:63:17 | Call: call to source | +| stl.cpp:69:7:69:7 | Convert: (const char *)... | stl.cpp:65:12:65:17 | Call: call to source | +| stl.cpp:69:7:69:7 | Load: a | stl.cpp:65:12:65:17 | Call: call to source | | taint.cpp:8:8:8:13 | Load: clean1 | taint.cpp:4:27:4:33 | InitializeParameter: source1 | | taint.cpp:16:8:16:14 | Load: source1 | taint.cpp:12:22:12:27 | Call: call to source | | taint.cpp:17:8:17:16 | Add: ++ ... | taint.cpp:12:22:12:27 | Call: call to source | From 4843c73750c3e7375576f3c17d98cb8b7a394137 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 30 Aug 2019 15:27:28 +0100 Subject: [PATCH 09/10] CPP: Change note. --- change-notes/1.23/analysis-cpp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change-notes/1.23/analysis-cpp.md b/change-notes/1.23/analysis-cpp.md index 8f236b6c2de9..9336f0c2c8d9 100644 --- a/change-notes/1.23/analysis-cpp.md +++ b/change-notes/1.23/analysis-cpp.md @@ -18,4 +18,4 @@ The following changes in version 1.23 affect C/C++ analysis in all applications. ## Changes to QL libraries -- bullet list +- The library now models data flow through `std::string` and `std::stringstream`. From 348d64d9f1c230bc2fdc370aee3a4356fdf48119 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 30 Aug 2019 18:12:44 +0100 Subject: [PATCH 10/10] CPP: Layout. --- .../cpp/dataflow/internal/DataFlowUtil.qll | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) 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 350d42170aeb..a91111b76c5f 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -545,20 +545,19 @@ private predicate exprToExprStep_nocfg(Expr fromExpr, Expr toExpr) { // `ClassAggregateLiteral` (`{ capture1, ..., captureN }`). toExpr.(LambdaExpression).getInitializer() = fromExpr or - exists(Call call, DataFlowFunction f, FunctionInput inModel, FunctionOutput outModel | - call.getTarget() = f and - f.hasDataFlow(inModel, outModel) and - ( + toExpr = any(Call call | + exists(DataFlowFunction f, FunctionInput inModel, FunctionOutput outModel | + call.getTarget() = f and + f.hasDataFlow(inModel, outModel) and + outModel.isOutReturnValue() + | exists(int argInIndex | inModel.isInParameter(argInIndex) and fromExpr = call.getArgument(argInIndex) - ) or ( - inModel.isInQualifier() and - fromExpr = call.getQualifier() ) - ) and ( - outModel.isOutReturnValue() and - toExpr = call + or + inModel.isInQualifier() and + fromExpr = call.getQualifier() ) ) }