From 983f54f11a74736eed61075c24229032131d09a2 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 25 Aug 2020 15:21:16 -0700 Subject: [PATCH 001/411] C++: simple tests for vector output iterators --- .../dataflow/taint-tests/localTaint.expected | 82 +++++++++++++++++++ .../dataflow/taint-tests/vector.cpp | 27 ++++++ 2 files changed, 109 insertions(+) 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 9a9fca0cd59..bca6b6299ad 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -3173,3 +3173,85 @@ | vector.cpp:324:7:324:8 | ref arg v2 | vector.cpp:327:1:327:1 | v2 | | | vector.cpp:325:7:325:8 | ref arg v3 | vector.cpp:327:1:327:1 | v3 | | | vector.cpp:326:7:326:8 | ref arg v4 | vector.cpp:327:1:327:1 | v4 | | +| vector.cpp:329:62:329:65 | iter | vector.cpp:330:3:330:6 | iter | | +| vector.cpp:330:2:330:17 | ... = ... | vector.cpp:330:2:330:2 | call to operator* [post update] | | +| vector.cpp:330:3:330:6 | iter | vector.cpp:330:2:330:2 | call to operator* | TAINT | +| vector.cpp:330:10:330:15 | call to source | vector.cpp:330:2:330:17 | ... = ... | | +| vector.cpp:334:22:334:24 | call to vector | vector.cpp:336:34:336:35 | v1 | | +| vector.cpp:334:22:334:24 | call to vector | vector.cpp:338:7:338:8 | v1 | | +| vector.cpp:334:22:334:24 | call to vector | vector.cpp:354:1:354:1 | v1 | | +| vector.cpp:334:30:334:32 | call to vector | vector.cpp:340:38:340:39 | v2 | | +| vector.cpp:334:30:334:32 | call to vector | vector.cpp:340:56:340:57 | v2 | | +| vector.cpp:334:30:334:32 | call to vector | vector.cpp:343:7:343:8 | v2 | | +| vector.cpp:334:30:334:32 | call to vector | vector.cpp:354:1:354:1 | v2 | | +| vector.cpp:334:38:334:40 | call to vector | vector.cpp:345:15:345:16 | v3 | | +| vector.cpp:334:38:334:40 | call to vector | vector.cpp:348:7:348:8 | v3 | | +| vector.cpp:334:38:334:40 | call to vector | vector.cpp:354:1:354:1 | v3 | | +| vector.cpp:334:46:334:48 | call to vector | vector.cpp:350:38:350:39 | v4 | | +| vector.cpp:334:46:334:48 | call to vector | vector.cpp:350:56:350:57 | v4 | | +| vector.cpp:334:46:334:48 | call to vector | vector.cpp:353:7:353:8 | v4 | | +| vector.cpp:334:46:334:48 | call to vector | vector.cpp:354:1:354:1 | v4 | | +| vector.cpp:336:34:336:35 | ref arg v1 | vector.cpp:338:7:338:8 | v1 | | +| vector.cpp:336:34:336:35 | ref arg v1 | vector.cpp:354:1:354:1 | v1 | | +| vector.cpp:336:34:336:35 | v1 | vector.cpp:336:37:336:41 | call to begin | TAINT | +| vector.cpp:336:37:336:41 | call to begin | vector.cpp:337:3:337:4 | i1 | | +| vector.cpp:337:2:337:15 | ... = ... | vector.cpp:337:2:337:2 | call to operator* [post update] | | +| vector.cpp:337:3:337:4 | i1 | vector.cpp:337:2:337:2 | call to operator* | TAINT | +| vector.cpp:337:8:337:13 | call to source | vector.cpp:337:2:337:15 | ... = ... | | +| vector.cpp:338:7:338:8 | ref arg v1 | vector.cpp:354:1:354:1 | v1 | | +| vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:340:56:340:57 | v2 | | +| vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:343:7:343:8 | v2 | | +| vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:354:1:354:1 | v2 | | +| vector.cpp:340:38:340:39 | v2 | vector.cpp:340:41:340:45 | call to begin | TAINT | +| vector.cpp:340:41:340:45 | call to begin | vector.cpp:340:50:340:51 | it | | +| vector.cpp:340:41:340:45 | call to begin | vector.cpp:340:68:340:69 | it | | +| vector.cpp:340:41:340:45 | call to begin | vector.cpp:341:4:341:5 | it | | +| vector.cpp:340:56:340:57 | ref arg v2 | vector.cpp:340:56:340:57 | v2 | | +| vector.cpp:340:56:340:57 | ref arg v2 | vector.cpp:343:7:343:8 | v2 | | +| vector.cpp:340:56:340:57 | ref arg v2 | vector.cpp:354:1:354:1 | v2 | | +| vector.cpp:340:56:340:57 | v2 | vector.cpp:340:59:340:61 | call to end | TAINT | +| vector.cpp:340:68:340:69 | it | vector.cpp:340:66:340:66 | call to operator++ | TAINT | +| vector.cpp:340:68:340:69 | ref arg it | vector.cpp:340:50:340:51 | it | | +| vector.cpp:340:68:340:69 | ref arg it | vector.cpp:340:68:340:69 | it | | +| vector.cpp:340:68:340:69 | ref arg it | vector.cpp:341:4:341:5 | it | | +| vector.cpp:341:3:341:16 | ... = ... | vector.cpp:341:3:341:3 | call to operator* [post update] | | +| vector.cpp:341:4:341:5 | it | vector.cpp:341:3:341:3 | call to operator* | TAINT | +| vector.cpp:341:9:341:14 | call to source | vector.cpp:341:3:341:16 | ... = ... | | +| vector.cpp:343:7:343:8 | ref arg v2 | vector.cpp:354:1:354:1 | v2 | | +| vector.cpp:345:15:345:15 | (__begin) | vector.cpp:345:15:345:15 | call to operator* | TAINT | +| vector.cpp:345:15:345:15 | (__begin) | vector.cpp:345:15:345:15 | call to operator++ | TAINT | +| vector.cpp:345:15:345:15 | (__end) | vector.cpp:345:15:345:15 | call to iterator | | +| vector.cpp:345:15:345:15 | (__range) | vector.cpp:345:15:345:15 | call to begin | TAINT | +| vector.cpp:345:15:345:15 | (__range) | vector.cpp:345:15:345:15 | call to end | TAINT | +| vector.cpp:345:15:345:15 | call to begin | vector.cpp:345:15:345:15 | (__begin) | | +| vector.cpp:345:15:345:15 | call to begin | vector.cpp:345:15:345:15 | (__begin) | | +| vector.cpp:345:15:345:15 | call to begin | vector.cpp:345:15:345:15 | (__begin) | | +| vector.cpp:345:15:345:15 | call to end | vector.cpp:345:15:345:15 | (__end) | | +| vector.cpp:345:15:345:15 | ref arg (__begin) | vector.cpp:345:15:345:15 | (__begin) | | +| vector.cpp:345:15:345:15 | ref arg (__begin) | vector.cpp:345:15:345:15 | (__begin) | | +| vector.cpp:345:15:345:15 | ref arg (__begin) | vector.cpp:345:15:345:15 | (__begin) | | +| vector.cpp:345:15:345:15 | ref arg (__range) | vector.cpp:345:15:345:15 | (__range) | | +| vector.cpp:345:15:345:16 | v3 | vector.cpp:345:15:345:15 | (__range) | | +| vector.cpp:345:15:345:16 | v3 | vector.cpp:345:15:345:15 | (__range) | | +| vector.cpp:345:15:345:16 | v3 | vector.cpp:345:15:345:15 | call to operator* | TAINT | +| vector.cpp:346:7:346:12 | call to source | vector.cpp:346:3:346:14 | ... = ... | | +| vector.cpp:348:7:348:8 | ref arg v3 | vector.cpp:354:1:354:1 | v3 | | +| vector.cpp:350:38:350:39 | ref arg v4 | vector.cpp:350:56:350:57 | v4 | | +| vector.cpp:350:38:350:39 | ref arg v4 | vector.cpp:353:7:353:8 | v4 | | +| vector.cpp:350:38:350:39 | ref arg v4 | vector.cpp:354:1:354:1 | v4 | | +| vector.cpp:350:38:350:39 | v4 | vector.cpp:350:41:350:45 | call to begin | TAINT | +| vector.cpp:350:41:350:45 | call to begin | vector.cpp:350:50:350:51 | it | | +| vector.cpp:350:41:350:45 | call to begin | vector.cpp:350:68:350:69 | it | | +| vector.cpp:350:41:350:45 | call to begin | vector.cpp:351:4:351:5 | it | | +| vector.cpp:350:56:350:57 | ref arg v4 | vector.cpp:350:56:350:57 | v4 | | +| vector.cpp:350:56:350:57 | ref arg v4 | vector.cpp:353:7:353:8 | v4 | | +| vector.cpp:350:56:350:57 | ref arg v4 | vector.cpp:354:1:354:1 | v4 | | +| vector.cpp:350:56:350:57 | v4 | vector.cpp:350:59:350:61 | call to end | TAINT | +| vector.cpp:350:68:350:69 | it | vector.cpp:350:66:350:66 | call to operator++ | TAINT | +| vector.cpp:350:68:350:69 | ref arg it | vector.cpp:350:50:350:51 | it | | +| vector.cpp:350:68:350:69 | ref arg it | vector.cpp:350:68:350:69 | it | | +| vector.cpp:350:68:350:69 | ref arg it | vector.cpp:351:4:351:5 | it | | +| vector.cpp:351:3:351:16 | ... = ... | vector.cpp:351:3:351:3 | call to operator* [post update] | | +| vector.cpp:351:4:351:5 | it | vector.cpp:351:3:351:3 | call to operator* | TAINT | +| vector.cpp:351:9:351:14 | call to source | vector.cpp:351:3:351:16 | ... = ... | | +| vector.cpp:353:7:353:8 | ref arg v4 | vector.cpp:354:1:354:1 | v4 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp index e2d12bed6c1..6360438663a 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp @@ -325,3 +325,30 @@ void test_constructors_more() { sink(v3); sink(v4); // tainted } + +void taint_vector_output_iterator(std::vector::iterator iter) { + *iter = source(); +} + +void test_vector_output_iterator() { + std::vector v1(10), v2(10), v3(10), v4(10); + + std::vector::iterator i1 = v1.begin(); + *i1 = source(); + sink(v1); // tainted [NOT DETECTED] + + for(std::vector::iterator it = v2.begin(); it != v2.end(); ++it) { + *it = source(); // tainted [NOT DETECTED] + } + sink(v2); + + for(int& x : v3) { + x = source(); + } + sink(v3); // tainted [NOT DETECTED] + + for(std::vector::iterator it = v4.begin(); it != v4.end(); ++it) { + *it = source(); + } + sink(v4); // tainted [NOT DETECTED] +} From 703db0b9a6ffdb53af4cef150cf1ae6f10ca4517 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 25 Aug 2020 15:26:18 -0700 Subject: [PATCH 002/411] C++: noisy output iterators in AST taint tracking --- .../dataflow/internal/TaintTrackingUtil.qll | 31 +++++++++++++++++++ .../cpp/models/implementations/Iterator.qll | 12 +++++++ .../dataflow/taint-tests/localTaint.expected | 11 +++++++ .../dataflow/taint-tests/taint.expected | 3 ++ .../dataflow/taint-tests/test_diff.expected | 3 ++ .../dataflow/taint-tests/vector.cpp | 10 +++--- 6 files changed, 65 insertions(+), 5 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 a3f0c435e16..c15f39c0c15 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll @@ -10,6 +10,7 @@ private import semmle.code.cpp.models.interfaces.DataFlow private import semmle.code.cpp.models.interfaces.Taint +private import semmle.code.cpp.models.implementations.Iterator private module DataFlow { import semmle.code.cpp.dataflow.internal.DataFlowUtil @@ -186,6 +187,12 @@ private predicate exprToExprStep(Expr exprIn, Expr exprOut) { exprIn = call.getQualifier() ) ) + or + exists(Variable iterator, Variable collection | + assignmentViaIterator(iterator, exprIn) and + isIteratorForCollection(iterator, collection) and + collection.getAnAccess() = exprOut + ) } private predicate exprToDefinitionByReferenceStep(Expr exprIn, Expr argOut) { @@ -249,3 +256,27 @@ private predicate exprToPartialDefinitionStep(Expr exprIn, Expr exprOut) { ) ) } + +private predicate isIteratorForCollection(Variable iterator, Variable collection) { + exists(Call beginOrEnd | + beginOrEnd.getTarget() instanceof BeginOrEndFunction and + beginOrEnd.getQualifier() = collection.getAnAccess() and + iterator.getAnAssignedValue() = beginOrEnd + ) +} + +private predicate assignmentViaIterator(Variable iterator, Expr rvalue) { + exists(Assignment a, Call c | + c.getTarget() instanceof IteratorArrayMemberOperator and + c.getQualifier() = iterator.getAnAccess() + or + c.getTarget() instanceof IteratorPointerDereferenceMemberOperator and + c.getQualifier() = iterator.getAnAccess() + or + c.getTarget() instanceof IteratorPointerDereferenceOperator and + c.getArgument(0) = iterator.getAnAccess() + | + c = a.getLValue() and + rvalue = a.getRValue() + ) +} diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll index 2ad464d1634..758d093bedc 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll @@ -271,3 +271,15 @@ class IteratorArrayMemberOperator extends MemberFunction, TaintFunction { output.isReturnValue() } } + +class BeginOrEndFunction extends MemberFunction, TaintFunction { + BeginOrEndFunction() { + this.hasName(["begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend"]) and + this.getType().getUnspecifiedType() instanceof Iterator + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + input.isQualifierObject() and + output.isReturnValue() + } +} 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 bca6b6299ad..0c0362206e1 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -3197,7 +3197,10 @@ | vector.cpp:336:37:336:41 | call to begin | vector.cpp:337:3:337:4 | i1 | | | vector.cpp:337:2:337:15 | ... = ... | vector.cpp:337:2:337:2 | call to operator* [post update] | | | vector.cpp:337:3:337:4 | i1 | vector.cpp:337:2:337:2 | call to operator* | TAINT | +| vector.cpp:337:8:337:13 | call to source | vector.cpp:336:34:336:35 | v1 | TAINT | | vector.cpp:337:8:337:13 | call to source | vector.cpp:337:2:337:15 | ... = ... | | +| vector.cpp:337:8:337:13 | call to source | vector.cpp:338:7:338:8 | v1 | TAINT | +| vector.cpp:337:8:337:13 | call to source | vector.cpp:354:1:354:1 | v1 | TAINT | | vector.cpp:338:7:338:8 | ref arg v1 | vector.cpp:354:1:354:1 | v1 | | | vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:340:56:340:57 | v2 | | | vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:343:7:343:8 | v2 | | @@ -3216,7 +3219,11 @@ | vector.cpp:340:68:340:69 | ref arg it | vector.cpp:341:4:341:5 | it | | | vector.cpp:341:3:341:16 | ... = ... | vector.cpp:341:3:341:3 | call to operator* [post update] | | | vector.cpp:341:4:341:5 | it | vector.cpp:341:3:341:3 | call to operator* | TAINT | +| vector.cpp:341:9:341:14 | call to source | vector.cpp:340:38:340:39 | v2 | TAINT | +| vector.cpp:341:9:341:14 | call to source | vector.cpp:340:56:340:57 | v2 | TAINT | | vector.cpp:341:9:341:14 | call to source | vector.cpp:341:3:341:16 | ... = ... | | +| vector.cpp:341:9:341:14 | call to source | vector.cpp:343:7:343:8 | v2 | TAINT | +| vector.cpp:341:9:341:14 | call to source | vector.cpp:354:1:354:1 | v2 | TAINT | | vector.cpp:343:7:343:8 | ref arg v2 | vector.cpp:354:1:354:1 | v2 | | | vector.cpp:345:15:345:15 | (__begin) | vector.cpp:345:15:345:15 | call to operator* | TAINT | | vector.cpp:345:15:345:15 | (__begin) | vector.cpp:345:15:345:15 | call to operator++ | TAINT | @@ -3253,5 +3260,9 @@ | vector.cpp:350:68:350:69 | ref arg it | vector.cpp:351:4:351:5 | it | | | vector.cpp:351:3:351:16 | ... = ... | vector.cpp:351:3:351:3 | call to operator* [post update] | | | vector.cpp:351:4:351:5 | it | vector.cpp:351:3:351:3 | call to operator* | TAINT | +| vector.cpp:351:9:351:14 | call to source | vector.cpp:350:38:350:39 | v4 | TAINT | +| vector.cpp:351:9:351:14 | call to source | vector.cpp:350:56:350:57 | v4 | TAINT | | vector.cpp:351:9:351:14 | call to source | vector.cpp:351:3:351:16 | ... = ... | | +| vector.cpp:351:9:351:14 | call to source | vector.cpp:353:7:353:8 | v4 | TAINT | +| vector.cpp:351:9:351:14 | call to source | vector.cpp:354:1:354:1 | v4 | TAINT | | vector.cpp:353:7:353:8 | ref arg v4 | vector.cpp:354:1:354:1 | v4 | | 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 15744c35716..6697e57e4a3 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -326,3 +326,6 @@ | vector.cpp:312:7:312:7 | d | vector.cpp:303:14:303:19 | call to source | | vector.cpp:324:7:324:8 | v2 | vector.cpp:318:15:318:20 | call to source | | vector.cpp:326:7:326:8 | v4 | vector.cpp:318:15:318:20 | call to source | +| vector.cpp:338:7:338:8 | v1 | vector.cpp:337:8:337:13 | call to source | +| vector.cpp:343:7:343:8 | v2 | vector.cpp:341:9:341:14 | call to source | +| vector.cpp:353:7:353:8 | v4 | vector.cpp:351:9:351:14 | 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 d4383d4e900..7533d079093 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 @@ -275,3 +275,6 @@ | vector.cpp:312:7:312:7 | vector.cpp:303:14:303:19 | AST only | | vector.cpp:324:7:324:8 | vector.cpp:318:15:318:20 | AST only | | vector.cpp:326:7:326:8 | vector.cpp:318:15:318:20 | AST only | +| vector.cpp:338:7:338:8 | vector.cpp:337:8:337:13 | AST only | +| vector.cpp:343:7:343:8 | vector.cpp:341:9:341:14 | AST only | +| vector.cpp:353:7:353:8 | vector.cpp:351:9:351:14 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp index 6360438663a..f1cf4e91457 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp @@ -21,7 +21,7 @@ void test_range_based_for_loop_vector(int source1) { } for(std::vector::iterator it = v.begin(); it != v.end(); ++it) { - sink(*it); // tainted + sink(*it); // tainted [NOT DETECTED by IR] } for(int& x : v) { @@ -335,12 +335,12 @@ void test_vector_output_iterator() { std::vector::iterator i1 = v1.begin(); *i1 = source(); - sink(v1); // tainted [NOT DETECTED] + sink(v1); // tainted [NOT DETECTED by IR] for(std::vector::iterator it = v2.begin(); it != v2.end(); ++it) { - *it = source(); // tainted [NOT DETECTED] + *it = source(); } - sink(v2); + sink(v2); // tainted [NOT DETECTED by IR] for(int& x : v3) { x = source(); @@ -350,5 +350,5 @@ void test_vector_output_iterator() { for(std::vector::iterator it = v4.begin(); it != v4.end(); ++it) { *it = source(); } - sink(v4); // tainted [NOT DETECTED] + sink(v4); // tainted [NOT DETECTED by IR] } From c8cdf68bf9b8881faae02f89ca3cb5091ec1c926 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 25 Aug 2020 16:34:36 -0700 Subject: [PATCH 003/411] C++: Remove StdStringBeginEnd --- .../cpp/models/implementations/Iterator.qll | 4 ++++ .../cpp/models/implementations/StdString.qll | 17 ----------------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll index 758d093bedc..93a04d5ef90 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll @@ -272,6 +272,10 @@ class IteratorArrayMemberOperator extends MemberFunction, TaintFunction { } } +/** + * A `begin` or `end` member function, or a related member function, that + * returns an iterator. + */ class BeginOrEndFunction extends MemberFunction, TaintFunction { BeginOrEndFunction() { this.hasName(["begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend"]) and 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 8e7cb24be73..3a2c914eb4c 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -212,23 +212,6 @@ class StdStringAssign extends TaintFunction { } } -/** - * The standard functions `std::string.begin` and `std::string.end` and their - * variants. - */ -class StdStringBeginEnd extends TaintFunction { - StdStringBeginEnd() { - this - .hasQualifiedName("std", "basic_string", - ["begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend"]) - } - - override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - input.isQualifierObject() and - output.isReturnValue() - } -} - /** * The standard function `std::string.copy`. */ From 13c45b6664a6b4fcad59a60a096236cb702d21b0 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 27 Aug 2020 15:09:01 -0700 Subject: [PATCH 004/411] C++: remove unnecessary parameter in FlowVar.qll --- .../code/cpp/dataflow/internal/FlowVar.qll | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll index 6dc5da2f20b..83941140fa6 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll @@ -240,7 +240,7 @@ module FlowVar_internal { ( initializer(v, sbb.getANode()) or - assignmentLikeOperation(sbb, v, _, _) + assignmentLikeOperation(sbb, v, _) or exists(PartialDefinition p | p.partiallyDefinesVariableAt(v, sbb)) or @@ -359,7 +359,7 @@ module FlowVar_internal { } override predicate definedByExpr(Expr e, ControlFlowNode node) { - assignmentLikeOperation(node, v, _, e) and + assignmentLikeOperation(node, v, e) and node = sbb or // We pick the defining `ControlFlowNode` of an `Initializer` to be its @@ -449,7 +449,7 @@ module FlowVar_internal { pragma[noinline] private Variable getAVariableAssignedInLoop() { exists(BasicBlock bbAssign | - assignmentLikeOperation(bbAssign.getANode(), result, _, _) and + assignmentLikeOperation(bbAssign.getANode(), result, _) and this.bbInLoop(bbAssign) ) } @@ -487,7 +487,7 @@ module FlowVar_internal { pragma[noinline] private predicate assignsToVar(BasicBlock bb, Variable v) { - assignmentLikeOperation(bb.getANode(), v, _, _) and + assignmentLikeOperation(bb.getANode(), v, _) and exists(AlwaysTrueUponEntryLoop loop | v = loop.getARelevantVariable()) } @@ -524,7 +524,7 @@ module FlowVar_internal { result = mid.getASuccessor() and variableLiveInSBB(result, v) and forall(AlwaysTrueUponEntryLoop loop | skipLoop(mid, result, v, loop) | loop.sbbInLoop(sbbDef)) and - not assignmentLikeOperation(result, v, _, _) + not assignmentLikeOperation(result, v, _) ) } @@ -566,7 +566,7 @@ module FlowVar_internal { * Holds if liveness of `v` should stop propagating backwards from `sbb`. */ private predicate variableNotLiveBefore(SubBasicBlock sbb, Variable v) { - assignmentLikeOperation(sbb, v, _, _) + assignmentLikeOperation(sbb, v, _) or // Liveness of `v` is killed when going backwards from a block that declares it exists(DeclStmt ds | ds.getADeclaration().(LocalVariable) = v and sbb.contains(ds)) @@ -687,20 +687,18 @@ module FlowVar_internal { * predicate. */ predicate assignmentLikeOperation( - ControlFlowNode node, Variable v, VariableAccess va, Expr assignedExpr + ControlFlowNode node, Variable v, Expr assignedExpr ) { // Together, the two following cases cover `Assignment` node = any(AssignExpr ae | - va = ae.getLValue() and - v = va.getTarget() and + v.getAnAccess() = ae.getLValue() and assignedExpr = ae.getRValue() ) or node = any(AssignOperation ao | - va = ao.getLValue() and - v = va.getTarget() and + v.getAnAccess() = ao.getLValue() and // Here and in the `PrefixCrementOperation` case, we say that the assigned // expression is the operation itself. For example, we say that `x += 1` // assigns `x += 1` to `x`. The justification is that after this operation, @@ -712,8 +710,7 @@ module FlowVar_internal { // `PrefixCrementOperation` is itself a source node = any(CrementOperation op | - va = op.getOperand() and - v = va.getTarget() and + v.getAnAccess() = op.getOperand() and assignedExpr = op ) } @@ -749,7 +746,7 @@ module FlowVar_internal { class DataFlowSubBasicBlockCutNode extends SubBasicBlockCutNode { DataFlowSubBasicBlockCutNode() { exists(Variable v | not fullySupportedSsaVariable(v) | - assignmentLikeOperation(this, v, _, _) + assignmentLikeOperation(this, v, _) or exists(PartialDefinition p | p.partiallyDefinesVariableAt(v, this)) // It is not necessary to cut the basic blocks at `Initializer` nodes From eab1557e27cfefef7b826960e3840e5ba79279e1 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 8 Sep 2020 14:09:57 -0700 Subject: [PATCH 005/411] C++: output iterator flow via FlowVar --- .../cpp/dataflow/internal/DataFlowUtil.qll | 20 ++- .../code/cpp/dataflow/internal/FlowVar.qll | 98 +++++++++-- .../dataflow/internal/TaintTrackingUtil.qll | 34 +--- .../dataflow/taint-tests/localTaint.expected | 160 +++++++++++++++--- .../dataflow/taint-tests/taint.expected | 8 + .../dataflow/taint-tests/test_diff.expected | 8 + .../dataflow/taint-tests/vector.cpp | 32 +++- 7 files changed, 287 insertions(+), 73 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 6647dda4072..9705ca492ce 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -283,12 +283,12 @@ abstract class PostUpdateNode extends Node { override Location getLocation() { result = getPreUpdateNode().getLocation() } } -private class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode { +private abstract class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode { PartialDefinition pd; - PartialDefinitionNode() { this = TPartialDefinitionNode(pd) } - - override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) } + PartialDefinitionNode() { + this = TPartialDefinitionNode(pd) + } override Location getLocation() { result = pd.getActualLocation() } @@ -297,6 +297,18 @@ private class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNo override string toString() { result = getPreUpdateNode().toString() + " [post update]" } } +private class VariablePartialDefinitionNode extends PartialDefinitionNode { + override VariablePartialDefinition pd; + + override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) } +} + +private class IteratorPartialDefinitionNode extends PartialDefinitionNode { + override IteratorPartialDefinition pd; + + override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) } +} + /** * A post-update node on the `e->f` in `f(&e->f)` (and other forms). */ diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll index 83941140fa6..cb2cdd68f08 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll @@ -6,6 +6,7 @@ import cpp private import semmle.code.cpp.controlflow.SSA private import semmle.code.cpp.dataflow.internal.SubBasicBlocks private import semmle.code.cpp.dataflow.internal.AddressFlow +private import semmle.code.cpp.models.implementations.Iterator /** * A conceptual variable that is assigned only once, like an SSA variable. This @@ -109,20 +110,16 @@ class FlowVar extends TFlowVar { */ private module PartialDefinitions { class PartialDefinition extends Expr { - Expr innerDefinedExpr; ControlFlowNode node; PartialDefinition() { - exists(Expr convertedInner | - valueToUpdate(convertedInner, this.getFullyConverted(), node) and - innerDefinedExpr = convertedInner.getUnconverted() and - not this instanceof Conversion - ) + valueToUpdate(_, this.getFullyConverted(), node) and + not this instanceof Conversion } - deprecated predicate partiallyDefines(Variable v) { innerDefinedExpr = v.getAnAccess() } + deprecated predicate partiallyDefines(Variable v) { none() } - deprecated predicate partiallyDefinesThis(ThisExpr e) { innerDefinedExpr = e } + deprecated predicate partiallyDefinesThis(ThisExpr e) { none() } /** * Gets the subBasicBlock where this `PartialDefinition` is defined. @@ -133,10 +130,9 @@ private module PartialDefinitions { * Holds if this `PartialDefinition` defines variable `v` at control-flow * node `cfn`. */ - pragma[noinline] + pragma[noinline] // does this work with a dispred? predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn) { - innerDefinedExpr = v.getAnAccess() and - cfn = node + none() } /** @@ -147,10 +143,7 @@ private module PartialDefinitions { * - `inner` = `... .x`, `outer` = `&...` * - `inner` = `a`, `outer` = `*` */ - predicate definesExpressions(Expr inner, Expr outer) { - inner = innerDefinedExpr and - outer = this - } + predicate definesExpressions(Expr inner, Expr outer) { none() } /** * Gets the location of this element, adjusted to avoid unknown locations @@ -166,6 +159,68 @@ private module PartialDefinitions { } } + class IteratorPartialDefinition extends PartialDefinition { + Variable collection; + Call innerDefinedExpr; + + IteratorPartialDefinition() { + exists(Expr convertedInner | + valueToUpdate(convertedInner, this.getFullyConverted(), node) and + innerDefinedExpr = convertedInner.getUnconverted() and + innerDefinedExpr.getQualifier() = getAnIteratorAccess(collection) and + innerDefinedExpr.getTarget() instanceof IteratorPointerDereferenceMemberOperator + ) + } + + deprecated override predicate partiallyDefines(Variable v) { v = collection } + + deprecated override predicate partiallyDefinesThis(ThisExpr e) { none() } + + override predicate definesExpressions(Expr inner, Expr outer) { + inner = innerDefinedExpr and + outer = this + } + + override predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn) { + v = collection and + cfn = node + } + } + + class VariablePartialDefinition extends PartialDefinition { + Expr innerDefinedExpr; + + VariablePartialDefinition() { + exists(Expr convertedInner | + valueToUpdate(convertedInner, this.getFullyConverted(), node) and + innerDefinedExpr = convertedInner.getUnconverted() and + not this instanceof Conversion + ) + } + + deprecated override predicate partiallyDefines(Variable v) { innerDefinedExpr = v.getAnAccess() } + + deprecated override predicate partiallyDefinesThis(ThisExpr e) { innerDefinedExpr = e } + + /** + * Holds if this partial definition may modify `inner` (or what it points + * to) through `outer`. These expressions will never be `Conversion`s. + * + * For example, in `f(& (*a).x)`, there are two results: + * - `inner` = `... .x`, `outer` = `&...` + * - `inner` = `a`, `outer` = `*` + */ + override predicate definesExpressions(Expr inner, Expr outer) { + inner = innerDefinedExpr and + outer = this + } + + override predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn) { + innerDefinedExpr = v.getAnAccess() and + cfn = node + } + } + /** * A partial definition that's a definition by reference. */ @@ -686,9 +741,7 @@ module FlowVar_internal { * `node instanceof Initializer` is covered by `initializer` instead of this * predicate. */ - predicate assignmentLikeOperation( - ControlFlowNode node, Variable v, Expr assignedExpr - ) { + predicate assignmentLikeOperation(ControlFlowNode node, Variable v, Expr assignedExpr) { // Together, the two following cases cover `Assignment` node = any(AssignExpr ae | @@ -715,6 +768,15 @@ module FlowVar_internal { ) } + Expr getAnIteratorAccess(Variable collection) { + exists(Call c, SsaDefinition def, Variable iterator | + c.getQualifier() = collection.getAnAccess() and + c.getTarget() instanceof BeginOrEndFunction and + def.getAnUltimateDefiningValue(iterator) = c and + result = def.getAUse(iterator) + ) + } + /** * Holds if `v` is initialized to have value `assignedExpr`. */ 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 c15f39c0c15..c8d963866a1 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll @@ -187,12 +187,6 @@ private predicate exprToExprStep(Expr exprIn, Expr exprOut) { exprIn = call.getQualifier() ) ) - or - exists(Variable iterator, Variable collection | - assignmentViaIterator(iterator, exprIn) and - isIteratorForCollection(iterator, collection) and - collection.getAnAccess() = exprOut - ) } private predicate exprToDefinitionByReferenceStep(Expr exprIn, Expr argOut) { @@ -255,28 +249,18 @@ private predicate exprToPartialDefinitionStep(Expr exprIn, Expr exprOut) { exprIn = call.getArgument(argInIndex) ) ) -} - -private predicate isIteratorForCollection(Variable iterator, Variable collection) { - exists(Call beginOrEnd | - beginOrEnd.getTarget() instanceof BeginOrEndFunction and - beginOrEnd.getQualifier() = collection.getAnAccess() and - iterator.getAnAssignedValue() = beginOrEnd + or + exists(Assignment a | + iteratorDereference(exprOut) and + a.getLValue() = exprOut and + a.getRValue() = exprIn ) } -private predicate assignmentViaIterator(Variable iterator, Expr rvalue) { - exists(Assignment a, Call c | - c.getTarget() instanceof IteratorArrayMemberOperator and - c.getQualifier() = iterator.getAnAccess() +private predicate iteratorDereference(Call c) { + c.getTarget() instanceof IteratorArrayMemberOperator or - c.getTarget() instanceof IteratorPointerDereferenceMemberOperator and - c.getQualifier() = iterator.getAnAccess() + c.getTarget() instanceof IteratorPointerDereferenceMemberOperator or - c.getTarget() instanceof IteratorPointerDereferenceOperator and - c.getArgument(0) = iterator.getAnAccess() - | - c = a.getLValue() and - rvalue = a.getRValue() - ) + c.getTarget() instanceof IteratorPointerDereferenceOperator } 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 0c0362206e1..c0f34638554 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -3176,55 +3176,75 @@ | vector.cpp:329:62:329:65 | iter | vector.cpp:330:3:330:6 | iter | | | vector.cpp:330:2:330:17 | ... = ... | vector.cpp:330:2:330:2 | call to operator* [post update] | | | vector.cpp:330:3:330:6 | iter | vector.cpp:330:2:330:2 | call to operator* | TAINT | +| vector.cpp:330:10:330:15 | call to source | vector.cpp:330:2:330:2 | call to operator* [post update] | TAINT | | vector.cpp:330:10:330:15 | call to source | vector.cpp:330:2:330:17 | ... = ... | | +| vector.cpp:333:38:333:38 | b | vector.cpp:368:5:368:5 | b | | | vector.cpp:334:22:334:24 | call to vector | vector.cpp:336:34:336:35 | v1 | | | vector.cpp:334:22:334:24 | call to vector | vector.cpp:338:7:338:8 | v1 | | -| vector.cpp:334:22:334:24 | call to vector | vector.cpp:354:1:354:1 | v1 | | +| vector.cpp:334:22:334:24 | call to vector | vector.cpp:382:1:382:1 | v1 | | | vector.cpp:334:30:334:32 | call to vector | vector.cpp:340:38:340:39 | v2 | | | vector.cpp:334:30:334:32 | call to vector | vector.cpp:340:56:340:57 | v2 | | | vector.cpp:334:30:334:32 | call to vector | vector.cpp:343:7:343:8 | v2 | | -| vector.cpp:334:30:334:32 | call to vector | vector.cpp:354:1:354:1 | v2 | | +| vector.cpp:334:30:334:32 | call to vector | vector.cpp:382:1:382:1 | v2 | | | vector.cpp:334:38:334:40 | call to vector | vector.cpp:345:15:345:16 | v3 | | | vector.cpp:334:38:334:40 | call to vector | vector.cpp:348:7:348:8 | v3 | | -| vector.cpp:334:38:334:40 | call to vector | vector.cpp:354:1:354:1 | v3 | | +| vector.cpp:334:38:334:40 | call to vector | vector.cpp:382:1:382:1 | v3 | | | vector.cpp:334:46:334:48 | call to vector | vector.cpp:350:38:350:39 | v4 | | | vector.cpp:334:46:334:48 | call to vector | vector.cpp:350:56:350:57 | v4 | | | vector.cpp:334:46:334:48 | call to vector | vector.cpp:353:7:353:8 | v4 | | -| vector.cpp:334:46:334:48 | call to vector | vector.cpp:354:1:354:1 | v4 | | +| vector.cpp:334:46:334:48 | call to vector | vector.cpp:382:1:382:1 | v4 | | +| vector.cpp:334:54:334:56 | call to vector | vector.cpp:355:34:355:35 | v5 | | +| vector.cpp:334:54:334:56 | call to vector | vector.cpp:357:7:357:8 | v5 | | +| vector.cpp:334:54:334:56 | call to vector | vector.cpp:359:7:359:8 | v5 | | +| vector.cpp:334:54:334:56 | call to vector | vector.cpp:382:1:382:1 | v5 | | +| vector.cpp:334:62:334:64 | call to vector | vector.cpp:361:34:361:35 | v6 | | +| vector.cpp:334:62:334:64 | call to vector | vector.cpp:363:7:363:8 | v6 | | +| vector.cpp:334:62:334:64 | call to vector | vector.cpp:364:2:364:3 | v6 | | +| vector.cpp:334:62:334:64 | call to vector | vector.cpp:365:7:365:8 | v6 | | +| vector.cpp:334:62:334:64 | call to vector | vector.cpp:382:1:382:1 | v6 | | +| vector.cpp:334:70:334:72 | call to vector | vector.cpp:367:34:367:35 | v7 | | +| vector.cpp:334:70:334:72 | call to vector | vector.cpp:370:8:370:9 | v7 | | +| vector.cpp:334:70:334:72 | call to vector | vector.cpp:373:8:373:9 | v7 | | +| vector.cpp:334:70:334:72 | call to vector | vector.cpp:375:7:375:8 | v7 | | +| vector.cpp:334:70:334:72 | call to vector | vector.cpp:382:1:382:1 | v7 | | +| vector.cpp:334:78:334:80 | call to vector | vector.cpp:377:34:377:35 | v8 | | +| vector.cpp:334:78:334:80 | call to vector | vector.cpp:379:7:379:8 | v8 | | +| vector.cpp:334:78:334:80 | call to vector | vector.cpp:381:7:381:8 | v8 | | +| vector.cpp:334:78:334:80 | call to vector | vector.cpp:382:1:382:1 | v8 | | | vector.cpp:336:34:336:35 | ref arg v1 | vector.cpp:338:7:338:8 | v1 | | -| vector.cpp:336:34:336:35 | ref arg v1 | vector.cpp:354:1:354:1 | v1 | | +| vector.cpp:336:34:336:35 | ref arg v1 | vector.cpp:382:1:382:1 | v1 | | | vector.cpp:336:34:336:35 | v1 | vector.cpp:336:37:336:41 | call to begin | TAINT | | vector.cpp:336:37:336:41 | call to begin | vector.cpp:337:3:337:4 | i1 | | +| vector.cpp:337:2:337:2 | call to operator* [post update] | vector.cpp:338:7:338:8 | v1 | | +| vector.cpp:337:2:337:2 | call to operator* [post update] | vector.cpp:382:1:382:1 | v1 | | | vector.cpp:337:2:337:15 | ... = ... | vector.cpp:337:2:337:2 | call to operator* [post update] | | | vector.cpp:337:3:337:4 | i1 | vector.cpp:337:2:337:2 | call to operator* | TAINT | -| vector.cpp:337:8:337:13 | call to source | vector.cpp:336:34:336:35 | v1 | TAINT | +| vector.cpp:337:8:337:13 | call to source | vector.cpp:337:2:337:2 | call to operator* [post update] | TAINT | | vector.cpp:337:8:337:13 | call to source | vector.cpp:337:2:337:15 | ... = ... | | -| vector.cpp:337:8:337:13 | call to source | vector.cpp:338:7:338:8 | v1 | TAINT | -| vector.cpp:337:8:337:13 | call to source | vector.cpp:354:1:354:1 | v1 | TAINT | -| vector.cpp:338:7:338:8 | ref arg v1 | vector.cpp:354:1:354:1 | v1 | | +| vector.cpp:338:7:338:8 | ref arg v1 | vector.cpp:382:1:382:1 | v1 | | | vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:340:56:340:57 | v2 | | | vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:343:7:343:8 | v2 | | -| vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:354:1:354:1 | v2 | | +| vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:382:1:382:1 | v2 | | | vector.cpp:340:38:340:39 | v2 | vector.cpp:340:41:340:45 | call to begin | TAINT | | vector.cpp:340:41:340:45 | call to begin | vector.cpp:340:50:340:51 | it | | | vector.cpp:340:41:340:45 | call to begin | vector.cpp:340:68:340:69 | it | | | vector.cpp:340:41:340:45 | call to begin | vector.cpp:341:4:341:5 | it | | | vector.cpp:340:56:340:57 | ref arg v2 | vector.cpp:340:56:340:57 | v2 | | | vector.cpp:340:56:340:57 | ref arg v2 | vector.cpp:343:7:343:8 | v2 | | -| vector.cpp:340:56:340:57 | ref arg v2 | vector.cpp:354:1:354:1 | v2 | | +| vector.cpp:340:56:340:57 | ref arg v2 | vector.cpp:382:1:382:1 | v2 | | | vector.cpp:340:56:340:57 | v2 | vector.cpp:340:59:340:61 | call to end | TAINT | | vector.cpp:340:68:340:69 | it | vector.cpp:340:66:340:66 | call to operator++ | TAINT | | vector.cpp:340:68:340:69 | ref arg it | vector.cpp:340:50:340:51 | it | | | vector.cpp:340:68:340:69 | ref arg it | vector.cpp:340:68:340:69 | it | | | vector.cpp:340:68:340:69 | ref arg it | vector.cpp:341:4:341:5 | it | | +| vector.cpp:341:3:341:3 | call to operator* [post update] | vector.cpp:340:56:340:57 | v2 | | +| vector.cpp:341:3:341:3 | call to operator* [post update] | vector.cpp:343:7:343:8 | v2 | | +| vector.cpp:341:3:341:3 | call to operator* [post update] | vector.cpp:382:1:382:1 | v2 | | | vector.cpp:341:3:341:16 | ... = ... | vector.cpp:341:3:341:3 | call to operator* [post update] | | | vector.cpp:341:4:341:5 | it | vector.cpp:341:3:341:3 | call to operator* | TAINT | -| vector.cpp:341:9:341:14 | call to source | vector.cpp:340:38:340:39 | v2 | TAINT | -| vector.cpp:341:9:341:14 | call to source | vector.cpp:340:56:340:57 | v2 | TAINT | +| vector.cpp:341:9:341:14 | call to source | vector.cpp:341:3:341:3 | call to operator* [post update] | TAINT | | vector.cpp:341:9:341:14 | call to source | vector.cpp:341:3:341:16 | ... = ... | | -| vector.cpp:341:9:341:14 | call to source | vector.cpp:343:7:343:8 | v2 | TAINT | -| vector.cpp:341:9:341:14 | call to source | vector.cpp:354:1:354:1 | v2 | TAINT | -| vector.cpp:343:7:343:8 | ref arg v2 | vector.cpp:354:1:354:1 | v2 | | +| vector.cpp:343:7:343:8 | ref arg v2 | vector.cpp:382:1:382:1 | v2 | | | vector.cpp:345:15:345:15 | (__begin) | vector.cpp:345:15:345:15 | call to operator* | TAINT | | vector.cpp:345:15:345:15 | (__begin) | vector.cpp:345:15:345:15 | call to operator++ | TAINT | | vector.cpp:345:15:345:15 | (__end) | vector.cpp:345:15:345:15 | call to iterator | | @@ -3242,27 +3262,119 @@ | vector.cpp:345:15:345:16 | v3 | vector.cpp:345:15:345:15 | (__range) | | | vector.cpp:345:15:345:16 | v3 | vector.cpp:345:15:345:15 | call to operator* | TAINT | | vector.cpp:346:7:346:12 | call to source | vector.cpp:346:3:346:14 | ... = ... | | -| vector.cpp:348:7:348:8 | ref arg v3 | vector.cpp:354:1:354:1 | v3 | | +| vector.cpp:348:7:348:8 | ref arg v3 | vector.cpp:382:1:382:1 | v3 | | | vector.cpp:350:38:350:39 | ref arg v4 | vector.cpp:350:56:350:57 | v4 | | | vector.cpp:350:38:350:39 | ref arg v4 | vector.cpp:353:7:353:8 | v4 | | -| vector.cpp:350:38:350:39 | ref arg v4 | vector.cpp:354:1:354:1 | v4 | | +| vector.cpp:350:38:350:39 | ref arg v4 | vector.cpp:382:1:382:1 | v4 | | | vector.cpp:350:38:350:39 | v4 | vector.cpp:350:41:350:45 | call to begin | TAINT | | vector.cpp:350:41:350:45 | call to begin | vector.cpp:350:50:350:51 | it | | | vector.cpp:350:41:350:45 | call to begin | vector.cpp:350:68:350:69 | it | | | vector.cpp:350:41:350:45 | call to begin | vector.cpp:351:4:351:5 | it | | | vector.cpp:350:56:350:57 | ref arg v4 | vector.cpp:350:56:350:57 | v4 | | | vector.cpp:350:56:350:57 | ref arg v4 | vector.cpp:353:7:353:8 | v4 | | -| vector.cpp:350:56:350:57 | ref arg v4 | vector.cpp:354:1:354:1 | v4 | | +| vector.cpp:350:56:350:57 | ref arg v4 | vector.cpp:382:1:382:1 | v4 | | | vector.cpp:350:56:350:57 | v4 | vector.cpp:350:59:350:61 | call to end | TAINT | | vector.cpp:350:68:350:69 | it | vector.cpp:350:66:350:66 | call to operator++ | TAINT | | vector.cpp:350:68:350:69 | ref arg it | vector.cpp:350:50:350:51 | it | | | vector.cpp:350:68:350:69 | ref arg it | vector.cpp:350:68:350:69 | it | | | vector.cpp:350:68:350:69 | ref arg it | vector.cpp:351:4:351:5 | it | | +| vector.cpp:351:3:351:3 | call to operator* [post update] | vector.cpp:350:56:350:57 | v4 | | +| vector.cpp:351:3:351:3 | call to operator* [post update] | vector.cpp:353:7:353:8 | v4 | | +| vector.cpp:351:3:351:3 | call to operator* [post update] | vector.cpp:382:1:382:1 | v4 | | | vector.cpp:351:3:351:16 | ... = ... | vector.cpp:351:3:351:3 | call to operator* [post update] | | | vector.cpp:351:4:351:5 | it | vector.cpp:351:3:351:3 | call to operator* | TAINT | -| vector.cpp:351:9:351:14 | call to source | vector.cpp:350:38:350:39 | v4 | TAINT | -| vector.cpp:351:9:351:14 | call to source | vector.cpp:350:56:350:57 | v4 | TAINT | +| vector.cpp:351:9:351:14 | call to source | vector.cpp:351:3:351:3 | call to operator* [post update] | TAINT | | vector.cpp:351:9:351:14 | call to source | vector.cpp:351:3:351:16 | ... = ... | | -| vector.cpp:351:9:351:14 | call to source | vector.cpp:353:7:353:8 | v4 | TAINT | -| vector.cpp:351:9:351:14 | call to source | vector.cpp:354:1:354:1 | v4 | TAINT | -| vector.cpp:353:7:353:8 | ref arg v4 | vector.cpp:354:1:354:1 | v4 | | +| vector.cpp:353:7:353:8 | ref arg v4 | vector.cpp:382:1:382:1 | v4 | | +| vector.cpp:355:34:355:35 | ref arg v5 | vector.cpp:357:7:357:8 | v5 | | +| vector.cpp:355:34:355:35 | ref arg v5 | vector.cpp:359:7:359:8 | v5 | | +| vector.cpp:355:34:355:35 | ref arg v5 | vector.cpp:382:1:382:1 | v5 | | +| vector.cpp:355:34:355:35 | v5 | vector.cpp:355:37:355:41 | call to begin | TAINT | +| vector.cpp:355:37:355:41 | call to begin | vector.cpp:356:3:356:4 | i5 | | +| vector.cpp:355:37:355:41 | call to begin | vector.cpp:358:3:358:4 | i5 | | +| vector.cpp:356:2:356:2 | call to operator* [post update] | vector.cpp:357:7:357:8 | v5 | | +| vector.cpp:356:2:356:2 | call to operator* [post update] | vector.cpp:359:7:359:8 | v5 | | +| vector.cpp:356:2:356:2 | call to operator* [post update] | vector.cpp:382:1:382:1 | v5 | | +| vector.cpp:356:2:356:15 | ... = ... | vector.cpp:356:2:356:2 | call to operator* [post update] | | +| vector.cpp:356:3:356:4 | i5 | vector.cpp:356:2:356:2 | call to operator* | TAINT | +| vector.cpp:356:8:356:13 | call to source | vector.cpp:356:2:356:2 | call to operator* [post update] | TAINT | +| vector.cpp:356:8:356:13 | call to source | vector.cpp:356:2:356:15 | ... = ... | | +| vector.cpp:357:7:357:8 | ref arg v5 | vector.cpp:359:7:359:8 | v5 | | +| vector.cpp:357:7:357:8 | ref arg v5 | vector.cpp:382:1:382:1 | v5 | | +| vector.cpp:358:2:358:2 | call to operator* [post update] | vector.cpp:359:7:359:8 | v5 | | +| vector.cpp:358:2:358:2 | call to operator* [post update] | vector.cpp:382:1:382:1 | v5 | | +| vector.cpp:358:2:358:8 | ... = ... | vector.cpp:358:2:358:2 | call to operator* [post update] | | +| vector.cpp:358:3:358:4 | i5 | vector.cpp:358:2:358:2 | call to operator* | TAINT | +| vector.cpp:358:8:358:8 | 1 | vector.cpp:358:2:358:2 | call to operator* [post update] | TAINT | +| vector.cpp:358:8:358:8 | 1 | vector.cpp:358:2:358:8 | ... = ... | | +| vector.cpp:359:7:359:8 | ref arg v5 | vector.cpp:382:1:382:1 | v5 | | +| vector.cpp:361:34:361:35 | ref arg v6 | vector.cpp:363:7:363:8 | v6 | | +| vector.cpp:361:34:361:35 | ref arg v6 | vector.cpp:364:2:364:3 | v6 | | +| vector.cpp:361:34:361:35 | ref arg v6 | vector.cpp:365:7:365:8 | v6 | | +| vector.cpp:361:34:361:35 | ref arg v6 | vector.cpp:382:1:382:1 | v6 | | +| vector.cpp:361:34:361:35 | v6 | vector.cpp:361:37:361:41 | call to begin | TAINT | +| vector.cpp:361:37:361:41 | call to begin | vector.cpp:362:3:362:4 | i6 | | +| vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:363:7:363:8 | v6 | | +| vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:364:2:364:3 | v6 | | +| vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:365:7:365:8 | v6 | | +| vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:382:1:382:1 | v6 | | +| vector.cpp:362:2:362:15 | ... = ... | vector.cpp:362:2:362:2 | call to operator* [post update] | | +| vector.cpp:362:3:362:4 | i6 | vector.cpp:362:2:362:2 | call to operator* | TAINT | +| vector.cpp:362:8:362:13 | call to source | vector.cpp:362:2:362:2 | call to operator* [post update] | TAINT | +| vector.cpp:362:8:362:13 | call to source | vector.cpp:362:2:362:15 | ... = ... | | +| vector.cpp:363:7:363:8 | ref arg v6 | vector.cpp:364:2:364:3 | v6 | | +| vector.cpp:363:7:363:8 | ref arg v6 | vector.cpp:365:7:365:8 | v6 | | +| vector.cpp:363:7:363:8 | ref arg v6 | vector.cpp:382:1:382:1 | v6 | | +| vector.cpp:364:2:364:3 | ref arg v6 | vector.cpp:365:7:365:8 | v6 | | +| vector.cpp:364:2:364:3 | ref arg v6 | vector.cpp:382:1:382:1 | v6 | | +| vector.cpp:364:7:364:26 | call to vector | vector.cpp:364:2:364:3 | ref arg v6 | TAINT | +| vector.cpp:364:7:364:26 | call to vector | vector.cpp:364:5:364:5 | call to operator= | TAINT | +| vector.cpp:365:7:365:8 | ref arg v6 | vector.cpp:382:1:382:1 | v6 | | +| vector.cpp:367:34:367:35 | ref arg v7 | vector.cpp:370:8:370:9 | v7 | | +| vector.cpp:367:34:367:35 | ref arg v7 | vector.cpp:373:8:373:9 | v7 | | +| vector.cpp:367:34:367:35 | ref arg v7 | vector.cpp:375:7:375:8 | v7 | | +| vector.cpp:367:34:367:35 | ref arg v7 | vector.cpp:382:1:382:1 | v7 | | +| vector.cpp:367:34:367:35 | v7 | vector.cpp:367:37:367:41 | call to begin | TAINT | +| vector.cpp:367:37:367:41 | call to begin | vector.cpp:369:4:369:5 | i7 | | +| vector.cpp:367:37:367:41 | call to begin | vector.cpp:372:4:372:5 | i7 | | +| vector.cpp:369:3:369:3 | call to operator* [post update] | vector.cpp:370:8:370:9 | v7 | | +| vector.cpp:369:3:369:3 | call to operator* [post update] | vector.cpp:375:7:375:8 | v7 | | +| vector.cpp:369:3:369:3 | call to operator* [post update] | vector.cpp:382:1:382:1 | v7 | | +| vector.cpp:369:3:369:16 | ... = ... | vector.cpp:369:3:369:3 | call to operator* [post update] | | +| vector.cpp:369:4:369:5 | i7 | vector.cpp:369:3:369:3 | call to operator* | TAINT | +| vector.cpp:369:9:369:14 | call to source | vector.cpp:369:3:369:3 | call to operator* [post update] | TAINT | +| vector.cpp:369:9:369:14 | call to source | vector.cpp:369:3:369:16 | ... = ... | | +| vector.cpp:370:8:370:9 | ref arg v7 | vector.cpp:375:7:375:8 | v7 | | +| vector.cpp:370:8:370:9 | ref arg v7 | vector.cpp:382:1:382:1 | v7 | | +| vector.cpp:372:3:372:3 | call to operator* [post update] | vector.cpp:373:8:373:9 | v7 | | +| vector.cpp:372:3:372:3 | call to operator* [post update] | vector.cpp:375:7:375:8 | v7 | | +| vector.cpp:372:3:372:3 | call to operator* [post update] | vector.cpp:382:1:382:1 | v7 | | +| vector.cpp:372:3:372:9 | ... = ... | vector.cpp:372:3:372:3 | call to operator* [post update] | | +| vector.cpp:372:4:372:5 | i7 | vector.cpp:372:3:372:3 | call to operator* | TAINT | +| vector.cpp:372:9:372:9 | 1 | vector.cpp:372:3:372:3 | call to operator* [post update] | TAINT | +| vector.cpp:372:9:372:9 | 1 | vector.cpp:372:3:372:9 | ... = ... | | +| vector.cpp:373:8:373:9 | ref arg v7 | vector.cpp:375:7:375:8 | v7 | | +| vector.cpp:373:8:373:9 | ref arg v7 | vector.cpp:382:1:382:1 | v7 | | +| vector.cpp:375:7:375:8 | ref arg v7 | vector.cpp:382:1:382:1 | v7 | | +| vector.cpp:377:34:377:35 | ref arg v8 | vector.cpp:379:7:379:8 | v8 | | +| vector.cpp:377:34:377:35 | ref arg v8 | vector.cpp:381:7:381:8 | v8 | | +| vector.cpp:377:34:377:35 | ref arg v8 | vector.cpp:382:1:382:1 | v8 | | +| vector.cpp:377:34:377:35 | v8 | vector.cpp:377:37:377:41 | call to begin | TAINT | +| vector.cpp:377:37:377:41 | call to begin | vector.cpp:378:3:378:4 | i8 | | +| vector.cpp:377:37:377:41 | call to begin | vector.cpp:380:3:380:4 | i8 | | +| vector.cpp:378:2:378:2 | call to operator* [post update] | vector.cpp:379:7:379:8 | v8 | | +| vector.cpp:378:2:378:2 | call to operator* [post update] | vector.cpp:381:7:381:8 | v8 | | +| vector.cpp:378:2:378:2 | call to operator* [post update] | vector.cpp:382:1:382:1 | v8 | | +| vector.cpp:378:2:378:15 | ... = ... | vector.cpp:378:2:378:2 | call to operator* [post update] | | +| vector.cpp:378:3:378:4 | i8 | vector.cpp:378:2:378:2 | call to operator* | TAINT | +| vector.cpp:378:8:378:13 | call to source | vector.cpp:378:2:378:2 | call to operator* [post update] | TAINT | +| vector.cpp:378:8:378:13 | call to source | vector.cpp:378:2:378:15 | ... = ... | | +| vector.cpp:379:7:379:8 | ref arg v8 | vector.cpp:381:7:381:8 | v8 | | +| vector.cpp:379:7:379:8 | ref arg v8 | vector.cpp:382:1:382:1 | v8 | | +| vector.cpp:380:2:380:2 | call to operator* [post update] | vector.cpp:381:7:381:8 | v8 | | +| vector.cpp:380:2:380:2 | call to operator* [post update] | vector.cpp:382:1:382:1 | v8 | | +| vector.cpp:380:2:380:8 | ... = ... | vector.cpp:380:2:380:2 | call to operator* [post update] | | +| vector.cpp:380:3:380:4 | i8 | vector.cpp:380:2:380:2 | call to operator* | TAINT | +| vector.cpp:380:8:380:8 | 1 | vector.cpp:380:2:380:2 | call to operator* [post update] | TAINT | +| vector.cpp:380:8:380:8 | 1 | vector.cpp:380:2:380:8 | ... = ... | | +| vector.cpp:381:7:381:8 | ref arg v8 | vector.cpp:382:1:382:1 | v8 | | 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 6697e57e4a3..c8ed520e639 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -329,3 +329,11 @@ | vector.cpp:338:7:338:8 | v1 | vector.cpp:337:8:337:13 | call to source | | vector.cpp:343:7:343:8 | v2 | vector.cpp:341:9:341:14 | call to source | | vector.cpp:353:7:353:8 | v4 | vector.cpp:351:9:351:14 | call to source | +| vector.cpp:357:7:357:8 | v5 | vector.cpp:356:8:356:13 | call to source | +| vector.cpp:359:7:359:8 | v5 | vector.cpp:356:8:356:13 | call to source | +| vector.cpp:363:7:363:8 | v6 | vector.cpp:362:8:362:13 | call to source | +| vector.cpp:365:7:365:8 | v6 | vector.cpp:362:8:362:13 | call to source | +| vector.cpp:370:8:370:9 | v7 | vector.cpp:369:9:369:14 | call to source | +| vector.cpp:375:7:375:8 | v7 | vector.cpp:369:9:369:14 | call to source | +| vector.cpp:379:7:379:8 | v8 | vector.cpp:378:8:378:13 | call to source | +| vector.cpp:381:7:381:8 | v8 | vector.cpp:378:8:378:13 | 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 7533d079093..94f4cf9d2fe 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 @@ -278,3 +278,11 @@ | vector.cpp:338:7:338:8 | vector.cpp:337:8:337:13 | AST only | | vector.cpp:343:7:343:8 | vector.cpp:341:9:341:14 | AST only | | vector.cpp:353:7:353:8 | vector.cpp:351:9:351:14 | AST only | +| vector.cpp:357:7:357:8 | vector.cpp:356:8:356:13 | AST only | +| vector.cpp:359:7:359:8 | vector.cpp:356:8:356:13 | AST only | +| vector.cpp:363:7:363:8 | vector.cpp:362:8:362:13 | AST only | +| vector.cpp:365:7:365:8 | vector.cpp:362:8:362:13 | AST only | +| vector.cpp:370:8:370:9 | vector.cpp:369:9:369:14 | AST only | +| vector.cpp:375:7:375:8 | vector.cpp:369:9:369:14 | AST only | +| vector.cpp:379:7:379:8 | vector.cpp:378:8:378:13 | AST only | +| vector.cpp:381:7:381:8 | vector.cpp:378:8:378:13 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp index f1cf4e91457..35145c3d815 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp @@ -330,8 +330,8 @@ void taint_vector_output_iterator(std::vector::iterator iter) { *iter = source(); } -void test_vector_output_iterator() { - std::vector v1(10), v2(10), v3(10), v4(10); +void test_vector_output_iterator(int b) { + std::vector v1(10), v2(10), v3(10), v4(10), v5(10), v6(10), v7(10), v8(10); std::vector::iterator i1 = v1.begin(); *i1 = source(); @@ -351,4 +351,32 @@ void test_vector_output_iterator() { *it = source(); } sink(v4); // tainted [NOT DETECTED by IR] + + std::vector::iterator i5 = v5.begin(); + *i5 = source(); + sink(v5); // tainted [NOT DETECTED by IR] + *i5 = 1; + sink(v5); // tainted [NOT DETECTED by IR] + + std::vector::iterator i6 = v6.begin(); + *i6 = source(); + sink(v6); // tainted [NOT DETECTED by IR] + v6 = std::vector(10); + sink(v6); // [FALSE POSITIVE in AST] + + std::vector::iterator i7 = v7.begin(); + if(b) { + *i7 = source(); + sink(v7); // tainted [NOT DETECTED by IR] + } else { + *i7 = 1; + sink(v7); + } + sink(v7); // tainted [NOT DETECTED by IR] + + std::vector::iterator i8 = v8.begin(); + *i8 = source(); + sink(v8); // tainted [NOT DETECTED by IR] + *i8 = 1; + sink(v8); } From 2e187a51ae6db786322ed979e6fa449e494352a7 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 9 Sep 2020 12:45:06 -0700 Subject: [PATCH 006/411] C++: test for interprocedurl iterator flow --- .../dataflow/taint-tests/localTaint.expected | 12 +++--------- .../dataflow/taint-tests/taint.expected | 1 - .../dataflow/taint-tests/test_diff.expected | 1 - .../library-tests/dataflow/taint-tests/vector.cpp | 2 +- 4 files changed, 4 insertions(+), 12 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 c0f34638554..13d38363b35 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -3269,7 +3269,7 @@ | vector.cpp:350:38:350:39 | v4 | vector.cpp:350:41:350:45 | call to begin | TAINT | | vector.cpp:350:41:350:45 | call to begin | vector.cpp:350:50:350:51 | it | | | vector.cpp:350:41:350:45 | call to begin | vector.cpp:350:68:350:69 | it | | -| vector.cpp:350:41:350:45 | call to begin | vector.cpp:351:4:351:5 | it | | +| vector.cpp:350:41:350:45 | call to begin | vector.cpp:351:32:351:33 | it | | | vector.cpp:350:56:350:57 | ref arg v4 | vector.cpp:350:56:350:57 | v4 | | | vector.cpp:350:56:350:57 | ref arg v4 | vector.cpp:353:7:353:8 | v4 | | | vector.cpp:350:56:350:57 | ref arg v4 | vector.cpp:382:1:382:1 | v4 | | @@ -3277,14 +3277,8 @@ | vector.cpp:350:68:350:69 | it | vector.cpp:350:66:350:66 | call to operator++ | TAINT | | vector.cpp:350:68:350:69 | ref arg it | vector.cpp:350:50:350:51 | it | | | vector.cpp:350:68:350:69 | ref arg it | vector.cpp:350:68:350:69 | it | | -| vector.cpp:350:68:350:69 | ref arg it | vector.cpp:351:4:351:5 | it | | -| vector.cpp:351:3:351:3 | call to operator* [post update] | vector.cpp:350:56:350:57 | v4 | | -| vector.cpp:351:3:351:3 | call to operator* [post update] | vector.cpp:353:7:353:8 | v4 | | -| vector.cpp:351:3:351:3 | call to operator* [post update] | vector.cpp:382:1:382:1 | v4 | | -| vector.cpp:351:3:351:16 | ... = ... | vector.cpp:351:3:351:3 | call to operator* [post update] | | -| vector.cpp:351:4:351:5 | it | vector.cpp:351:3:351:3 | call to operator* | TAINT | -| vector.cpp:351:9:351:14 | call to source | vector.cpp:351:3:351:3 | call to operator* [post update] | TAINT | -| vector.cpp:351:9:351:14 | call to source | vector.cpp:351:3:351:16 | ... = ... | | +| vector.cpp:350:68:350:69 | ref arg it | vector.cpp:351:32:351:33 | it | | +| vector.cpp:351:32:351:33 | it | vector.cpp:351:32:351:33 | call to iterator | | | vector.cpp:353:7:353:8 | ref arg v4 | vector.cpp:382:1:382:1 | v4 | | | vector.cpp:355:34:355:35 | ref arg v5 | vector.cpp:357:7:357:8 | v5 | | | vector.cpp:355:34:355:35 | ref arg v5 | vector.cpp:359:7:359:8 | v5 | | 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 c8ed520e639..6759dd90d60 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -328,7 +328,6 @@ | vector.cpp:326:7:326:8 | v4 | vector.cpp:318:15:318:20 | call to source | | vector.cpp:338:7:338:8 | v1 | vector.cpp:337:8:337:13 | call to source | | vector.cpp:343:7:343:8 | v2 | vector.cpp:341:9:341:14 | call to source | -| vector.cpp:353:7:353:8 | v4 | vector.cpp:351:9:351:14 | call to source | | vector.cpp:357:7:357:8 | v5 | vector.cpp:356:8:356:13 | call to source | | vector.cpp:359:7:359:8 | v5 | vector.cpp:356:8:356:13 | call to source | | vector.cpp:363:7:363:8 | v6 | vector.cpp:362:8:362:13 | 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 94f4cf9d2fe..8fbeb0c246c 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 @@ -277,7 +277,6 @@ | vector.cpp:326:7:326:8 | vector.cpp:318:15:318:20 | AST only | | vector.cpp:338:7:338:8 | vector.cpp:337:8:337:13 | AST only | | vector.cpp:343:7:343:8 | vector.cpp:341:9:341:14 | AST only | -| vector.cpp:353:7:353:8 | vector.cpp:351:9:351:14 | AST only | | vector.cpp:357:7:357:8 | vector.cpp:356:8:356:13 | AST only | | vector.cpp:359:7:359:8 | vector.cpp:356:8:356:13 | AST only | | vector.cpp:363:7:363:8 | vector.cpp:362:8:362:13 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp index 35145c3d815..153385a202d 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp @@ -348,7 +348,7 @@ void test_vector_output_iterator(int b) { sink(v3); // tainted [NOT DETECTED] for(std::vector::iterator it = v4.begin(); it != v4.end(); ++it) { - *it = source(); + taint_vector_output_iterator(it); } sink(v4); // tainted [NOT DETECTED by IR] From 10633019a6081ee9b169d3a022d2132789e057af Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 9 Sep 2020 12:45:17 -0700 Subject: [PATCH 007/411] C++: autoformat --- .../semmle/code/cpp/dataflow/internal/FlowVar.qll | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll index cb2cdd68f08..c6929358543 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll @@ -130,10 +130,9 @@ private module PartialDefinitions { * Holds if this `PartialDefinition` defines variable `v` at control-flow * node `cfn`. */ - pragma[noinline] // does this work with a dispred? - predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn) { - none() - } + // does this work with a dispred? + pragma[noinline] + predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn) { none() } /** * Holds if this partial definition may modify `inner` (or what it points @@ -180,7 +179,7 @@ private module PartialDefinitions { inner = innerDefinedExpr and outer = this } - + override predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn) { v = collection and cfn = node @@ -198,7 +197,9 @@ private module PartialDefinitions { ) } - deprecated override predicate partiallyDefines(Variable v) { innerDefinedExpr = v.getAnAccess() } + deprecated override predicate partiallyDefines(Variable v) { + innerDefinedExpr = v.getAnAccess() + } deprecated override predicate partiallyDefinesThis(ThisExpr e) { innerDefinedExpr = e } @@ -214,7 +215,7 @@ private module PartialDefinitions { inner = innerDefinedExpr and outer = this } - + override predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn) { innerDefinedExpr = v.getAnAccess() and cfn = node From eb5782d90822bcf6f3551aa599c4e0a0dde0fd93 Mon Sep 17 00:00:00 2001 From: "lcartey@github.com" Date: Fri, 11 Sep 2020 17:12:10 +0100 Subject: [PATCH 008/411] C++: Support customizable ranges for RangeSsaDefinitions. --- .../interfaces/SimpleRangeAnalysisDef.qll | 34 +++++++++++++++++++ .../cpp/rangeanalysis/SimpleRangeAnalysis.qll | 10 ++++++ 2 files changed, 44 insertions(+) create mode 100644 cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisDef.qll diff --git a/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisDef.qll b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisDef.qll new file mode 100644 index 00000000000..c2647e2bebc --- /dev/null +++ b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisDef.qll @@ -0,0 +1,34 @@ +/** + * EXPERIMENTAL: The API of this module may change without notice. + * + * Provides a class for modeling `RangeSsaDefinition`s with a restricted range. + */ + +import cpp +import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis + +/** + * EXPERIMENTAL: The API of this class may change without notice. + * + * An SSA definition for which a range can be deduced. Extend this class to add + * functionality to the range analysis library. + */ +abstract class SimpleRangeAnalysisDefinition extends RangeSsaDefinition { + /** + * Gets the lower bound of the defomotopn. + * + * Implementations of this predicate should use + * `getFullyConvertedLowerBounds` and `getFullyConvertedUpperBounds` for + * recursive calls to get the bounds of their children. + */ + abstract float getLowerBounds(); + + /** + * Gets the upper bound of the definition. + * + * Implementations of this predicate should use + * `getFullyConvertedLowerBounds` and `getFullyConvertedUpperBounds` for + * recursive calls to get the bounds of their children. + */ + abstract float getUpperBounds(); +} \ No newline at end of file diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index c8a6e70ce1f..4c61c06c829 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -45,6 +45,7 @@ import cpp private import RangeAnalysisUtils private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr +private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisDef import RangeSSA import SimpleRangeAnalysisCached private import NanAnalysis @@ -492,6 +493,9 @@ private predicate analyzableDef(RangeSsaDefinition def, StackVariable v) { v = def.getAVariable() or phiDependsOnDef(def, v, _, _) + or + // A modeled def for range analysis + def.(SimpleRangeAnalysisDefinition).getAVariable() =v } /** @@ -1211,6 +1215,9 @@ private float getDefLowerBoundsImpl(RangeSsaDefinition def, StackVariable v) { // Phi nodes. result = getPhiLowerBounds(v, def) or + // A modeled def for range analysis + result = def.(SimpleRangeAnalysisDefinition).getLowerBounds() + or // Unanalyzable definitions. unanalyzableDefBounds(def, v, result, _) } @@ -1244,6 +1251,9 @@ private float getDefUpperBoundsImpl(RangeSsaDefinition def, StackVariable v) { // Phi nodes. result = getPhiUpperBounds(v, def) or + // A modeled def for range analysis + result = def.(SimpleRangeAnalysisDefinition).getUpperBounds() + or // Unanalyzable definitions. unanalyzableDefBounds(def, v, _, result) } From 826fc0a630cb4742875221c31ee3d9ab269b76ca Mon Sep 17 00:00:00 2001 From: Faten Healy <5361987+fatenhealy@users.noreply.github.com> Date: Sun, 13 Sep 2020 21:04:07 +1000 Subject: [PATCH 009/411] Update BrokenCryptoAlgorithm - Blowfish to AES --- python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp b/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp index 1b4031b1cc5..ba5ab4d10c1 100644 --- a/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp +++ b/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp @@ -33,7 +33,7 @@ pycrypto you must specify the encryption algorithm to use. The first example uses DES, which is an older algorithm that is now considered weak. The second - example uses Blowfish, which is a stronger more modern algorithm. + example uses AES, which is a stronger modern algorithm.

From 6f20516f8433bdab89610c805a360d5b0b9eb3ca Mon Sep 17 00:00:00 2001 From: Faten Healy <5361987+fatenhealy@users.noreply.github.com> Date: Sun, 13 Sep 2020 21:07:28 +1000 Subject: [PATCH 010/411] Update broken_crypto.py to AES instead of Blowfish --- python/ql/src/Security/CWE-327/examples/broken_crypto.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/Security/CWE-327/examples/broken_crypto.py b/python/ql/src/Security/CWE-327/examples/broken_crypto.py index ef9fc75e889..690ed0096b1 100644 --- a/python/ql/src/Security/CWE-327/examples/broken_crypto.py +++ b/python/ql/src/Security/CWE-327/examples/broken_crypto.py @@ -6,7 +6,7 @@ def send_encrypted(channel, message): channel.send(cipher.encrypt(message)) # BAD: weak encryption -cipher = Blowfish.new(SECRET_KEY) +cipher = AES.new(SECRET_KEY) def send_encrypted(channel, message): channel.send(cipher.encrypt(message)) # GOOD: strong encryption From d3653b3030954d82488ac06e5c3d752e805d5d0e Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 9 Sep 2020 15:23:31 +0200 Subject: [PATCH 011/411] add support for re-exports using the spread operator for NodeJS exports --- javascript/ql/src/semmle/javascript/NodeJS.qll | 16 ++++++++++++++++ .../library-tests/NodeJS/ModuleAccess.expected | 2 ++ .../NodeJS/Module_getAnExportedSymbol.expected | 3 +++ .../NodeJS/Module_getAnImport.expected | 1 + .../NodeJS/Module_getAnImportedModule.expected | 1 + .../test/library-tests/NodeJS/Modules.expected | 2 ++ .../NodeJS/NodeModule_exports.expected | 3 +++ .../test/library-tests/NodeJS/Require.expected | 1 + .../library-tests/NodeJS/RequireImport.expected | 1 + .../ql/test/library-tests/NodeJS/reexport/a.js | 3 +++ .../ql/test/library-tests/NodeJS/reexport/b.js | 6 ++++++ 11 files changed, 39 insertions(+) create mode 100644 javascript/ql/test/library-tests/NodeJS/reexport/a.js create mode 100644 javascript/ql/test/library-tests/NodeJS/reexport/b.js diff --git a/javascript/ql/src/semmle/javascript/NodeJS.qll b/javascript/ql/src/semmle/javascript/NodeJS.qll index 72aebbea6f7..e4557ca077a 100644 --- a/javascript/ql/src/semmle/javascript/NodeJS.qll +++ b/javascript/ql/src/semmle/javascript/NodeJS.qll @@ -55,6 +55,22 @@ class NodeModule extends Module { name = pwn.getPropertyName() ) or + // a re-export using spread-operator. E.g. `const foo = require("./foo"); module.exports = {bar: bar, ...foo};` + exists(ObjectExpr obj | obj.analyze().getAValue() = getAModuleExportsValue() | + obj + .getAProperty() + .(SpreadProperty) + .getInit() + .(SpreadElement) + .getOperand() + .flow() + .getALocalSource() + .asExpr() + .(Import) + .getImportedModule() + .exports(name, export) + ) + or // an externs definition (where appropriate) exists(PropAccess pacc | export = pacc | pacc.getBase().analyze().getAValue() = getAModuleExportsValue() and diff --git a/javascript/ql/test/library-tests/NodeJS/ModuleAccess.expected b/javascript/ql/test/library-tests/NodeJS/ModuleAccess.expected index 81fd8a8a0d0..214373771a9 100644 --- a/javascript/ql/test/library-tests/NodeJS/ModuleAccess.expected +++ b/javascript/ql/test/library-tests/NodeJS/ModuleAccess.expected @@ -1,2 +1,4 @@ | b.js:7:22:7:27 | module | | d.js:3:1:3:6 | module | +| reexport/a.js:1:1:1:6 | module | +| reexport/b.js:3:1:3:6 | module | diff --git a/javascript/ql/test/library-tests/NodeJS/Module_getAnExportedSymbol.expected b/javascript/ql/test/library-tests/NodeJS/Module_getAnExportedSymbol.expected index 5b7c6130a6a..45cdeb20853 100644 --- a/javascript/ql/test/library-tests/NodeJS/Module_getAnExportedSymbol.expected +++ b/javascript/ql/test/library-tests/NodeJS/Module_getAnExportedSymbol.expected @@ -1,4 +1,7 @@ | b.js:1:1:8:0 | | sneaky | | d.js:1:1:7:15 | | baz | +| reexport/a.js:1:1:3:1 | | foo | +| reexport/b.js:1:1:6:1 | | bar | +| reexport/b.js:1:1:6:1 | | foo | | sub/c.js:1:1:4:0 | | foo | | sub/f.js:1:1:4:17 | | bar | diff --git a/javascript/ql/test/library-tests/NodeJS/Module_getAnImport.expected b/javascript/ql/test/library-tests/NodeJS/Module_getAnImport.expected index d1cc2576141..4694ebca20b 100644 --- a/javascript/ql/test/library-tests/NodeJS/Module_getAnImport.expected +++ b/javascript/ql/test/library-tests/NodeJS/Module_getAnImport.expected @@ -15,4 +15,5 @@ | mjs-files/require-from-js.js:1:1:4:0 | | mjs-files/require-from-js.js:1:12:1:36 | require ... on-me') | | mjs-files/require-from-js.js:1:1:4:0 | | mjs-files/require-from-js.js:2:12:2:39 | require ... me.js') | | mjs-files/require-from-js.js:1:1:4:0 | | mjs-files/require-from-js.js:3:12:3:40 | require ... e.mjs') | +| reexport/b.js:1:1:6:1 | | reexport/b.js:1:11:1:24 | require("./a") | | sub/c.js:1:1:4:0 | | sub/c.js:1:1:1:15 | require('../a') | diff --git a/javascript/ql/test/library-tests/NodeJS/Module_getAnImportedModule.expected b/javascript/ql/test/library-tests/NodeJS/Module_getAnImportedModule.expected index 0fa0e65f359..7eca17b3bc8 100644 --- a/javascript/ql/test/library-tests/NodeJS/Module_getAnImportedModule.expected +++ b/javascript/ql/test/library-tests/NodeJS/Module_getAnImportedModule.expected @@ -8,4 +8,5 @@ | index.js:1:1:3:0 | | b.js:1:1:8:0 | | | mjs-files/require-from-js.js:1:1:4:0 | | mjs-files/depend-on-me.js:1:1:8:0 | | | mjs-files/require-from-js.js:1:1:4:0 | | mjs-files/depend-on-me.mjs:1:1:7:1 | | +| reexport/b.js:1:1:6:1 | | reexport/a.js:1:1:3:1 | | | sub/c.js:1:1:4:0 | | a.js:1:1:14:0 | | diff --git a/javascript/ql/test/library-tests/NodeJS/Modules.expected b/javascript/ql/test/library-tests/NodeJS/Modules.expected index 1ef82d0328e..3d834490e60 100644 --- a/javascript/ql/test/library-tests/NodeJS/Modules.expected +++ b/javascript/ql/test/library-tests/NodeJS/Modules.expected @@ -4,5 +4,7 @@ | e.js:1:1:6:0 | | e.js:0:0:0:0 | e.js | e.js | e | | index.js:1:1:3:0 | | index.js:0:0:0:0 | index.js | index.js | index | | mjs-files/require-from-js.js:1:1:4:0 | | mjs-files/require-from-js.js:0:0:0:0 | mjs-files/require-from-js.js | mjs-files/require-from-js.js | require-from-js | +| reexport/a.js:1:1:3:1 | | reexport/a.js:0:0:0:0 | reexport/a.js | reexport/a.js | a | +| reexport/b.js:1:1:6:1 | | reexport/b.js:0:0:0:0 | reexport/b.js | reexport/b.js | b | | sub/c.js:1:1:4:0 | | sub/c.js:0:0:0:0 | sub/c.js | sub/c.js | c | | sub/f.js:1:1:4:17 | | sub/f.js:0:0:0:0 | sub/f.js | sub/f.js | f | diff --git a/javascript/ql/test/library-tests/NodeJS/NodeModule_exports.expected b/javascript/ql/test/library-tests/NodeJS/NodeModule_exports.expected index 0c2384a6999..d73a69441af 100644 --- a/javascript/ql/test/library-tests/NodeJS/NodeModule_exports.expected +++ b/javascript/ql/test/library-tests/NodeJS/NodeModule_exports.expected @@ -2,5 +2,8 @@ | d.js:1:1:7:15 | | baz | d.js:4:2:4:8 | baz: 42 | | mjs-files/depend-on-me.js:1:1:8:0 | | add | mjs-files/depend-on-me.js:5:1:7:1 | export ... + y;\\n} | | mjs-files/depend-on-me.mjs:1:1:7:1 | | add | mjs-files/depend-on-me.mjs:5:1:7:1 | export ... + y;\\n} | +| reexport/a.js:1:1:3:1 | | foo | reexport/a.js:2:5:2:26 | foo: fu ... oo() {} | +| reexport/b.js:1:1:6:1 | | bar | reexport/b.js:4:5:4:26 | bar: fu ... ar() {} | +| reexport/b.js:1:1:6:1 | | foo | reexport/a.js:2:5:2:26 | foo: fu ... oo() {} | | sub/c.js:1:1:4:0 | | foo | sub/c.js:3:1:3:11 | exports.foo | | sub/f.js:1:1:4:17 | | bar | sub/f.js:4:1:4:11 | exports.bar | diff --git a/javascript/ql/test/library-tests/NodeJS/Require.expected b/javascript/ql/test/library-tests/NodeJS/Require.expected index 364ad6fe99d..67bc4fb1df8 100644 --- a/javascript/ql/test/library-tests/NodeJS/Require.expected +++ b/javascript/ql/test/library-tests/NodeJS/Require.expected @@ -19,4 +19,5 @@ | mjs-files/require-from-js.js:1:12:1:36 | require ... on-me') | | mjs-files/require-from-js.js:2:12:2:39 | require ... me.js') | | mjs-files/require-from-js.js:3:12:3:40 | require ... e.mjs') | +| reexport/b.js:1:11:1:24 | require("./a") | | sub/c.js:1:1:1:15 | require('../a') | diff --git a/javascript/ql/test/library-tests/NodeJS/RequireImport.expected b/javascript/ql/test/library-tests/NodeJS/RequireImport.expected index fe43bdcd3bd..04c897ce0c0 100644 --- a/javascript/ql/test/library-tests/NodeJS/RequireImport.expected +++ b/javascript/ql/test/library-tests/NodeJS/RequireImport.expected @@ -11,4 +11,5 @@ | mjs-files/require-from-js.js:1:12:1:36 | require ... on-me') | ./depend-on-me | mjs-files/depend-on-me.mjs:1:1:7:1 | | | mjs-files/require-from-js.js:2:12:2:39 | require ... me.js') | ./depend-on-me.js | mjs-files/depend-on-me.js:1:1:8:0 | | | mjs-files/require-from-js.js:3:12:3:40 | require ... e.mjs') | ./depend-on-me.mjs | mjs-files/depend-on-me.mjs:1:1:7:1 | | +| reexport/b.js:1:11:1:24 | require("./a") | ./a | reexport/a.js:1:1:3:1 | | | sub/c.js:1:1:1:15 | require('../a') | ../a | a.js:1:1:14:0 | | diff --git a/javascript/ql/test/library-tests/NodeJS/reexport/a.js b/javascript/ql/test/library-tests/NodeJS/reexport/a.js new file mode 100644 index 00000000000..ab33553c7cd --- /dev/null +++ b/javascript/ql/test/library-tests/NodeJS/reexport/a.js @@ -0,0 +1,3 @@ +module.exports = { + foo: function foo() {} +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/NodeJS/reexport/b.js b/javascript/ql/test/library-tests/NodeJS/reexport/b.js new file mode 100644 index 00000000000..59a34a4c7e2 --- /dev/null +++ b/javascript/ql/test/library-tests/NodeJS/reexport/b.js @@ -0,0 +1,6 @@ +const a = require("./a"); + +module.exports = { + bar: function bar() {}, + ...a +} \ No newline at end of file From 61f6580d1ec6a9e3b0980839e2ed062c7a2ccba1 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 9 Sep 2020 23:18:12 +0200 Subject: [PATCH 012/411] add API in `PackageExports.qll` for getting a value exported under a name --- .../src/semmle/javascript/PackageExports.qll | 20 +++++++++++++++---- .../library-tests/PackageExports/lib1/baz.js | 5 +++++ .../PackageExports/tests.expected | 9 +++++++++ .../library-tests/PackageExports/tests.ql | 4 ++++ 4 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 javascript/ql/test/library-tests/PackageExports/lib1/baz.js diff --git a/javascript/ql/src/semmle/javascript/PackageExports.qll b/javascript/ql/src/semmle/javascript/PackageExports.qll index b0d185b746c..b54f0b48351 100644 --- a/javascript/ql/src/semmle/javascript/PackageExports.qll +++ b/javascript/ql/src/semmle/javascript/PackageExports.qll @@ -40,7 +40,7 @@ DataFlow::Node getAValueExportedBy(PackageJSON packageJSON) { exists(DataFlow::SourceNode callee | callee = getAValueExportedBy(packageJSON).(DataFlow::NewNode).getCalleeNode().getALocalSource() | - result = callee.getAPropertyRead("prototype").getAPropertyWrite() + result = callee.getAPropertyRead("prototype").getAPropertyWrite().getRhs() or result = callee.(DataFlow::ClassNode).getAnInstanceMethod() ) @@ -68,10 +68,22 @@ DataFlow::Node getAValueExportedBy(PackageJSON packageJSON) { private DataFlow::Node getAnExportFromModule(Module mod) { result.analyze().getAValue() = mod.(NodeModule).getAModuleExportsValue() or - exists(ASTNode export | result.getEnclosingExpr() = export | mod.exports(_, export)) + result = getAnExportedValue(mod, _) +} + +/** + * Gets a value exported from `mod` under `name`. + */ +DataFlow::Node getAnExportedValue(Module mod, string name) { + exists(Property export | result.asExpr() = export.getInit() | mod.exports(name, export)) + or + result = + DataFlow::valueNode(any(ASTNode export | mod.exports(name, export))) + .(DataFlow::PropWrite) + .getRhs() or exists(ExportDeclaration export | - result = export.getSourceNode(_) and - mod = export.getTopLevel() + result = export.getSourceNode(name) and + mod = export.getEnclosingModule() ) } diff --git a/javascript/ql/test/library-tests/PackageExports/lib1/baz.js b/javascript/ql/test/library-tests/PackageExports/lib1/baz.js new file mode 100644 index 00000000000..6ed47ee1a69 --- /dev/null +++ b/javascript/ql/test/library-tests/PackageExports/lib1/baz.js @@ -0,0 +1,5 @@ +module.exports = { + // not imported from anywhere + foo: function foo() {}, + bar: function bar() {} +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/PackageExports/tests.expected b/javascript/ql/test/library-tests/PackageExports/tests.expected index 1bd02d82385..f6b6083517e 100644 --- a/javascript/ql/test/library-tests/PackageExports/tests.expected +++ b/javascript/ql/test/library-tests/PackageExports/tests.expected @@ -34,3 +34,12 @@ getAValueExportedBy | lib1/sublib/package.json:1:1:3:1 | {\\n " ... b.js"\\n} | lib1/sublib/sublib.js:1:1:1:0 | this | | lib1/sublib/package.json:1:1:3:1 | {\\n " ... b.js"\\n} | lib1/sublib/sublib.js:1:1:1:73 | module. ... rt() {} | | lib1/sublib/package.json:1:1:3:1 | {\\n " ... b.js"\\n} | lib1/sublib/sublib.js:1:18:1:73 | functio ... rt() {} | +getAnExportedValue +| absent_main/index.js:1:1:2:0 | | foo | absent_main/index.js:1:22:1:34 | function() {} | +| esmodules/main.js:1:1:4:0 | | exported | esmodules/main.js:1:8:1:29 | functio ... ed() {} | +| lib1/baz.js:1:1:5:1 | | bar | lib1/baz.js:4:10:4:26 | function bar() {} | +| lib1/baz.js:1:1:5:1 | | foo | lib1/baz.js:3:10:3:26 | function foo() {} | +| lib1/foo.js:1:1:3:47 | | foo | lib1/foo.js:3:22:3:47 | functio ... ed() {} | +| lib1/main.js:1:1:17:30 | | Baz | lib1/main.js:17:22:17:30 | new Baz() | +| lib1/main.js:1:1:17:30 | | bar | lib1/main.js:5:22:9:1 | class B ... () {}\\n} | +| lib1/main.js:1:1:17:30 | | foo | lib1/main.js:3:22:3:40 | require("./foo.js") | diff --git a/javascript/ql/test/library-tests/PackageExports/tests.ql b/javascript/ql/test/library-tests/PackageExports/tests.ql index 71b269cf8cd..49e47ad79d0 100644 --- a/javascript/ql/test/library-tests/PackageExports/tests.ql +++ b/javascript/ql/test/library-tests/PackageExports/tests.ql @@ -6,3 +6,7 @@ query PackageJSON getTopmostPackageJSON() { result = Exports::getTopmostPackageJ query DataFlow::Node getAValueExportedBy(PackageJSON json) { result = Exports::getAValueExportedBy(json) } + +query DataFlow::Node getAnExportedValue(Module mod, string name) { + result = Exports::getAnExportedValue(mod, name) +} \ No newline at end of file From 29457c52dc0b8b79f3866461f490ecf3628fb552 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 9 Sep 2020 23:37:45 +0200 Subject: [PATCH 013/411] add reexported test to PackageExports test --- .../PackageExports/lib1/reexport/a.js | 3 +++ .../PackageExports/lib1/reexport/b.js | 6 ++++++ .../library-tests/PackageExports/tests.expected | 15 +++++++++++++++ .../ql/test/library-tests/PackageExports/tests.ql | 4 +++- 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 javascript/ql/test/library-tests/PackageExports/lib1/reexport/a.js create mode 100644 javascript/ql/test/library-tests/PackageExports/lib1/reexport/b.js diff --git a/javascript/ql/test/library-tests/PackageExports/lib1/reexport/a.js b/javascript/ql/test/library-tests/PackageExports/lib1/reexport/a.js new file mode 100644 index 00000000000..554e1f29c54 --- /dev/null +++ b/javascript/ql/test/library-tests/PackageExports/lib1/reexport/a.js @@ -0,0 +1,3 @@ +module.exports = { + reexported: function reexported() {} +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/PackageExports/lib1/reexport/b.js b/javascript/ql/test/library-tests/PackageExports/lib1/reexport/b.js new file mode 100644 index 00000000000..5c3b111edb5 --- /dev/null +++ b/javascript/ql/test/library-tests/PackageExports/lib1/reexport/b.js @@ -0,0 +1,6 @@ +const a = require("./a"); + +module.exports = { + base: function base() {}, + ...a +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/PackageExports/tests.expected b/javascript/ql/test/library-tests/PackageExports/tests.expected index f6b6083517e..83ae0c2d2ad 100644 --- a/javascript/ql/test/library-tests/PackageExports/tests.expected +++ b/javascript/ql/test/library-tests/PackageExports/tests.expected @@ -43,3 +43,18 @@ getAnExportedValue | lib1/main.js:1:1:17:30 | | Baz | lib1/main.js:17:22:17:30 | new Baz() | | lib1/main.js:1:1:17:30 | | bar | lib1/main.js:5:22:9:1 | class B ... () {}\\n} | | lib1/main.js:1:1:17:30 | | foo | lib1/main.js:3:22:3:40 | require("./foo.js") | +| lib1/reexport/a.js:1:1:3:1 | | reexported | lib1/reexport/a.js:2:17:2:40 | functio ... ed() {} | +| lib1/reexport/b.js:1:1:6:1 | | base | lib1/reexport/b.js:4:11:4:28 | function base() {} | +| lib1/reexport/b.js:1:1:6:1 | | reexported | lib1/reexport/a.js:2:17:2:40 | functio ... ed() {} | +exports +| Baz | lib1/main.js:17:1:17:18 | module.exports.Baz | lib1/main.js:1:1:17:30 | | +| bar | lib1/baz.js:4:5:4:26 | bar: fu ... ar() {} | lib1/baz.js:1:1:5:1 | | +| bar | lib1/main.js:5:1:5:18 | module.exports.bar | lib1/main.js:1:1:17:30 | | +| base | lib1/reexport/b.js:4:5:4:28 | base: f ... se() {} | lib1/reexport/b.js:1:1:6:1 | | +| exported | esmodules/main.js:1:1:1:29 | export ... ed() {} | esmodules/main.js:1:1:4:0 | | +| foo | absent_main/index.js:1:1:1:18 | module.exports.foo | absent_main/index.js:1:1:2:0 | | +| foo | lib1/baz.js:3:5:3:26 | foo: fu ... oo() {} | lib1/baz.js:1:1:5:1 | | +| foo | lib1/foo.js:3:1:3:18 | module.exports.foo | lib1/foo.js:1:1:3:47 | | +| foo | lib1/main.js:3:1:3:18 | module.exports.foo | lib1/main.js:1:1:17:30 | | +| reexported | lib1/reexport/a.js:2:5:2:40 | reexpor ... ed() {} | lib1/reexport/a.js:1:1:3:1 | | +| reexported | lib1/reexport/a.js:2:5:2:40 | reexpor ... ed() {} | lib1/reexport/b.js:1:1:6:1 | | diff --git a/javascript/ql/test/library-tests/PackageExports/tests.ql b/javascript/ql/test/library-tests/PackageExports/tests.ql index 49e47ad79d0..efbc708a538 100644 --- a/javascript/ql/test/library-tests/PackageExports/tests.ql +++ b/javascript/ql/test/library-tests/PackageExports/tests.ql @@ -9,4 +9,6 @@ query DataFlow::Node getAValueExportedBy(PackageJSON json) { query DataFlow::Node getAnExportedValue(Module mod, string name) { result = Exports::getAnExportedValue(mod, name) -} \ No newline at end of file +} + +query Module exports(string name, ASTNode export) { result.exports(name, export) } From f2ecb63e5ae7209c2a9fd1c215c46ccbfdf22ae5 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 10 Sep 2020 00:05:39 +0200 Subject: [PATCH 014/411] add a direct Export step as a PreCallGraphStep --- .../src/semmle/javascript/frameworks/NodeJSLib.qll | 14 ++++++++++++++ .../TypeTracking/PredicateStyle.expected | 5 +++++ .../library-tests/TypeTracking/PredicateStyle.ql | 12 ++++++++++++ .../test/library-tests/TypeTracking/reexport/a.js | 3 +++ .../test/library-tests/TypeTracking/reexport/b.js | 6 ++++++ .../library-tests/TypeTracking/reexport/test.js | 4 ++++ 6 files changed, 44 insertions(+) create mode 100644 javascript/ql/test/library-tests/TypeTracking/reexport/a.js create mode 100644 javascript/ql/test/library-tests/TypeTracking/reexport/b.js create mode 100644 javascript/ql/test/library-tests/TypeTracking/reexport/test.js diff --git a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll index 53a5f18c0d4..e9dbe9980c8 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll @@ -638,6 +638,20 @@ module NodeJSLib { } } + private import semmle.javascript.PackageExports as Exports + + /** + * A direct step from an named export to a property-read reading the exported value. + */ + private class ExportsStep extends PreCallGraphStep { + override predicate step(DataFlow::Node pred, DataFlow::Node succ) { + exists(Import imp, string name | + succ = DataFlow::valueNode(imp).(DataFlow::SourceNode).getAPropertyRead(name) and + pred = Exports::getAnExportedValue(imp.getImportedModule(), name) + ) + } + } + /** * A call to a method from module `child_process`. */ diff --git a/javascript/ql/test/library-tests/TypeTracking/PredicateStyle.expected b/javascript/ql/test/library-tests/TypeTracking/PredicateStyle.expected index 53bbd6ec126..61d1675e794 100644 --- a/javascript/ql/test/library-tests/TypeTracking/PredicateStyle.expected +++ b/javascript/ql/test/library-tests/TypeTracking/PredicateStyle.expected @@ -70,3 +70,8 @@ dataValue | tst.js:51:30:51:33 | data | | tst.js:58:16:58:16 | x | | tst.js:68:16:68:19 | data | +reexport +| reexport/a.js:2:10:2:26 | function foo() {} | reexport/a.js:2:10:2:26 | function foo() {} | +| reexport/a.js:2:10:2:26 | function foo() {} | reexport/test.js:3:13:3:17 | b.foo | +| reexport/b.js:4:10:4:26 | function bar() {} | reexport/b.js:4:10:4:26 | function bar() {} | +| reexport/b.js:4:10:4:26 | function bar() {} | reexport/test.js:4:13:4:17 | b.bar | diff --git a/javascript/ql/test/library-tests/TypeTracking/PredicateStyle.ql b/javascript/ql/test/library-tests/TypeTracking/PredicateStyle.ql index eaac73bc55c..6e0859cb8e7 100644 --- a/javascript/ql/test/library-tests/TypeTracking/PredicateStyle.ql +++ b/javascript/ql/test/library-tests/TypeTracking/PredicateStyle.ql @@ -46,3 +46,15 @@ DataFlow::SourceNode dataValue(DataFlow::TypeTracker t) { } query DataFlow::SourceNode dataValue() { result = dataValue(DataFlow::TypeTracker::end()) } + +DataFlow::SourceNode reexport(DataFlow::TypeTracker t, DataFlow::FunctionNode func) { + t.start() and + func = result and + func.getFile().getParentContainer().getBaseName() = "reexport" + or + exists(DataFlow::TypeTracker t2 | result = reexport(t2, func).track(t2, t)) +} + +query DataFlow::SourceNode reexport(DataFlow::FunctionNode func) { + result = reexport(DataFlow::TypeTracker::end(), func) +} diff --git a/javascript/ql/test/library-tests/TypeTracking/reexport/a.js b/javascript/ql/test/library-tests/TypeTracking/reexport/a.js new file mode 100644 index 00000000000..ab33553c7cd --- /dev/null +++ b/javascript/ql/test/library-tests/TypeTracking/reexport/a.js @@ -0,0 +1,3 @@ +module.exports = { + foo: function foo() {} +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/TypeTracking/reexport/b.js b/javascript/ql/test/library-tests/TypeTracking/reexport/b.js new file mode 100644 index 00000000000..8b5f1a246c6 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeTracking/reexport/b.js @@ -0,0 +1,6 @@ +const a = require("./a"); + +module.exports = { + bar: function bar() {}, // name: bar + ...a +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/TypeTracking/reexport/test.js b/javascript/ql/test/library-tests/TypeTracking/reexport/test.js new file mode 100644 index 00000000000..c22470f14e9 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeTracking/reexport/test.js @@ -0,0 +1,4 @@ +const b = require("./b"); + +const foo = b.foo; +const bar = b.bar; \ No newline at end of file From c1cb19abd7ddc37e5e0688862bc8a7fc3f7a30d5 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 10 Sep 2020 00:32:35 +0200 Subject: [PATCH 015/411] add level PreCallGrapSteps to the callgraph --- .../src/semmle/javascript/dataflow/internal/CallGraphs.qll | 5 +++++ .../library-tests/CallGraphs/AnnotatedTest/reexport/a.js | 4 ++++ .../library-tests/CallGraphs/AnnotatedTest/reexport/b.js | 7 +++++++ .../CallGraphs/AnnotatedTest/reexport/import.js | 7 +++++++ 4 files changed, 23 insertions(+) create mode 100644 javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/reexport/a.js create mode 100644 javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/reexport/b.js create mode 100644 javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/reexport/import.js diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll b/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll index a1877de45e0..5b596dfb727 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll @@ -4,6 +4,7 @@ private import javascript private import semmle.javascript.dataflow.internal.StepSummary +private import semmle.javascript.dataflow.internal.PreCallGraphStep cached module CallGraph { @@ -48,6 +49,10 @@ module CallGraph { t.start() and AccessPath::step(function, result) or + t.start() and + imprecision = 0 and + PreCallGraphStep::step(any(DataFlow::Node n | function.flowsTo(n)), result) + or imprecision = 0 and exists(DataFlow::ClassNode cls | exists(string name | diff --git a/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/reexport/a.js b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/reexport/a.js new file mode 100644 index 00000000000..b6e65ec9d17 --- /dev/null +++ b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/reexport/a.js @@ -0,0 +1,4 @@ +module.exports = { + /** name:reexport.foo */ + foo: function foo() {} +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/reexport/b.js b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/reexport/b.js new file mode 100644 index 00000000000..f29148bf79b --- /dev/null +++ b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/reexport/b.js @@ -0,0 +1,7 @@ +const a = require("./a"); + +module.exports = { + /** name:reexport.bar */ + bar: function bar() {}, + ...a +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/reexport/import.js b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/reexport/import.js new file mode 100644 index 00000000000..e20e4a0c00f --- /dev/null +++ b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/reexport/import.js @@ -0,0 +1,7 @@ +const b = require("./b.js"); + +/** calls:reexport.foo */ +b.foo(); + +/** calls:reexport.bar */ +b.bar(); \ No newline at end of file From c5b5a4fd558ca3527bac46100be1b48a72aaa8cd Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 14 Sep 2020 20:39:51 +0200 Subject: [PATCH 016/411] improve performance of NodeJS::NodeModule::exports --- .../ql/src/semmle/javascript/NodeJS.qll | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/NodeJS.qll b/javascript/ql/src/semmle/javascript/NodeJS.qll index e4557ca077a..a4c1c0cbe70 100644 --- a/javascript/ql/src/semmle/javascript/NodeJS.qll +++ b/javascript/ql/src/semmle/javascript/NodeJS.qll @@ -42,6 +42,24 @@ class NodeModule extends Module { ) } + /** + * Gets an expression that is an alias for `module.exports`. + * For performance this predicate only computes relevant expressions. + * So if using this predicate - consider expanding the list of relevant expressions. + */ + pragma[noinline] + private DataFlow::Node getAModuleExportsNode() { + ( + // A bit of manual magic + result = any(DataFlow::PropWrite w | exists(w.getPropertyName())).getBase() + or + result = DataFlow::valueNode(any(PropAccess p | exists(p.getPropertyName())).getBase()) + or + result = DataFlow::valueNode(any(ObjectExpr obj)) + ) and + result.analyze().getAValue() = getAModuleExportsValue() + } + /** Gets a symbol exported by this module. */ override string getAnExportedSymbol() { result = super.getAnExportedSymbol() or @@ -51,12 +69,12 @@ class NodeModule extends Module { override predicate exports(string name, ASTNode export) { // a property write whose base is `exports` or `module.exports` exists(DataFlow::PropWrite pwn | export = pwn.getAstNode() | - pwn.getBase().analyze().getAValue() = getAModuleExportsValue() and + pwn.getBase() = getAModuleExportsNode() and name = pwn.getPropertyName() ) or // a re-export using spread-operator. E.g. `const foo = require("./foo"); module.exports = {bar: bar, ...foo};` - exists(ObjectExpr obj | obj.analyze().getAValue() = getAModuleExportsValue() | + exists(ObjectExpr obj | obj = getAModuleExportsNode().asExpr() | obj .getAProperty() .(SpreadProperty) @@ -73,7 +91,7 @@ class NodeModule extends Module { or // an externs definition (where appropriate) exists(PropAccess pacc | export = pacc | - pacc.getBase().analyze().getAValue() = getAModuleExportsValue() and + pacc.getBase() = getAModuleExportsNode().asExpr() and name = pacc.getPropertyName() and isExterns() and exists(pacc.getDocumentation()) From 5f2cafc4f5571f06928b43cbb37d97b5a7044640 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 14 Sep 2020 14:36:19 -0700 Subject: [PATCH 017/411] C++: Interprocedural iterator flow --- .../code/cpp/dataflow/internal/FlowVar.qll | 43 ++++++++++++++++--- .../dataflow/taint-tests/localTaint.expected | 17 ++++++++ .../dataflow/taint-tests/taint.expected | 1 + .../dataflow/taint-tests/test_diff.expected | 1 + 4 files changed, 56 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll index c6929358543..0163d1e0ce7 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll @@ -109,11 +109,10 @@ class FlowVar extends TFlowVar { * ``` */ private module PartialDefinitions { - class PartialDefinition extends Expr { + abstract class PartialDefinition extends Expr { ControlFlowNode node; PartialDefinition() { - valueToUpdate(_, this.getFullyConverted(), node) and not this instanceof Conversion } @@ -160,14 +159,39 @@ private module PartialDefinitions { class IteratorPartialDefinition extends PartialDefinition { Variable collection; - Call innerDefinedExpr; + Expr innerDefinedExpr; IteratorPartialDefinition() { exists(Expr convertedInner | valueToUpdate(convertedInner, this.getFullyConverted(), node) and innerDefinedExpr = convertedInner.getUnconverted() and - innerDefinedExpr.getQualifier() = getAnIteratorAccess(collection) and - innerDefinedExpr.getTarget() instanceof IteratorPointerDereferenceMemberOperator + ( + innerDefinedExpr.(Call).getQualifier() = getAnIteratorAccess(collection) + or + innerDefinedExpr.(Call).getQualifier() = collection.getAnAccess() and + collection instanceof IteratorParameter + ) and + innerDefinedExpr.(Call).getTarget() instanceof IteratorPointerDereferenceMemberOperator + ) + or + // iterators passed by value without a copy constructor + exists(Call call | + call = node and + call.getAnArgument() = innerDefinedExpr and + innerDefinedExpr = this and + this = getAnIteratorAccess(collection) and + not call.getTarget() instanceof IteratorPointerDereferenceMemberOperator + ) + or + // iterators passed by value with a copy constructor + exists(Call call, ConstructorCall copy | + copy.getTarget() instanceof CopyConstructor and + call = node and + call.getAnArgument() = copy and + copy.getArgument(0) = getAnIteratorAccess(collection) and + innerDefinedExpr = this and + this = copy and + not call.getTarget() instanceof IteratorPointerDereferenceMemberOperator ) } @@ -267,7 +291,8 @@ module FlowVar_internal { // The SSA library has a theoretically accurate treatment of reference types, // treating them as immutable, but for data flow it gives better results in // practice to make the variable synonymous with its contents. - not v.getUnspecifiedType() instanceof ReferenceType + not v.getUnspecifiedType() instanceof ReferenceType and + not v instanceof IteratorParameter } /** @@ -616,6 +641,8 @@ module FlowVar_internal { refType = p.getUnderlyingType() and not refType.getBaseType().isConst() ) + or + p instanceof IteratorParameter } /** @@ -778,6 +805,10 @@ module FlowVar_internal { ) } + class IteratorParameter extends Parameter { + IteratorParameter() { this.getUnspecifiedType() instanceof Iterator } + } + /** * Holds if `v` is initialized to have value `assignedExpr`. */ 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 13d38363b35..396fecf212f 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -439,23 +439,29 @@ | movableclass.cpp:65:13:65:18 | call to source | movableclass.cpp:65:13:65:20 | call to MyMovableClass | TAINT | | movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:8:65:9 | ref arg s3 | TAINT | | movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:11:65:11 | call to operator= | TAINT | +| standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:39:45:39:51 | source1 | | | standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:40:11:40:17 | source1 | | | standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:41:12:41:18 | source1 | | | 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:39:45:39:51 | source1 | | | 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: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 | ref arg source1 | standalone_iterators.cpp:39:45:39:51 | source1 | | | standalone_iterators.cpp:42:14:42:20 | source1 | standalone_iterators.cpp:42:12:42:12 | call to operator++ | TAINT | +| standalone_iterators.cpp:45:39:45:45 | source1 | standalone_iterators.cpp:45:39:45:45 | source1 | | | 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:45:39:45:45 | source1 | | | 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: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 | ref arg source1 | standalone_iterators.cpp:45:39:45:45 | source1 | | | standalone_iterators.cpp:48:14:48:20 | source1 | standalone_iterators.cpp:48:12:48:12 | call to operator++ | TAINT | | 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 | | @@ -2967,10 +2973,13 @@ | vector.cpp:255:3:255:4 | ref arg v6 | vector.cpp:262:2:262:2 | v6 | | | vector.cpp:255:13:255:14 | call to iterator | vector.cpp:255:3:255:4 | ref arg v6 | TAINT | | vector.cpp:255:13:255:14 | i1 | vector.cpp:255:13:255:14 | call to iterator | | +| vector.cpp:255:13:255:14 | ref arg call to iterator | vector.cpp:277:1:277:1 | v3 | | +| vector.cpp:255:13:255:14 | ref arg i1 | vector.cpp:277:1:277:1 | v3 | | | vector.cpp:255:17:255:18 | call to iterator | vector.cpp:255:3:255:4 | ref arg v6 | TAINT | | vector.cpp:255:17:255:18 | i2 | vector.cpp:255:17:255:18 | call to iterator | | | vector.cpp:257:8:257:9 | ref arg v4 | vector.cpp:262:2:262:2 | v4 | | | vector.cpp:258:8:258:9 | ref arg v5 | vector.cpp:262:2:262:2 | v5 | | +| vector.cpp:259:8:259:9 | ref arg i1 | vector.cpp:277:1:277:1 | v3 | | | vector.cpp:261:8:261:9 | ref arg v6 | vector.cpp:262:2:262:2 | v6 | | | vector.cpp:265:22:265:23 | call to vector | vector.cpp:269:3:269:4 | v7 | | | vector.cpp:265:22:265:23 | call to vector | vector.cpp:273:8:273:9 | v7 | | @@ -3173,7 +3182,9 @@ | vector.cpp:324:7:324:8 | ref arg v2 | vector.cpp:327:1:327:1 | v2 | | | vector.cpp:325:7:325:8 | ref arg v3 | vector.cpp:327:1:327:1 | v3 | | | vector.cpp:326:7:326:8 | ref arg v4 | vector.cpp:327:1:327:1 | v4 | | +| vector.cpp:329:62:329:65 | iter | vector.cpp:329:62:329:65 | iter | | | vector.cpp:329:62:329:65 | iter | vector.cpp:330:3:330:6 | iter | | +| vector.cpp:330:2:330:2 | call to operator* [post update] | vector.cpp:329:62:329:65 | iter | | | vector.cpp:330:2:330:17 | ... = ... | vector.cpp:330:2:330:2 | call to operator* [post update] | | | vector.cpp:330:3:330:6 | iter | vector.cpp:330:2:330:2 | call to operator* | TAINT | | vector.cpp:330:10:330:15 | call to source | vector.cpp:330:2:330:2 | call to operator* [post update] | TAINT | @@ -3279,6 +3290,12 @@ | vector.cpp:350:68:350:69 | ref arg it | vector.cpp:350:68:350:69 | it | | | vector.cpp:350:68:350:69 | ref arg it | vector.cpp:351:32:351:33 | it | | | vector.cpp:351:32:351:33 | it | vector.cpp:351:32:351:33 | call to iterator | | +| vector.cpp:351:32:351:33 | ref arg call to iterator | vector.cpp:350:56:350:57 | v4 | | +| vector.cpp:351:32:351:33 | ref arg call to iterator | vector.cpp:353:7:353:8 | v4 | | +| vector.cpp:351:32:351:33 | ref arg call to iterator | vector.cpp:382:1:382:1 | v4 | | +| vector.cpp:351:32:351:33 | ref arg it | vector.cpp:350:56:350:57 | v4 | | +| vector.cpp:351:32:351:33 | ref arg it | vector.cpp:353:7:353:8 | v4 | | +| vector.cpp:351:32:351:33 | ref arg it | vector.cpp:382:1:382:1 | v4 | | | vector.cpp:353:7:353:8 | ref arg v4 | vector.cpp:382:1:382:1 | v4 | | | vector.cpp:355:34:355:35 | ref arg v5 | vector.cpp:357:7:357:8 | v5 | | | vector.cpp:355:34:355:35 | ref arg v5 | vector.cpp:359:7:359:8 | v5 | | 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 6759dd90d60..889e1da17e6 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -328,6 +328,7 @@ | vector.cpp:326:7:326:8 | v4 | vector.cpp:318:15:318:20 | call to source | | vector.cpp:338:7:338:8 | v1 | vector.cpp:337:8:337:13 | call to source | | vector.cpp:343:7:343:8 | v2 | vector.cpp:341:9:341:14 | call to source | +| vector.cpp:353:7:353:8 | v4 | vector.cpp:330:10:330:15 | call to source | | vector.cpp:357:7:357:8 | v5 | vector.cpp:356:8:356:13 | call to source | | vector.cpp:359:7:359:8 | v5 | vector.cpp:356:8:356:13 | call to source | | vector.cpp:363:7:363:8 | v6 | vector.cpp:362:8:362:13 | 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 8fbeb0c246c..0f6b7a574a5 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 @@ -277,6 +277,7 @@ | vector.cpp:326:7:326:8 | vector.cpp:318:15:318:20 | AST only | | vector.cpp:338:7:338:8 | vector.cpp:337:8:337:13 | AST only | | vector.cpp:343:7:343:8 | vector.cpp:341:9:341:14 | AST only | +| vector.cpp:353:7:353:8 | vector.cpp:330:10:330:15 | AST only | | vector.cpp:357:7:357:8 | vector.cpp:356:8:356:13 | AST only | | vector.cpp:359:7:359:8 | vector.cpp:356:8:356:13 | AST only | | vector.cpp:363:7:363:8 | vector.cpp:362:8:362:13 | AST only | From fa0e27b2de6c9fa8d9fbe500b4ba7accda8b0cbe Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 16 Sep 2020 12:34:52 -0700 Subject: [PATCH 018/411] C++: move interprocedural iterator flow to taint --- .../code/cpp/dataflow/internal/DataFlowUtil.qll | 6 +++--- .../semmle/code/cpp/dataflow/internal/FlowVar.qll | 12 ++++++++---- .../cpp/dataflow/internal/TaintTrackingUtil.qll | 15 ++++++++++----- .../library-tests/dataflow/taint-tests/vector.cpp | 9 ++++++++- 4 files changed, 29 insertions(+), 13 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 9705ca492ce..1103e50ce16 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -303,7 +303,7 @@ private class VariablePartialDefinitionNode extends PartialDefinitionNode { override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) } } -private class IteratorPartialDefinitionNode extends PartialDefinitionNode { +class IteratorPartialDefinitionNode extends PartialDefinitionNode { override IteratorPartialDefinition pd; override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) } @@ -546,10 +546,10 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { or // In `f(&x->a)`, this step provides the flow from post-`&` to post-`x->a`, // from which there is field flow to `x` via reverse read. - exists(PartialDefinition def, Expr inner, Expr outer | + exists(VariablePartialDefinition def, Expr inner, Expr outer | def.definesExpressions(inner, outer) and inner = nodeTo.(InnerPartialDefinitionNode).getPreUpdateNode().asExpr() and - outer = nodeFrom.(PartialDefinitionNode).getPreUpdateNode().asExpr() + outer = nodeFrom.(VariablePartialDefinitionNode).getPreUpdateNode().asExpr() ) or // Reverse flow: data that flows from the post-update node of a reference diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll index 0163d1e0ce7..d4c264184d7 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll @@ -109,7 +109,7 @@ class FlowVar extends TFlowVar { * ``` */ private module PartialDefinitions { - abstract class PartialDefinition extends Expr { + class PartialDefinition extends Expr { ControlFlowNode node; PartialDefinition() { @@ -216,8 +216,7 @@ private module PartialDefinitions { VariablePartialDefinition() { exists(Expr convertedInner | valueToUpdate(convertedInner, this.getFullyConverted(), node) and - innerDefinedExpr = convertedInner.getUnconverted() and - not this instanceof Conversion + innerDefinedExpr = convertedInner.getUnconverted() ) } @@ -249,11 +248,16 @@ private module PartialDefinitions { /** * A partial definition that's a definition by reference. */ - class DefinitionByReference extends PartialDefinition { + class DefinitionByReference extends VariablePartialDefinition { DefinitionByReference() { exists(Call c | this = c.getAnArgument() or this = c.getQualifier()) } } } +predicate quickTest(PartialDefinition pd) { + pd instanceof DefinitionByReference and + pd instanceof IteratorPartialDefinition +} + import PartialDefinitions private import FlowVar_internal 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 c8d963866a1..f52c3cddf7e 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll @@ -31,6 +31,11 @@ predicate localTaintStep(DataFlow::Node src, DataFlow::Node sink) { */ predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) { localAdditionalTaintStep(src, sink) + or + exists(FunctionCall call, int i | + sink.(DataFlow::IteratorPartialDefinitionNode).getPartialDefinition().definesExpressions(_, call.getArgument(i)) and + src.(DataFlow::RefParameterFinalValueNode).getParameter() = call.getTarget().getParameter(i) + ) } /** @@ -258,9 +263,9 @@ private predicate exprToPartialDefinitionStep(Expr exprIn, Expr exprOut) { } private predicate iteratorDereference(Call c) { - c.getTarget() instanceof IteratorArrayMemberOperator - or - c.getTarget() instanceof IteratorPointerDereferenceMemberOperator - or - c.getTarget() instanceof IteratorPointerDereferenceOperator + c.getTarget() instanceof IteratorArrayMemberOperator + or + c.getTarget() instanceof IteratorPointerDereferenceMemberOperator + or + c.getTarget() instanceof IteratorPointerDereferenceOperator } diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp index 153385a202d..4fc63acbad2 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp @@ -331,7 +331,7 @@ void taint_vector_output_iterator(std::vector::iterator iter) { } void test_vector_output_iterator(int b) { - std::vector v1(10), v2(10), v3(10), v4(10), v5(10), v6(10), v7(10), v8(10); + std::vector v1(10), v2(10), v3(10), v4(10), v5(10), v6(10), v7(10), v8(10), v9(10); std::vector::iterator i1 = v1.begin(); *i1 = source(); @@ -379,4 +379,11 @@ void test_vector_output_iterator(int b) { sink(v8); // tainted [NOT DETECTED by IR] *i8 = 1; sink(v8); + + std::vector::iterator i9 = v9.begin(); + + *i9 = source(); + taint_vector_output_iterator(i9); + + sink(v9); } From 086d074a26e55d45ff6e7c70a91124eee0c3fac7 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 16 Sep 2020 12:48:38 -0700 Subject: [PATCH 019/411] C++: make PartialDefinition abstract --- .../src/semmle/code/cpp/dataflow/internal/FlowVar.qll | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll index d4c264184d7..45a537f8049 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll @@ -109,16 +109,16 @@ class FlowVar extends TFlowVar { * ``` */ private module PartialDefinitions { - class PartialDefinition extends Expr { + abstract class PartialDefinition extends Expr { ControlFlowNode node; PartialDefinition() { not this instanceof Conversion } - deprecated predicate partiallyDefines(Variable v) { none() } + deprecated abstract predicate partiallyDefines(Variable v); - deprecated predicate partiallyDefinesThis(ThisExpr e) { none() } + deprecated abstract predicate partiallyDefinesThis(ThisExpr e); /** * Gets the subBasicBlock where this `PartialDefinition` is defined. @@ -131,7 +131,7 @@ private module PartialDefinitions { */ // does this work with a dispred? pragma[noinline] - predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn) { none() } + abstract predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn); /** * Holds if this partial definition may modify `inner` (or what it points @@ -141,7 +141,7 @@ private module PartialDefinitions { * - `inner` = `... .x`, `outer` = `&...` * - `inner` = `a`, `outer` = `*` */ - predicate definesExpressions(Expr inner, Expr outer) { none() } + abstract predicate definesExpressions(Expr inner, Expr outer); /** * Gets the location of this element, adjusted to avoid unknown locations From 44c5233459a67643a405200398fb5dc70c60fea2 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 16 Sep 2020 12:49:15 -0700 Subject: [PATCH 020/411] C++: accept test output --- .../dataflow/taint-tests/localTaint.expected | 116 ++++++++++-------- .../dataflow/taint-tests/taint.expected | 2 + .../dataflow/taint-tests/test_diff.expected | 2 + 3 files changed, 72 insertions(+), 48 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 396fecf212f..e5e4905e395 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -2972,9 +2972,9 @@ | vector.cpp:255:3:255:4 | ref arg v6 | vector.cpp:261:8:261:9 | v6 | | | vector.cpp:255:3:255:4 | ref arg v6 | vector.cpp:262:2:262:2 | v6 | | | vector.cpp:255:13:255:14 | call to iterator | vector.cpp:255:3:255:4 | ref arg v6 | TAINT | +| vector.cpp:255:13:255:14 | call to iterator [post update] | vector.cpp:277:1:277:1 | v3 | | | vector.cpp:255:13:255:14 | i1 | vector.cpp:255:13:255:14 | call to iterator | | -| vector.cpp:255:13:255:14 | ref arg call to iterator | vector.cpp:277:1:277:1 | v3 | | -| vector.cpp:255:13:255:14 | ref arg i1 | vector.cpp:277:1:277:1 | v3 | | +| vector.cpp:255:13:255:14 | i1 [post update] | vector.cpp:277:1:277:1 | v3 | | | vector.cpp:255:17:255:18 | call to iterator | vector.cpp:255:3:255:4 | ref arg v6 | TAINT | | vector.cpp:255:17:255:18 | i2 | vector.cpp:255:17:255:18 | call to iterator | | | vector.cpp:257:8:257:9 | ref arg v4 | vector.cpp:262:2:262:2 | v4 | | @@ -3192,57 +3192,60 @@ | vector.cpp:333:38:333:38 | b | vector.cpp:368:5:368:5 | b | | | vector.cpp:334:22:334:24 | call to vector | vector.cpp:336:34:336:35 | v1 | | | vector.cpp:334:22:334:24 | call to vector | vector.cpp:338:7:338:8 | v1 | | -| vector.cpp:334:22:334:24 | call to vector | vector.cpp:382:1:382:1 | v1 | | +| vector.cpp:334:22:334:24 | call to vector | vector.cpp:389:1:389:1 | v1 | | | vector.cpp:334:30:334:32 | call to vector | vector.cpp:340:38:340:39 | v2 | | | vector.cpp:334:30:334:32 | call to vector | vector.cpp:340:56:340:57 | v2 | | | vector.cpp:334:30:334:32 | call to vector | vector.cpp:343:7:343:8 | v2 | | -| vector.cpp:334:30:334:32 | call to vector | vector.cpp:382:1:382:1 | v2 | | +| vector.cpp:334:30:334:32 | call to vector | vector.cpp:389:1:389:1 | v2 | | | vector.cpp:334:38:334:40 | call to vector | vector.cpp:345:15:345:16 | v3 | | | vector.cpp:334:38:334:40 | call to vector | vector.cpp:348:7:348:8 | v3 | | -| vector.cpp:334:38:334:40 | call to vector | vector.cpp:382:1:382:1 | v3 | | +| vector.cpp:334:38:334:40 | call to vector | vector.cpp:389:1:389:1 | v3 | | | vector.cpp:334:46:334:48 | call to vector | vector.cpp:350:38:350:39 | v4 | | | vector.cpp:334:46:334:48 | call to vector | vector.cpp:350:56:350:57 | v4 | | | vector.cpp:334:46:334:48 | call to vector | vector.cpp:353:7:353:8 | v4 | | -| vector.cpp:334:46:334:48 | call to vector | vector.cpp:382:1:382:1 | v4 | | +| vector.cpp:334:46:334:48 | call to vector | vector.cpp:389:1:389:1 | v4 | | | vector.cpp:334:54:334:56 | call to vector | vector.cpp:355:34:355:35 | v5 | | | vector.cpp:334:54:334:56 | call to vector | vector.cpp:357:7:357:8 | v5 | | | vector.cpp:334:54:334:56 | call to vector | vector.cpp:359:7:359:8 | v5 | | -| vector.cpp:334:54:334:56 | call to vector | vector.cpp:382:1:382:1 | v5 | | +| vector.cpp:334:54:334:56 | call to vector | vector.cpp:389:1:389:1 | v5 | | | vector.cpp:334:62:334:64 | call to vector | vector.cpp:361:34:361:35 | v6 | | | vector.cpp:334:62:334:64 | call to vector | vector.cpp:363:7:363:8 | v6 | | | vector.cpp:334:62:334:64 | call to vector | vector.cpp:364:2:364:3 | v6 | | | vector.cpp:334:62:334:64 | call to vector | vector.cpp:365:7:365:8 | v6 | | -| vector.cpp:334:62:334:64 | call to vector | vector.cpp:382:1:382:1 | v6 | | +| vector.cpp:334:62:334:64 | call to vector | vector.cpp:389:1:389:1 | v6 | | | vector.cpp:334:70:334:72 | call to vector | vector.cpp:367:34:367:35 | v7 | | | vector.cpp:334:70:334:72 | call to vector | vector.cpp:370:8:370:9 | v7 | | | vector.cpp:334:70:334:72 | call to vector | vector.cpp:373:8:373:9 | v7 | | | vector.cpp:334:70:334:72 | call to vector | vector.cpp:375:7:375:8 | v7 | | -| vector.cpp:334:70:334:72 | call to vector | vector.cpp:382:1:382:1 | v7 | | +| vector.cpp:334:70:334:72 | call to vector | vector.cpp:389:1:389:1 | v7 | | | vector.cpp:334:78:334:80 | call to vector | vector.cpp:377:34:377:35 | v8 | | | vector.cpp:334:78:334:80 | call to vector | vector.cpp:379:7:379:8 | v8 | | | vector.cpp:334:78:334:80 | call to vector | vector.cpp:381:7:381:8 | v8 | | -| vector.cpp:334:78:334:80 | call to vector | vector.cpp:382:1:382:1 | v8 | | +| vector.cpp:334:78:334:80 | call to vector | vector.cpp:389:1:389:1 | v8 | | +| vector.cpp:334:86:334:88 | call to vector | vector.cpp:383:34:383:35 | v9 | | +| vector.cpp:334:86:334:88 | call to vector | vector.cpp:388:7:388:8 | v9 | | +| vector.cpp:334:86:334:88 | call to vector | vector.cpp:389:1:389:1 | v9 | | | vector.cpp:336:34:336:35 | ref arg v1 | vector.cpp:338:7:338:8 | v1 | | -| vector.cpp:336:34:336:35 | ref arg v1 | vector.cpp:382:1:382:1 | v1 | | +| vector.cpp:336:34:336:35 | ref arg v1 | vector.cpp:389:1:389:1 | v1 | | | vector.cpp:336:34:336:35 | v1 | vector.cpp:336:37:336:41 | call to begin | TAINT | | vector.cpp:336:37:336:41 | call to begin | vector.cpp:337:3:337:4 | i1 | | | vector.cpp:337:2:337:2 | call to operator* [post update] | vector.cpp:338:7:338:8 | v1 | | -| vector.cpp:337:2:337:2 | call to operator* [post update] | vector.cpp:382:1:382:1 | v1 | | +| vector.cpp:337:2:337:2 | call to operator* [post update] | vector.cpp:389:1:389:1 | v1 | | | vector.cpp:337:2:337:15 | ... = ... | vector.cpp:337:2:337:2 | call to operator* [post update] | | | vector.cpp:337:3:337:4 | i1 | vector.cpp:337:2:337:2 | call to operator* | TAINT | | vector.cpp:337:8:337:13 | call to source | vector.cpp:337:2:337:2 | call to operator* [post update] | TAINT | | vector.cpp:337:8:337:13 | call to source | vector.cpp:337:2:337:15 | ... = ... | | -| vector.cpp:338:7:338:8 | ref arg v1 | vector.cpp:382:1:382:1 | v1 | | +| vector.cpp:338:7:338:8 | ref arg v1 | vector.cpp:389:1:389:1 | v1 | | | vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:340:56:340:57 | v2 | | | vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:343:7:343:8 | v2 | | -| vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:382:1:382:1 | v2 | | +| vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:389:1:389:1 | v2 | | | vector.cpp:340:38:340:39 | v2 | vector.cpp:340:41:340:45 | call to begin | TAINT | | vector.cpp:340:41:340:45 | call to begin | vector.cpp:340:50:340:51 | it | | | vector.cpp:340:41:340:45 | call to begin | vector.cpp:340:68:340:69 | it | | | vector.cpp:340:41:340:45 | call to begin | vector.cpp:341:4:341:5 | it | | | vector.cpp:340:56:340:57 | ref arg v2 | vector.cpp:340:56:340:57 | v2 | | | vector.cpp:340:56:340:57 | ref arg v2 | vector.cpp:343:7:343:8 | v2 | | -| vector.cpp:340:56:340:57 | ref arg v2 | vector.cpp:382:1:382:1 | v2 | | +| vector.cpp:340:56:340:57 | ref arg v2 | vector.cpp:389:1:389:1 | v2 | | | vector.cpp:340:56:340:57 | v2 | vector.cpp:340:59:340:61 | call to end | TAINT | | vector.cpp:340:68:340:69 | it | vector.cpp:340:66:340:66 | call to operator++ | TAINT | | vector.cpp:340:68:340:69 | ref arg it | vector.cpp:340:50:340:51 | it | | @@ -3250,12 +3253,12 @@ | vector.cpp:340:68:340:69 | ref arg it | vector.cpp:341:4:341:5 | it | | | vector.cpp:341:3:341:3 | call to operator* [post update] | vector.cpp:340:56:340:57 | v2 | | | vector.cpp:341:3:341:3 | call to operator* [post update] | vector.cpp:343:7:343:8 | v2 | | -| vector.cpp:341:3:341:3 | call to operator* [post update] | vector.cpp:382:1:382:1 | v2 | | +| vector.cpp:341:3:341:3 | call to operator* [post update] | vector.cpp:389:1:389:1 | v2 | | | vector.cpp:341:3:341:16 | ... = ... | vector.cpp:341:3:341:3 | call to operator* [post update] | | | vector.cpp:341:4:341:5 | it | vector.cpp:341:3:341:3 | call to operator* | TAINT | | vector.cpp:341:9:341:14 | call to source | vector.cpp:341:3:341:3 | call to operator* [post update] | TAINT | | vector.cpp:341:9:341:14 | call to source | vector.cpp:341:3:341:16 | ... = ... | | -| vector.cpp:343:7:343:8 | ref arg v2 | vector.cpp:382:1:382:1 | v2 | | +| vector.cpp:343:7:343:8 | ref arg v2 | vector.cpp:389:1:389:1 | v2 | | | vector.cpp:345:15:345:15 | (__begin) | vector.cpp:345:15:345:15 | call to operator* | TAINT | | vector.cpp:345:15:345:15 | (__begin) | vector.cpp:345:15:345:15 | call to operator++ | TAINT | | vector.cpp:345:15:345:15 | (__end) | vector.cpp:345:15:345:15 | call to iterator | | @@ -3273,119 +3276,136 @@ | vector.cpp:345:15:345:16 | v3 | vector.cpp:345:15:345:15 | (__range) | | | vector.cpp:345:15:345:16 | v3 | vector.cpp:345:15:345:15 | call to operator* | TAINT | | vector.cpp:346:7:346:12 | call to source | vector.cpp:346:3:346:14 | ... = ... | | -| vector.cpp:348:7:348:8 | ref arg v3 | vector.cpp:382:1:382:1 | v3 | | +| vector.cpp:348:7:348:8 | ref arg v3 | vector.cpp:389:1:389:1 | v3 | | | vector.cpp:350:38:350:39 | ref arg v4 | vector.cpp:350:56:350:57 | v4 | | | vector.cpp:350:38:350:39 | ref arg v4 | vector.cpp:353:7:353:8 | v4 | | -| vector.cpp:350:38:350:39 | ref arg v4 | vector.cpp:382:1:382:1 | v4 | | +| vector.cpp:350:38:350:39 | ref arg v4 | vector.cpp:389:1:389:1 | v4 | | | vector.cpp:350:38:350:39 | v4 | vector.cpp:350:41:350:45 | call to begin | TAINT | | vector.cpp:350:41:350:45 | call to begin | vector.cpp:350:50:350:51 | it | | | vector.cpp:350:41:350:45 | call to begin | vector.cpp:350:68:350:69 | it | | | vector.cpp:350:41:350:45 | call to begin | vector.cpp:351:32:351:33 | it | | | vector.cpp:350:56:350:57 | ref arg v4 | vector.cpp:350:56:350:57 | v4 | | | vector.cpp:350:56:350:57 | ref arg v4 | vector.cpp:353:7:353:8 | v4 | | -| vector.cpp:350:56:350:57 | ref arg v4 | vector.cpp:382:1:382:1 | v4 | | +| vector.cpp:350:56:350:57 | ref arg v4 | vector.cpp:389:1:389:1 | v4 | | | vector.cpp:350:56:350:57 | v4 | vector.cpp:350:59:350:61 | call to end | TAINT | | vector.cpp:350:68:350:69 | it | vector.cpp:350:66:350:66 | call to operator++ | TAINT | | vector.cpp:350:68:350:69 | ref arg it | vector.cpp:350:50:350:51 | it | | | vector.cpp:350:68:350:69 | ref arg it | vector.cpp:350:68:350:69 | it | | | vector.cpp:350:68:350:69 | ref arg it | vector.cpp:351:32:351:33 | it | | +| vector.cpp:351:32:351:33 | call to iterator [post update] | vector.cpp:350:56:350:57 | v4 | | +| vector.cpp:351:32:351:33 | call to iterator [post update] | vector.cpp:353:7:353:8 | v4 | | +| vector.cpp:351:32:351:33 | call to iterator [post update] | vector.cpp:389:1:389:1 | v4 | | | vector.cpp:351:32:351:33 | it | vector.cpp:351:32:351:33 | call to iterator | | -| vector.cpp:351:32:351:33 | ref arg call to iterator | vector.cpp:350:56:350:57 | v4 | | -| vector.cpp:351:32:351:33 | ref arg call to iterator | vector.cpp:353:7:353:8 | v4 | | -| vector.cpp:351:32:351:33 | ref arg call to iterator | vector.cpp:382:1:382:1 | v4 | | -| vector.cpp:351:32:351:33 | ref arg it | vector.cpp:350:56:350:57 | v4 | | -| vector.cpp:351:32:351:33 | ref arg it | vector.cpp:353:7:353:8 | v4 | | -| vector.cpp:351:32:351:33 | ref arg it | vector.cpp:382:1:382:1 | v4 | | -| vector.cpp:353:7:353:8 | ref arg v4 | vector.cpp:382:1:382:1 | v4 | | +| vector.cpp:351:32:351:33 | it [post update] | vector.cpp:350:56:350:57 | v4 | | +| vector.cpp:351:32:351:33 | it [post update] | vector.cpp:353:7:353:8 | v4 | | +| vector.cpp:351:32:351:33 | it [post update] | vector.cpp:389:1:389:1 | v4 | | +| vector.cpp:353:7:353:8 | ref arg v4 | vector.cpp:389:1:389:1 | v4 | | | vector.cpp:355:34:355:35 | ref arg v5 | vector.cpp:357:7:357:8 | v5 | | | vector.cpp:355:34:355:35 | ref arg v5 | vector.cpp:359:7:359:8 | v5 | | -| vector.cpp:355:34:355:35 | ref arg v5 | vector.cpp:382:1:382:1 | v5 | | +| vector.cpp:355:34:355:35 | ref arg v5 | vector.cpp:389:1:389:1 | v5 | | | vector.cpp:355:34:355:35 | v5 | vector.cpp:355:37:355:41 | call to begin | TAINT | | vector.cpp:355:37:355:41 | call to begin | vector.cpp:356:3:356:4 | i5 | | | vector.cpp:355:37:355:41 | call to begin | vector.cpp:358:3:358:4 | i5 | | | vector.cpp:356:2:356:2 | call to operator* [post update] | vector.cpp:357:7:357:8 | v5 | | | vector.cpp:356:2:356:2 | call to operator* [post update] | vector.cpp:359:7:359:8 | v5 | | -| vector.cpp:356:2:356:2 | call to operator* [post update] | vector.cpp:382:1:382:1 | v5 | | +| vector.cpp:356:2:356:2 | call to operator* [post update] | vector.cpp:389:1:389:1 | v5 | | | vector.cpp:356:2:356:15 | ... = ... | vector.cpp:356:2:356:2 | call to operator* [post update] | | | vector.cpp:356:3:356:4 | i5 | vector.cpp:356:2:356:2 | call to operator* | TAINT | | vector.cpp:356:8:356:13 | call to source | vector.cpp:356:2:356:2 | call to operator* [post update] | TAINT | | vector.cpp:356:8:356:13 | call to source | vector.cpp:356:2:356:15 | ... = ... | | | vector.cpp:357:7:357:8 | ref arg v5 | vector.cpp:359:7:359:8 | v5 | | -| vector.cpp:357:7:357:8 | ref arg v5 | vector.cpp:382:1:382:1 | v5 | | +| vector.cpp:357:7:357:8 | ref arg v5 | vector.cpp:389:1:389:1 | v5 | | | vector.cpp:358:2:358:2 | call to operator* [post update] | vector.cpp:359:7:359:8 | v5 | | -| vector.cpp:358:2:358:2 | call to operator* [post update] | vector.cpp:382:1:382:1 | v5 | | +| vector.cpp:358:2:358:2 | call to operator* [post update] | vector.cpp:389:1:389:1 | v5 | | | vector.cpp:358:2:358:8 | ... = ... | vector.cpp:358:2:358:2 | call to operator* [post update] | | | vector.cpp:358:3:358:4 | i5 | vector.cpp:358:2:358:2 | call to operator* | TAINT | | vector.cpp:358:8:358:8 | 1 | vector.cpp:358:2:358:2 | call to operator* [post update] | TAINT | | vector.cpp:358:8:358:8 | 1 | vector.cpp:358:2:358:8 | ... = ... | | -| vector.cpp:359:7:359:8 | ref arg v5 | vector.cpp:382:1:382:1 | v5 | | +| vector.cpp:359:7:359:8 | ref arg v5 | vector.cpp:389:1:389:1 | v5 | | | vector.cpp:361:34:361:35 | ref arg v6 | vector.cpp:363:7:363:8 | v6 | | | vector.cpp:361:34:361:35 | ref arg v6 | vector.cpp:364:2:364:3 | v6 | | | vector.cpp:361:34:361:35 | ref arg v6 | vector.cpp:365:7:365:8 | v6 | | -| vector.cpp:361:34:361:35 | ref arg v6 | vector.cpp:382:1:382:1 | v6 | | +| vector.cpp:361:34:361:35 | ref arg v6 | vector.cpp:389:1:389:1 | v6 | | | vector.cpp:361:34:361:35 | v6 | vector.cpp:361:37:361:41 | call to begin | TAINT | | vector.cpp:361:37:361:41 | call to begin | vector.cpp:362:3:362:4 | i6 | | | vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:363:7:363:8 | v6 | | | vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:364:2:364:3 | v6 | | | vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:365:7:365:8 | v6 | | -| vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:382:1:382:1 | v6 | | +| vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:389:1:389:1 | v6 | | | vector.cpp:362:2:362:15 | ... = ... | vector.cpp:362:2:362:2 | call to operator* [post update] | | | vector.cpp:362:3:362:4 | i6 | vector.cpp:362:2:362:2 | call to operator* | TAINT | | vector.cpp:362:8:362:13 | call to source | vector.cpp:362:2:362:2 | call to operator* [post update] | TAINT | | vector.cpp:362:8:362:13 | call to source | vector.cpp:362:2:362:15 | ... = ... | | | vector.cpp:363:7:363:8 | ref arg v6 | vector.cpp:364:2:364:3 | v6 | | | vector.cpp:363:7:363:8 | ref arg v6 | vector.cpp:365:7:365:8 | v6 | | -| vector.cpp:363:7:363:8 | ref arg v6 | vector.cpp:382:1:382:1 | v6 | | +| vector.cpp:363:7:363:8 | ref arg v6 | vector.cpp:389:1:389:1 | v6 | | | vector.cpp:364:2:364:3 | ref arg v6 | vector.cpp:365:7:365:8 | v6 | | -| vector.cpp:364:2:364:3 | ref arg v6 | vector.cpp:382:1:382:1 | v6 | | +| vector.cpp:364:2:364:3 | ref arg v6 | vector.cpp:389:1:389:1 | v6 | | | vector.cpp:364:7:364:26 | call to vector | vector.cpp:364:2:364:3 | ref arg v6 | TAINT | | vector.cpp:364:7:364:26 | call to vector | vector.cpp:364:5:364:5 | call to operator= | TAINT | -| vector.cpp:365:7:365:8 | ref arg v6 | vector.cpp:382:1:382:1 | v6 | | +| vector.cpp:365:7:365:8 | ref arg v6 | vector.cpp:389:1:389:1 | v6 | | | vector.cpp:367:34:367:35 | ref arg v7 | vector.cpp:370:8:370:9 | v7 | | | vector.cpp:367:34:367:35 | ref arg v7 | vector.cpp:373:8:373:9 | v7 | | | vector.cpp:367:34:367:35 | ref arg v7 | vector.cpp:375:7:375:8 | v7 | | -| vector.cpp:367:34:367:35 | ref arg v7 | vector.cpp:382:1:382:1 | v7 | | +| vector.cpp:367:34:367:35 | ref arg v7 | vector.cpp:389:1:389:1 | v7 | | | vector.cpp:367:34:367:35 | v7 | vector.cpp:367:37:367:41 | call to begin | TAINT | | vector.cpp:367:37:367:41 | call to begin | vector.cpp:369:4:369:5 | i7 | | | vector.cpp:367:37:367:41 | call to begin | vector.cpp:372:4:372:5 | i7 | | | vector.cpp:369:3:369:3 | call to operator* [post update] | vector.cpp:370:8:370:9 | v7 | | | vector.cpp:369:3:369:3 | call to operator* [post update] | vector.cpp:375:7:375:8 | v7 | | -| vector.cpp:369:3:369:3 | call to operator* [post update] | vector.cpp:382:1:382:1 | v7 | | +| vector.cpp:369:3:369:3 | call to operator* [post update] | vector.cpp:389:1:389:1 | v7 | | | vector.cpp:369:3:369:16 | ... = ... | vector.cpp:369:3:369:3 | call to operator* [post update] | | | vector.cpp:369:4:369:5 | i7 | vector.cpp:369:3:369:3 | call to operator* | TAINT | | vector.cpp:369:9:369:14 | call to source | vector.cpp:369:3:369:3 | call to operator* [post update] | TAINT | | vector.cpp:369:9:369:14 | call to source | vector.cpp:369:3:369:16 | ... = ... | | | vector.cpp:370:8:370:9 | ref arg v7 | vector.cpp:375:7:375:8 | v7 | | -| vector.cpp:370:8:370:9 | ref arg v7 | vector.cpp:382:1:382:1 | v7 | | +| vector.cpp:370:8:370:9 | ref arg v7 | vector.cpp:389:1:389:1 | v7 | | | vector.cpp:372:3:372:3 | call to operator* [post update] | vector.cpp:373:8:373:9 | v7 | | | vector.cpp:372:3:372:3 | call to operator* [post update] | vector.cpp:375:7:375:8 | v7 | | -| vector.cpp:372:3:372:3 | call to operator* [post update] | vector.cpp:382:1:382:1 | v7 | | +| vector.cpp:372:3:372:3 | call to operator* [post update] | vector.cpp:389:1:389:1 | v7 | | | vector.cpp:372:3:372:9 | ... = ... | vector.cpp:372:3:372:3 | call to operator* [post update] | | | vector.cpp:372:4:372:5 | i7 | vector.cpp:372:3:372:3 | call to operator* | TAINT | | vector.cpp:372:9:372:9 | 1 | vector.cpp:372:3:372:3 | call to operator* [post update] | TAINT | | vector.cpp:372:9:372:9 | 1 | vector.cpp:372:3:372:9 | ... = ... | | | vector.cpp:373:8:373:9 | ref arg v7 | vector.cpp:375:7:375:8 | v7 | | -| vector.cpp:373:8:373:9 | ref arg v7 | vector.cpp:382:1:382:1 | v7 | | -| vector.cpp:375:7:375:8 | ref arg v7 | vector.cpp:382:1:382:1 | v7 | | +| vector.cpp:373:8:373:9 | ref arg v7 | vector.cpp:389:1:389:1 | v7 | | +| vector.cpp:375:7:375:8 | ref arg v7 | vector.cpp:389:1:389:1 | v7 | | | vector.cpp:377:34:377:35 | ref arg v8 | vector.cpp:379:7:379:8 | v8 | | | vector.cpp:377:34:377:35 | ref arg v8 | vector.cpp:381:7:381:8 | v8 | | -| vector.cpp:377:34:377:35 | ref arg v8 | vector.cpp:382:1:382:1 | v8 | | +| vector.cpp:377:34:377:35 | ref arg v8 | vector.cpp:389:1:389:1 | v8 | | | vector.cpp:377:34:377:35 | v8 | vector.cpp:377:37:377:41 | call to begin | TAINT | | vector.cpp:377:37:377:41 | call to begin | vector.cpp:378:3:378:4 | i8 | | | vector.cpp:377:37:377:41 | call to begin | vector.cpp:380:3:380:4 | i8 | | | vector.cpp:378:2:378:2 | call to operator* [post update] | vector.cpp:379:7:379:8 | v8 | | | vector.cpp:378:2:378:2 | call to operator* [post update] | vector.cpp:381:7:381:8 | v8 | | -| vector.cpp:378:2:378:2 | call to operator* [post update] | vector.cpp:382:1:382:1 | v8 | | +| vector.cpp:378:2:378:2 | call to operator* [post update] | vector.cpp:389:1:389:1 | v8 | | | vector.cpp:378:2:378:15 | ... = ... | vector.cpp:378:2:378:2 | call to operator* [post update] | | | vector.cpp:378:3:378:4 | i8 | vector.cpp:378:2:378:2 | call to operator* | TAINT | | vector.cpp:378:8:378:13 | call to source | vector.cpp:378:2:378:2 | call to operator* [post update] | TAINT | | vector.cpp:378:8:378:13 | call to source | vector.cpp:378:2:378:15 | ... = ... | | | vector.cpp:379:7:379:8 | ref arg v8 | vector.cpp:381:7:381:8 | v8 | | -| vector.cpp:379:7:379:8 | ref arg v8 | vector.cpp:382:1:382:1 | v8 | | +| vector.cpp:379:7:379:8 | ref arg v8 | vector.cpp:389:1:389:1 | v8 | | | vector.cpp:380:2:380:2 | call to operator* [post update] | vector.cpp:381:7:381:8 | v8 | | -| vector.cpp:380:2:380:2 | call to operator* [post update] | vector.cpp:382:1:382:1 | v8 | | +| vector.cpp:380:2:380:2 | call to operator* [post update] | vector.cpp:389:1:389:1 | v8 | | | vector.cpp:380:2:380:8 | ... = ... | vector.cpp:380:2:380:2 | call to operator* [post update] | | | vector.cpp:380:3:380:4 | i8 | vector.cpp:380:2:380:2 | call to operator* | TAINT | | vector.cpp:380:8:380:8 | 1 | vector.cpp:380:2:380:2 | call to operator* [post update] | TAINT | | vector.cpp:380:8:380:8 | 1 | vector.cpp:380:2:380:8 | ... = ... | | -| vector.cpp:381:7:381:8 | ref arg v8 | vector.cpp:382:1:382:1 | v8 | | +| vector.cpp:381:7:381:8 | ref arg v8 | vector.cpp:389:1:389:1 | v8 | | +| vector.cpp:383:34:383:35 | ref arg v9 | vector.cpp:388:7:388:8 | v9 | | +| vector.cpp:383:34:383:35 | ref arg v9 | vector.cpp:389:1:389:1 | v9 | | +| vector.cpp:383:34:383:35 | v9 | vector.cpp:383:37:383:41 | call to begin | TAINT | +| vector.cpp:383:37:383:41 | call to begin | vector.cpp:385:3:385:4 | i9 | | +| vector.cpp:383:37:383:41 | call to begin | vector.cpp:386:31:386:32 | i9 | | +| vector.cpp:385:2:385:2 | call to operator* [post update] | vector.cpp:388:7:388:8 | v9 | | +| vector.cpp:385:2:385:2 | call to operator* [post update] | vector.cpp:389:1:389:1 | v9 | | +| vector.cpp:385:2:385:15 | ... = ... | vector.cpp:385:2:385:2 | call to operator* [post update] | | +| vector.cpp:385:3:385:4 | i9 | vector.cpp:385:2:385:2 | call to operator* | TAINT | +| vector.cpp:385:8:385:13 | call to source | vector.cpp:385:2:385:2 | call to operator* [post update] | TAINT | +| vector.cpp:385:8:385:13 | call to source | vector.cpp:385:2:385:15 | ... = ... | | +| vector.cpp:386:31:386:32 | call to iterator [post update] | vector.cpp:388:7:388:8 | v9 | | +| vector.cpp:386:31:386:32 | call to iterator [post update] | vector.cpp:389:1:389:1 | v9 | | +| vector.cpp:386:31:386:32 | i9 | vector.cpp:386:31:386:32 | call to iterator | | +| vector.cpp:386:31:386:32 | i9 [post update] | vector.cpp:388:7:388:8 | v9 | | +| vector.cpp:386:31:386:32 | i9 [post update] | vector.cpp:389:1:389:1 | v9 | | +| vector.cpp:388:7:388:8 | ref arg v9 | vector.cpp:389:1:389:1 | v9 | | 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 889e1da17e6..01ef2e1a494 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -337,3 +337,5 @@ | vector.cpp:375:7:375:8 | v7 | vector.cpp:369:9:369:14 | call to source | | vector.cpp:379:7:379:8 | v8 | vector.cpp:378:8:378:13 | call to source | | vector.cpp:381:7:381:8 | v8 | vector.cpp:378:8:378:13 | call to source | +| vector.cpp:388:7:388:8 | v9 | vector.cpp:330:10:330:15 | call to source | +| vector.cpp:388:7:388:8 | v9 | vector.cpp:385:8:385:13 | 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 0f6b7a574a5..173bb28f831 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 @@ -286,3 +286,5 @@ | vector.cpp:375:7:375:8 | vector.cpp:369:9:369:14 | AST only | | vector.cpp:379:7:379:8 | vector.cpp:378:8:378:13 | AST only | | vector.cpp:381:7:381:8 | vector.cpp:378:8:378:13 | AST only | +| vector.cpp:388:7:388:8 | vector.cpp:330:10:330:15 | AST only | +| vector.cpp:388:7:388:8 | vector.cpp:385:8:385:13 | AST only | From 107e9770da5ebde3e06ba7fefd5952a0154ed105 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 18 Sep 2020 14:12:33 -0700 Subject: [PATCH 021/411] C++: remove accidentally committed test code --- cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll | 5 ----- 1 file changed, 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll index 45a537f8049..b9e5eadfcf5 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll @@ -253,11 +253,6 @@ private module PartialDefinitions { } } -predicate quickTest(PartialDefinition pd) { - pd instanceof DefinitionByReference and - pd instanceof IteratorPartialDefinition -} - import PartialDefinitions private import FlowVar_internal From b84bf5e9bb5a3a4562592a558290d476b68f83d3 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 18 Sep 2020 14:18:38 -0700 Subject: [PATCH 022/411] C++: QLDoc for IteratorPartialDefinitionNode --- .../src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll | 6 ++++++ 1 file changed, 6 insertions(+) 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 faa242aec64..d71b3a4ad62 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -304,6 +304,12 @@ private class VariablePartialDefinitionNode extends PartialDefinitionNode { override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) } } +/** + * INTERNAL: do not use. + * + * A synthetic data flow node used for flow into a collection when an iterator + * write occurs in a callee. + */ class IteratorPartialDefinitionNode extends PartialDefinitionNode { override IteratorPartialDefinition pd; From bd7f5a41d1016b001fa1f8dbf3988fac6d93cfb1 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 18 Sep 2020 14:19:29 -0700 Subject: [PATCH 023/411] C++: autoformat --- .../semmle/code/cpp/dataflow/internal/DataFlowUtil.qll | 8 +++----- cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll | 8 +++----- 2 files changed, 6 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 d71b3a4ad62..963f1a17826 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -284,12 +284,10 @@ abstract class PostUpdateNode extends Node { override Location getLocation() { result = getPreUpdateNode().getLocation() } } -private abstract class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode { +abstract private class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode { PartialDefinition pd; - PartialDefinitionNode() { - this = TPartialDefinitionNode(pd) - } + PartialDefinitionNode() { this = TPartialDefinitionNode(pd) } override Location getLocation() { result = pd.getActualLocation() } @@ -306,7 +304,7 @@ private class VariablePartialDefinitionNode extends PartialDefinitionNode { /** * INTERNAL: do not use. - * + * * A synthetic data flow node used for flow into a collection when an iterator * write occurs in a callee. */ diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll index b9e5eadfcf5..13f11f8b275 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll @@ -112,13 +112,11 @@ private module PartialDefinitions { abstract class PartialDefinition extends Expr { ControlFlowNode node; - PartialDefinition() { - not this instanceof Conversion - } + PartialDefinition() { not this instanceof Conversion } - deprecated abstract predicate partiallyDefines(Variable v); + abstract deprecated predicate partiallyDefines(Variable v); - deprecated abstract predicate partiallyDefinesThis(ThisExpr e); + abstract deprecated predicate partiallyDefinesThis(ThisExpr e); /** * Gets the subBasicBlock where this `PartialDefinition` is defined. From 913881b17b869602b45e37d5044949e1ba72bde8 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 21 Sep 2020 16:10:37 -0700 Subject: [PATCH 024/411] C++: Add test for iterator false positive --- .../dataflow/taint-tests/localTaint.expected | 476 ++++++++++-------- .../dataflow/taint-tests/taint.expected | 28 +- .../dataflow/taint-tests/test_diff.expected | 28 +- .../dataflow/taint-tests/vector.cpp | 14 +- 4 files changed, 298 insertions(+), 248 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 ae2bc9b563e..365216bce3c 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -3701,224 +3701,258 @@ | vector.cpp:330:3:330:6 | iter | vector.cpp:330:2:330:2 | call to operator* | TAINT | | vector.cpp:330:10:330:15 | call to source | vector.cpp:330:2:330:2 | call to operator* [post update] | TAINT | | vector.cpp:330:10:330:15 | call to source | vector.cpp:330:2:330:17 | ... = ... | | -| vector.cpp:333:38:333:38 | b | vector.cpp:368:5:368:5 | b | | -| vector.cpp:334:22:334:24 | call to vector | vector.cpp:336:34:336:35 | v1 | | -| vector.cpp:334:22:334:24 | call to vector | vector.cpp:338:7:338:8 | v1 | | -| vector.cpp:334:22:334:24 | call to vector | vector.cpp:389:1:389:1 | v1 | | -| vector.cpp:334:30:334:32 | call to vector | vector.cpp:340:38:340:39 | v2 | | -| vector.cpp:334:30:334:32 | call to vector | vector.cpp:340:56:340:57 | v2 | | -| vector.cpp:334:30:334:32 | call to vector | vector.cpp:343:7:343:8 | v2 | | -| vector.cpp:334:30:334:32 | call to vector | vector.cpp:389:1:389:1 | v2 | | -| vector.cpp:334:38:334:40 | call to vector | vector.cpp:345:15:345:16 | v3 | | -| vector.cpp:334:38:334:40 | call to vector | vector.cpp:348:7:348:8 | v3 | | -| vector.cpp:334:38:334:40 | call to vector | vector.cpp:389:1:389:1 | v3 | | -| vector.cpp:334:46:334:48 | call to vector | vector.cpp:350:38:350:39 | v4 | | -| vector.cpp:334:46:334:48 | call to vector | vector.cpp:350:56:350:57 | v4 | | -| vector.cpp:334:46:334:48 | call to vector | vector.cpp:353:7:353:8 | v4 | | -| vector.cpp:334:46:334:48 | call to vector | vector.cpp:389:1:389:1 | v4 | | -| vector.cpp:334:54:334:56 | call to vector | vector.cpp:355:34:355:35 | v5 | | -| vector.cpp:334:54:334:56 | call to vector | vector.cpp:357:7:357:8 | v5 | | -| vector.cpp:334:54:334:56 | call to vector | vector.cpp:359:7:359:8 | v5 | | -| vector.cpp:334:54:334:56 | call to vector | vector.cpp:389:1:389:1 | v5 | | -| vector.cpp:334:62:334:64 | call to vector | vector.cpp:361:34:361:35 | v6 | | -| vector.cpp:334:62:334:64 | call to vector | vector.cpp:363:7:363:8 | v6 | | -| vector.cpp:334:62:334:64 | call to vector | vector.cpp:364:2:364:3 | v6 | | -| vector.cpp:334:62:334:64 | call to vector | vector.cpp:365:7:365:8 | v6 | | -| vector.cpp:334:62:334:64 | call to vector | vector.cpp:389:1:389:1 | v6 | | -| vector.cpp:334:70:334:72 | call to vector | vector.cpp:367:34:367:35 | v7 | | -| vector.cpp:334:70:334:72 | call to vector | vector.cpp:370:8:370:9 | v7 | | -| vector.cpp:334:70:334:72 | call to vector | vector.cpp:373:8:373:9 | v7 | | -| vector.cpp:334:70:334:72 | call to vector | vector.cpp:375:7:375:8 | v7 | | -| vector.cpp:334:70:334:72 | call to vector | vector.cpp:389:1:389:1 | v7 | | -| vector.cpp:334:78:334:80 | call to vector | vector.cpp:377:34:377:35 | v8 | | -| vector.cpp:334:78:334:80 | call to vector | vector.cpp:379:7:379:8 | v8 | | -| vector.cpp:334:78:334:80 | call to vector | vector.cpp:381:7:381:8 | v8 | | -| vector.cpp:334:78:334:80 | call to vector | vector.cpp:389:1:389:1 | v8 | | -| vector.cpp:334:86:334:88 | call to vector | vector.cpp:383:34:383:35 | v9 | | -| vector.cpp:334:86:334:88 | call to vector | vector.cpp:388:7:388:8 | v9 | | -| vector.cpp:334:86:334:88 | call to vector | vector.cpp:389:1:389:1 | v9 | | -| vector.cpp:336:34:336:35 | ref arg v1 | vector.cpp:338:7:338:8 | v1 | | -| vector.cpp:336:34:336:35 | ref arg v1 | vector.cpp:389:1:389:1 | v1 | | -| vector.cpp:336:34:336:35 | v1 | vector.cpp:336:37:336:41 | call to begin | TAINT | -| vector.cpp:336:37:336:41 | call to begin | vector.cpp:337:3:337:4 | i1 | | -| vector.cpp:337:2:337:2 | call to operator* [post update] | vector.cpp:338:7:338:8 | v1 | | -| vector.cpp:337:2:337:2 | call to operator* [post update] | vector.cpp:389:1:389:1 | v1 | | -| vector.cpp:337:2:337:15 | ... = ... | vector.cpp:337:2:337:2 | call to operator* [post update] | | -| vector.cpp:337:3:337:4 | i1 | vector.cpp:337:2:337:2 | call to operator* | TAINT | -| vector.cpp:337:8:337:13 | call to source | vector.cpp:337:2:337:2 | call to operator* [post update] | TAINT | -| vector.cpp:337:8:337:13 | call to source | vector.cpp:337:2:337:15 | ... = ... | | -| vector.cpp:338:7:338:8 | ref arg v1 | vector.cpp:389:1:389:1 | v1 | | -| vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:340:56:340:57 | v2 | | -| vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:343:7:343:8 | v2 | | -| vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:389:1:389:1 | v2 | | -| vector.cpp:340:38:340:39 | v2 | vector.cpp:340:41:340:45 | call to begin | TAINT | -| vector.cpp:340:41:340:45 | call to begin | vector.cpp:340:50:340:51 | it | | -| vector.cpp:340:41:340:45 | call to begin | vector.cpp:340:68:340:69 | it | | -| vector.cpp:340:41:340:45 | call to begin | vector.cpp:341:4:341:5 | it | | -| vector.cpp:340:56:340:57 | ref arg v2 | vector.cpp:340:56:340:57 | v2 | | -| vector.cpp:340:56:340:57 | ref arg v2 | vector.cpp:343:7:343:8 | v2 | | -| vector.cpp:340:56:340:57 | ref arg v2 | vector.cpp:389:1:389:1 | v2 | | -| vector.cpp:340:56:340:57 | v2 | vector.cpp:340:59:340:61 | call to end | TAINT | -| vector.cpp:340:68:340:69 | it | vector.cpp:340:66:340:66 | call to operator++ | | -| vector.cpp:340:68:340:69 | ref arg it | vector.cpp:340:50:340:51 | it | | -| vector.cpp:340:68:340:69 | ref arg it | vector.cpp:340:68:340:69 | it | | -| vector.cpp:340:68:340:69 | ref arg it | vector.cpp:341:4:341:5 | it | | -| vector.cpp:341:3:341:3 | call to operator* [post update] | vector.cpp:340:56:340:57 | v2 | | -| vector.cpp:341:3:341:3 | call to operator* [post update] | vector.cpp:343:7:343:8 | v2 | | -| vector.cpp:341:3:341:3 | call to operator* [post update] | vector.cpp:389:1:389:1 | v2 | | -| vector.cpp:341:3:341:16 | ... = ... | vector.cpp:341:3:341:3 | call to operator* [post update] | | -| vector.cpp:341:4:341:5 | it | vector.cpp:341:3:341:3 | call to operator* | TAINT | -| vector.cpp:341:9:341:14 | call to source | vector.cpp:341:3:341:3 | call to operator* [post update] | TAINT | -| vector.cpp:341:9:341:14 | call to source | vector.cpp:341:3:341:16 | ... = ... | | -| vector.cpp:343:7:343:8 | ref arg v2 | vector.cpp:389:1:389:1 | v2 | | -| vector.cpp:345:15:345:15 | (__begin) | vector.cpp:345:15:345:15 | call to operator* | TAINT | -| vector.cpp:345:15:345:15 | (__begin) | vector.cpp:345:15:345:15 | call to operator++ | | -| vector.cpp:345:15:345:15 | (__end) | vector.cpp:345:15:345:15 | call to iterator | | -| vector.cpp:345:15:345:15 | (__range) | vector.cpp:345:15:345:15 | call to begin | TAINT | -| vector.cpp:345:15:345:15 | (__range) | vector.cpp:345:15:345:15 | call to end | TAINT | -| vector.cpp:345:15:345:15 | call to begin | vector.cpp:345:15:345:15 | (__begin) | | -| vector.cpp:345:15:345:15 | call to begin | vector.cpp:345:15:345:15 | (__begin) | | -| vector.cpp:345:15:345:15 | call to begin | vector.cpp:345:15:345:15 | (__begin) | | -| vector.cpp:345:15:345:15 | call to end | vector.cpp:345:15:345:15 | (__end) | | -| vector.cpp:345:15:345:15 | ref arg (__begin) | vector.cpp:345:15:345:15 | (__begin) | | -| vector.cpp:345:15:345:15 | ref arg (__begin) | vector.cpp:345:15:345:15 | (__begin) | | -| vector.cpp:345:15:345:15 | ref arg (__begin) | vector.cpp:345:15:345:15 | (__begin) | | -| vector.cpp:345:15:345:15 | ref arg (__range) | vector.cpp:345:15:345:15 | (__range) | | -| vector.cpp:345:15:345:16 | v3 | vector.cpp:345:15:345:15 | (__range) | | -| vector.cpp:345:15:345:16 | v3 | vector.cpp:345:15:345:15 | (__range) | | -| vector.cpp:345:15:345:16 | v3 | vector.cpp:345:15:345:15 | call to operator* | TAINT | -| vector.cpp:346:3:346:14 | ... = ... | vector.cpp:346:3:346:3 | x [post update] | | -| vector.cpp:346:7:346:12 | call to source | vector.cpp:346:3:346:14 | ... = ... | | -| vector.cpp:348:7:348:8 | ref arg v3 | vector.cpp:389:1:389:1 | v3 | | -| vector.cpp:350:38:350:39 | ref arg v4 | vector.cpp:350:56:350:57 | v4 | | -| vector.cpp:350:38:350:39 | ref arg v4 | vector.cpp:353:7:353:8 | v4 | | -| vector.cpp:350:38:350:39 | ref arg v4 | vector.cpp:389:1:389:1 | v4 | | -| vector.cpp:350:38:350:39 | v4 | vector.cpp:350:41:350:45 | call to begin | TAINT | -| vector.cpp:350:41:350:45 | call to begin | vector.cpp:350:50:350:51 | it | | -| vector.cpp:350:41:350:45 | call to begin | vector.cpp:350:68:350:69 | it | | -| vector.cpp:350:41:350:45 | call to begin | vector.cpp:351:32:351:33 | it | | -| vector.cpp:350:56:350:57 | ref arg v4 | vector.cpp:350:56:350:57 | v4 | | -| vector.cpp:350:56:350:57 | ref arg v4 | vector.cpp:353:7:353:8 | v4 | | -| vector.cpp:350:56:350:57 | ref arg v4 | vector.cpp:389:1:389:1 | v4 | | -| vector.cpp:350:56:350:57 | v4 | vector.cpp:350:59:350:61 | call to end | TAINT | -| vector.cpp:350:68:350:69 | it | vector.cpp:350:66:350:66 | call to operator++ | | -| vector.cpp:350:68:350:69 | ref arg it | vector.cpp:350:50:350:51 | it | | -| vector.cpp:350:68:350:69 | ref arg it | vector.cpp:350:68:350:69 | it | | -| vector.cpp:350:68:350:69 | ref arg it | vector.cpp:351:32:351:33 | it | | -| vector.cpp:351:32:351:33 | call to iterator [post update] | vector.cpp:350:56:350:57 | v4 | | -| vector.cpp:351:32:351:33 | call to iterator [post update] | vector.cpp:353:7:353:8 | v4 | | -| vector.cpp:351:32:351:33 | call to iterator [post update] | vector.cpp:389:1:389:1 | v4 | | -| vector.cpp:351:32:351:33 | it | vector.cpp:351:32:351:33 | call to iterator | | -| vector.cpp:351:32:351:33 | it [post update] | vector.cpp:350:56:350:57 | v4 | | -| vector.cpp:351:32:351:33 | it [post update] | vector.cpp:353:7:353:8 | v4 | | -| vector.cpp:351:32:351:33 | it [post update] | vector.cpp:389:1:389:1 | v4 | | -| vector.cpp:353:7:353:8 | ref arg v4 | vector.cpp:389:1:389:1 | v4 | | -| vector.cpp:355:34:355:35 | ref arg v5 | vector.cpp:357:7:357:8 | v5 | | -| vector.cpp:355:34:355:35 | ref arg v5 | vector.cpp:359:7:359:8 | v5 | | -| vector.cpp:355:34:355:35 | ref arg v5 | vector.cpp:389:1:389:1 | v5 | | -| vector.cpp:355:34:355:35 | v5 | vector.cpp:355:37:355:41 | call to begin | TAINT | -| vector.cpp:355:37:355:41 | call to begin | vector.cpp:356:3:356:4 | i5 | | -| vector.cpp:355:37:355:41 | call to begin | vector.cpp:358:3:358:4 | i5 | | -| vector.cpp:356:2:356:2 | call to operator* [post update] | vector.cpp:357:7:357:8 | v5 | | -| vector.cpp:356:2:356:2 | call to operator* [post update] | vector.cpp:359:7:359:8 | v5 | | -| vector.cpp:356:2:356:2 | call to operator* [post update] | vector.cpp:389:1:389:1 | v5 | | -| vector.cpp:356:2:356:15 | ... = ... | vector.cpp:356:2:356:2 | call to operator* [post update] | | -| vector.cpp:356:3:356:4 | i5 | vector.cpp:356:2:356:2 | call to operator* | TAINT | -| vector.cpp:356:8:356:13 | call to source | vector.cpp:356:2:356:2 | call to operator* [post update] | TAINT | -| vector.cpp:356:8:356:13 | call to source | vector.cpp:356:2:356:15 | ... = ... | | -| vector.cpp:357:7:357:8 | ref arg v5 | vector.cpp:359:7:359:8 | v5 | | -| vector.cpp:357:7:357:8 | ref arg v5 | vector.cpp:389:1:389:1 | v5 | | -| vector.cpp:358:2:358:2 | call to operator* [post update] | vector.cpp:359:7:359:8 | v5 | | -| vector.cpp:358:2:358:2 | call to operator* [post update] | vector.cpp:389:1:389:1 | v5 | | -| vector.cpp:358:2:358:8 | ... = ... | vector.cpp:358:2:358:2 | call to operator* [post update] | | -| vector.cpp:358:3:358:4 | i5 | vector.cpp:358:2:358:2 | call to operator* | TAINT | -| vector.cpp:358:8:358:8 | 1 | vector.cpp:358:2:358:2 | call to operator* [post update] | TAINT | -| vector.cpp:358:8:358:8 | 1 | vector.cpp:358:2:358:8 | ... = ... | | -| vector.cpp:359:7:359:8 | ref arg v5 | vector.cpp:389:1:389:1 | v5 | | -| vector.cpp:361:34:361:35 | ref arg v6 | vector.cpp:363:7:363:8 | v6 | | -| vector.cpp:361:34:361:35 | ref arg v6 | vector.cpp:364:2:364:3 | v6 | | -| vector.cpp:361:34:361:35 | ref arg v6 | vector.cpp:365:7:365:8 | v6 | | -| vector.cpp:361:34:361:35 | ref arg v6 | vector.cpp:389:1:389:1 | v6 | | -| vector.cpp:361:34:361:35 | v6 | vector.cpp:361:37:361:41 | call to begin | TAINT | -| vector.cpp:361:37:361:41 | call to begin | vector.cpp:362:3:362:4 | i6 | | -| vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:363:7:363:8 | v6 | | -| vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:364:2:364:3 | v6 | | -| vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:365:7:365:8 | v6 | | -| vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:389:1:389:1 | v6 | | -| vector.cpp:362:2:362:15 | ... = ... | vector.cpp:362:2:362:2 | call to operator* [post update] | | -| vector.cpp:362:3:362:4 | i6 | vector.cpp:362:2:362:2 | call to operator* | TAINT | -| vector.cpp:362:8:362:13 | call to source | vector.cpp:362:2:362:2 | call to operator* [post update] | TAINT | -| vector.cpp:362:8:362:13 | call to source | vector.cpp:362:2:362:15 | ... = ... | | -| vector.cpp:363:7:363:8 | ref arg v6 | vector.cpp:364:2:364:3 | v6 | | -| vector.cpp:363:7:363:8 | ref arg v6 | vector.cpp:365:7:365:8 | v6 | | -| vector.cpp:363:7:363:8 | ref arg v6 | vector.cpp:389:1:389:1 | v6 | | -| vector.cpp:364:2:364:3 | ref arg v6 | vector.cpp:365:7:365:8 | v6 | | -| vector.cpp:364:2:364:3 | ref arg v6 | vector.cpp:389:1:389:1 | v6 | | -| vector.cpp:364:7:364:26 | call to vector | vector.cpp:364:2:364:3 | ref arg v6 | TAINT | -| vector.cpp:364:7:364:26 | call to vector | vector.cpp:364:5:364:5 | call to operator= | TAINT | -| vector.cpp:365:7:365:8 | ref arg v6 | vector.cpp:389:1:389:1 | v6 | | -| vector.cpp:367:34:367:35 | ref arg v7 | vector.cpp:370:8:370:9 | v7 | | -| vector.cpp:367:34:367:35 | ref arg v7 | vector.cpp:373:8:373:9 | v7 | | -| vector.cpp:367:34:367:35 | ref arg v7 | vector.cpp:375:7:375:8 | v7 | | -| vector.cpp:367:34:367:35 | ref arg v7 | vector.cpp:389:1:389:1 | v7 | | -| vector.cpp:367:34:367:35 | v7 | vector.cpp:367:37:367:41 | call to begin | TAINT | -| vector.cpp:367:37:367:41 | call to begin | vector.cpp:369:4:369:5 | i7 | | -| vector.cpp:367:37:367:41 | call to begin | vector.cpp:372:4:372:5 | i7 | | -| vector.cpp:369:3:369:3 | call to operator* [post update] | vector.cpp:370:8:370:9 | v7 | | -| vector.cpp:369:3:369:3 | call to operator* [post update] | vector.cpp:375:7:375:8 | v7 | | -| vector.cpp:369:3:369:3 | call to operator* [post update] | vector.cpp:389:1:389:1 | v7 | | -| vector.cpp:369:3:369:16 | ... = ... | vector.cpp:369:3:369:3 | call to operator* [post update] | | -| vector.cpp:369:4:369:5 | i7 | vector.cpp:369:3:369:3 | call to operator* | TAINT | -| vector.cpp:369:9:369:14 | call to source | vector.cpp:369:3:369:3 | call to operator* [post update] | TAINT | -| vector.cpp:369:9:369:14 | call to source | vector.cpp:369:3:369:16 | ... = ... | | -| vector.cpp:370:8:370:9 | ref arg v7 | vector.cpp:375:7:375:8 | v7 | | -| vector.cpp:370:8:370:9 | ref arg v7 | vector.cpp:389:1:389:1 | v7 | | -| vector.cpp:372:3:372:3 | call to operator* [post update] | vector.cpp:373:8:373:9 | v7 | | -| vector.cpp:372:3:372:3 | call to operator* [post update] | vector.cpp:375:7:375:8 | v7 | | -| vector.cpp:372:3:372:3 | call to operator* [post update] | vector.cpp:389:1:389:1 | v7 | | -| vector.cpp:372:3:372:9 | ... = ... | vector.cpp:372:3:372:3 | call to operator* [post update] | | -| vector.cpp:372:4:372:5 | i7 | vector.cpp:372:3:372:3 | call to operator* | TAINT | -| vector.cpp:372:9:372:9 | 1 | vector.cpp:372:3:372:3 | call to operator* [post update] | TAINT | -| vector.cpp:372:9:372:9 | 1 | vector.cpp:372:3:372:9 | ... = ... | | -| vector.cpp:373:8:373:9 | ref arg v7 | vector.cpp:375:7:375:8 | v7 | | -| vector.cpp:373:8:373:9 | ref arg v7 | vector.cpp:389:1:389:1 | v7 | | -| vector.cpp:375:7:375:8 | ref arg v7 | vector.cpp:389:1:389:1 | v7 | | -| vector.cpp:377:34:377:35 | ref arg v8 | vector.cpp:379:7:379:8 | v8 | | -| vector.cpp:377:34:377:35 | ref arg v8 | vector.cpp:381:7:381:8 | v8 | | -| vector.cpp:377:34:377:35 | ref arg v8 | vector.cpp:389:1:389:1 | v8 | | -| vector.cpp:377:34:377:35 | v8 | vector.cpp:377:37:377:41 | call to begin | TAINT | -| vector.cpp:377:37:377:41 | call to begin | vector.cpp:378:3:378:4 | i8 | | -| vector.cpp:377:37:377:41 | call to begin | vector.cpp:380:3:380:4 | i8 | | -| vector.cpp:378:2:378:2 | call to operator* [post update] | vector.cpp:379:7:379:8 | v8 | | -| vector.cpp:378:2:378:2 | call to operator* [post update] | vector.cpp:381:7:381:8 | v8 | | -| vector.cpp:378:2:378:2 | call to operator* [post update] | vector.cpp:389:1:389:1 | v8 | | -| vector.cpp:378:2:378:15 | ... = ... | vector.cpp:378:2:378:2 | call to operator* [post update] | | -| vector.cpp:378:3:378:4 | i8 | vector.cpp:378:2:378:2 | call to operator* | TAINT | -| vector.cpp:378:8:378:13 | call to source | vector.cpp:378:2:378:2 | call to operator* [post update] | TAINT | -| vector.cpp:378:8:378:13 | call to source | vector.cpp:378:2:378:15 | ... = ... | | -| vector.cpp:379:7:379:8 | ref arg v8 | vector.cpp:381:7:381:8 | v8 | | -| vector.cpp:379:7:379:8 | ref arg v8 | vector.cpp:389:1:389:1 | v8 | | -| vector.cpp:380:2:380:2 | call to operator* [post update] | vector.cpp:381:7:381:8 | v8 | | -| vector.cpp:380:2:380:2 | call to operator* [post update] | vector.cpp:389:1:389:1 | v8 | | -| vector.cpp:380:2:380:8 | ... = ... | vector.cpp:380:2:380:2 | call to operator* [post update] | | -| vector.cpp:380:3:380:4 | i8 | vector.cpp:380:2:380:2 | call to operator* | TAINT | -| vector.cpp:380:8:380:8 | 1 | vector.cpp:380:2:380:2 | call to operator* [post update] | TAINT | -| vector.cpp:380:8:380:8 | 1 | vector.cpp:380:2:380:8 | ... = ... | | -| vector.cpp:381:7:381:8 | ref arg v8 | vector.cpp:389:1:389:1 | v8 | | -| vector.cpp:383:34:383:35 | ref arg v9 | vector.cpp:388:7:388:8 | v9 | | -| vector.cpp:383:34:383:35 | ref arg v9 | vector.cpp:389:1:389:1 | v9 | | -| vector.cpp:383:34:383:35 | v9 | vector.cpp:383:37:383:41 | call to begin | TAINT | -| vector.cpp:383:37:383:41 | call to begin | vector.cpp:385:3:385:4 | i9 | | -| vector.cpp:383:37:383:41 | call to begin | vector.cpp:386:31:386:32 | i9 | | -| vector.cpp:385:2:385:2 | call to operator* [post update] | vector.cpp:388:7:388:8 | v9 | | -| vector.cpp:385:2:385:2 | call to operator* [post update] | vector.cpp:389:1:389:1 | v9 | | -| vector.cpp:385:2:385:15 | ... = ... | vector.cpp:385:2:385:2 | call to operator* [post update] | | -| vector.cpp:385:3:385:4 | i9 | vector.cpp:385:2:385:2 | call to operator* | TAINT | -| vector.cpp:385:8:385:13 | call to source | vector.cpp:385:2:385:2 | call to operator* [post update] | TAINT | -| vector.cpp:385:8:385:13 | call to source | vector.cpp:385:2:385:15 | ... = ... | | -| vector.cpp:386:31:386:32 | call to iterator [post update] | vector.cpp:388:7:388:8 | v9 | | -| vector.cpp:386:31:386:32 | call to iterator [post update] | vector.cpp:389:1:389:1 | v9 | | -| vector.cpp:386:31:386:32 | i9 | vector.cpp:386:31:386:32 | call to iterator | | -| vector.cpp:386:31:386:32 | i9 [post update] | vector.cpp:388:7:388:8 | v9 | | -| vector.cpp:386:31:386:32 | i9 [post update] | vector.cpp:389:1:389:1 | v9 | | -| vector.cpp:388:7:388:8 | ref arg v9 | vector.cpp:389:1:389:1 | v9 | | +| vector.cpp:333:64:333:67 | iter | vector.cpp:333:64:333:67 | iter | | +| vector.cpp:333:64:333:67 | iter | vector.cpp:334:3:334:6 | iter | | +| vector.cpp:333:74:333:74 | i | vector.cpp:334:10:334:10 | i | | +| vector.cpp:334:2:334:2 | call to operator* [post update] | vector.cpp:333:64:333:67 | iter | | +| vector.cpp:334:2:334:10 | ... = ... | vector.cpp:334:2:334:2 | call to operator* [post update] | | +| vector.cpp:334:3:334:6 | iter | vector.cpp:334:2:334:2 | call to operator* | TAINT | +| vector.cpp:334:10:334:10 | i | vector.cpp:334:2:334:2 | call to operator* [post update] | TAINT | +| vector.cpp:334:10:334:10 | i | vector.cpp:334:2:334:10 | ... = ... | | +| vector.cpp:337:38:337:38 | b | vector.cpp:372:5:372:5 | b | | +| vector.cpp:338:22:338:24 | call to vector | vector.cpp:340:34:340:35 | v1 | | +| vector.cpp:338:22:338:24 | call to vector | vector.cpp:342:7:342:8 | v1 | | +| vector.cpp:338:22:338:24 | call to vector | vector.cpp:401:1:401:1 | v1 | | +| vector.cpp:338:30:338:32 | call to vector | vector.cpp:344:38:344:39 | v2 | | +| vector.cpp:338:30:338:32 | call to vector | vector.cpp:344:56:344:57 | v2 | | +| vector.cpp:338:30:338:32 | call to vector | vector.cpp:347:7:347:8 | v2 | | +| vector.cpp:338:30:338:32 | call to vector | vector.cpp:401:1:401:1 | v2 | | +| vector.cpp:338:38:338:40 | call to vector | vector.cpp:349:15:349:16 | v3 | | +| vector.cpp:338:38:338:40 | call to vector | vector.cpp:352:7:352:8 | v3 | | +| vector.cpp:338:38:338:40 | call to vector | vector.cpp:401:1:401:1 | v3 | | +| vector.cpp:338:46:338:48 | call to vector | vector.cpp:354:38:354:39 | v4 | | +| vector.cpp:338:46:338:48 | call to vector | vector.cpp:354:56:354:57 | v4 | | +| vector.cpp:338:46:338:48 | call to vector | vector.cpp:357:7:357:8 | v4 | | +| vector.cpp:338:46:338:48 | call to vector | vector.cpp:401:1:401:1 | v4 | | +| vector.cpp:338:54:338:56 | call to vector | vector.cpp:359:34:359:35 | v5 | | +| vector.cpp:338:54:338:56 | call to vector | vector.cpp:361:7:361:8 | v5 | | +| vector.cpp:338:54:338:56 | call to vector | vector.cpp:363:7:363:8 | v5 | | +| vector.cpp:338:54:338:56 | call to vector | vector.cpp:401:1:401:1 | v5 | | +| vector.cpp:338:62:338:64 | call to vector | vector.cpp:365:34:365:35 | v6 | | +| vector.cpp:338:62:338:64 | call to vector | vector.cpp:367:7:367:8 | v6 | | +| vector.cpp:338:62:338:64 | call to vector | vector.cpp:368:2:368:3 | v6 | | +| vector.cpp:338:62:338:64 | call to vector | vector.cpp:369:7:369:8 | v6 | | +| vector.cpp:338:62:338:64 | call to vector | vector.cpp:401:1:401:1 | v6 | | +| vector.cpp:338:70:338:72 | call to vector | vector.cpp:371:34:371:35 | v7 | | +| vector.cpp:338:70:338:72 | call to vector | vector.cpp:374:8:374:9 | v7 | | +| vector.cpp:338:70:338:72 | call to vector | vector.cpp:377:8:377:9 | v7 | | +| vector.cpp:338:70:338:72 | call to vector | vector.cpp:379:7:379:8 | v7 | | +| vector.cpp:338:70:338:72 | call to vector | vector.cpp:401:1:401:1 | v7 | | +| vector.cpp:338:78:338:80 | call to vector | vector.cpp:381:34:381:35 | v8 | | +| vector.cpp:338:78:338:80 | call to vector | vector.cpp:383:7:383:8 | v8 | | +| vector.cpp:338:78:338:80 | call to vector | vector.cpp:385:7:385:8 | v8 | | +| vector.cpp:338:78:338:80 | call to vector | vector.cpp:401:1:401:1 | v8 | | +| vector.cpp:338:86:338:88 | call to vector | vector.cpp:387:34:387:35 | v9 | | +| vector.cpp:338:86:338:88 | call to vector | vector.cpp:392:7:392:8 | v9 | | +| vector.cpp:338:86:338:88 | call to vector | vector.cpp:401:1:401:1 | v9 | | +| vector.cpp:338:95:338:97 | call to vector | vector.cpp:394:35:394:37 | v10 | | +| vector.cpp:338:95:338:97 | call to vector | vector.cpp:396:7:396:9 | v10 | | +| vector.cpp:338:95:338:97 | call to vector | vector.cpp:401:1:401:1 | v10 | | +| vector.cpp:338:104:338:106 | call to vector | vector.cpp:398:35:398:37 | v11 | | +| vector.cpp:338:104:338:106 | call to vector | vector.cpp:400:7:400:9 | v11 | | +| vector.cpp:338:104:338:106 | call to vector | vector.cpp:401:1:401:1 | v11 | | +| vector.cpp:340:34:340:35 | ref arg v1 | vector.cpp:342:7:342:8 | v1 | | +| vector.cpp:340:34:340:35 | ref arg v1 | vector.cpp:401:1:401:1 | v1 | | +| vector.cpp:340:34:340:35 | v1 | vector.cpp:340:37:340:41 | call to begin | TAINT | +| vector.cpp:340:37:340:41 | call to begin | vector.cpp:341:3:341:4 | i1 | | +| vector.cpp:341:2:341:2 | call to operator* [post update] | vector.cpp:342:7:342:8 | v1 | | +| vector.cpp:341:2:341:2 | call to operator* [post update] | vector.cpp:401:1:401:1 | v1 | | +| vector.cpp:341:2:341:15 | ... = ... | vector.cpp:341:2:341:2 | call to operator* [post update] | | +| vector.cpp:341:3:341:4 | i1 | vector.cpp:341:2:341:2 | call to operator* | TAINT | +| vector.cpp:341:8:341:13 | call to source | vector.cpp:341:2:341:2 | call to operator* [post update] | TAINT | +| vector.cpp:341:8:341:13 | call to source | vector.cpp:341:2:341:15 | ... = ... | | +| vector.cpp:342:7:342:8 | ref arg v1 | vector.cpp:401:1:401:1 | v1 | | +| vector.cpp:344:38:344:39 | ref arg v2 | vector.cpp:344:56:344:57 | v2 | | +| vector.cpp:344:38:344:39 | ref arg v2 | vector.cpp:347:7:347:8 | v2 | | +| vector.cpp:344:38:344:39 | ref arg v2 | vector.cpp:401:1:401:1 | v2 | | +| vector.cpp:344:38:344:39 | v2 | vector.cpp:344:41:344:45 | call to begin | TAINT | +| vector.cpp:344:41:344:45 | call to begin | vector.cpp:344:50:344:51 | it | | +| vector.cpp:344:41:344:45 | call to begin | vector.cpp:344:68:344:69 | it | | +| vector.cpp:344:41:344:45 | call to begin | vector.cpp:345:4:345:5 | it | | +| vector.cpp:344:56:344:57 | ref arg v2 | vector.cpp:344:56:344:57 | v2 | | +| vector.cpp:344:56:344:57 | ref arg v2 | vector.cpp:347:7:347:8 | v2 | | +| vector.cpp:344:56:344:57 | ref arg v2 | vector.cpp:401:1:401:1 | v2 | | +| vector.cpp:344:56:344:57 | v2 | vector.cpp:344:59:344:61 | call to end | TAINT | +| vector.cpp:344:68:344:69 | it | vector.cpp:344:66:344:66 | call to operator++ | | +| vector.cpp:344:68:344:69 | ref arg it | vector.cpp:344:50:344:51 | it | | +| vector.cpp:344:68:344:69 | ref arg it | vector.cpp:344:68:344:69 | it | | +| vector.cpp:344:68:344:69 | ref arg it | vector.cpp:345:4:345:5 | it | | +| vector.cpp:345:3:345:3 | call to operator* [post update] | vector.cpp:344:56:344:57 | v2 | | +| vector.cpp:345:3:345:3 | call to operator* [post update] | vector.cpp:347:7:347:8 | v2 | | +| vector.cpp:345:3:345:3 | call to operator* [post update] | vector.cpp:401:1:401:1 | v2 | | +| vector.cpp:345:3:345:16 | ... = ... | vector.cpp:345:3:345:3 | call to operator* [post update] | | +| vector.cpp:345:4:345:5 | it | vector.cpp:345:3:345:3 | call to operator* | TAINT | +| vector.cpp:345:9:345:14 | call to source | vector.cpp:345:3:345:3 | call to operator* [post update] | TAINT | +| vector.cpp:345:9:345:14 | call to source | vector.cpp:345:3:345:16 | ... = ... | | +| vector.cpp:347:7:347:8 | ref arg v2 | vector.cpp:401:1:401:1 | v2 | | +| vector.cpp:349:15:349:15 | (__begin) | vector.cpp:349:15:349:15 | call to operator* | TAINT | +| vector.cpp:349:15:349:15 | (__begin) | vector.cpp:349:15:349:15 | call to operator++ | | +| vector.cpp:349:15:349:15 | (__end) | vector.cpp:349:15:349:15 | call to iterator | | +| vector.cpp:349:15:349:15 | (__range) | vector.cpp:349:15:349:15 | call to begin | TAINT | +| vector.cpp:349:15:349:15 | (__range) | vector.cpp:349:15:349:15 | call to end | TAINT | +| vector.cpp:349:15:349:15 | call to begin | vector.cpp:349:15:349:15 | (__begin) | | +| vector.cpp:349:15:349:15 | call to begin | vector.cpp:349:15:349:15 | (__begin) | | +| vector.cpp:349:15:349:15 | call to begin | vector.cpp:349:15:349:15 | (__begin) | | +| vector.cpp:349:15:349:15 | call to end | vector.cpp:349:15:349:15 | (__end) | | +| vector.cpp:349:15:349:15 | ref arg (__begin) | vector.cpp:349:15:349:15 | (__begin) | | +| vector.cpp:349:15:349:15 | ref arg (__begin) | vector.cpp:349:15:349:15 | (__begin) | | +| vector.cpp:349:15:349:15 | ref arg (__begin) | vector.cpp:349:15:349:15 | (__begin) | | +| vector.cpp:349:15:349:15 | ref arg (__range) | vector.cpp:349:15:349:15 | (__range) | | +| vector.cpp:349:15:349:16 | v3 | vector.cpp:349:15:349:15 | (__range) | | +| vector.cpp:349:15:349:16 | v3 | vector.cpp:349:15:349:15 | (__range) | | +| vector.cpp:349:15:349:16 | v3 | vector.cpp:349:15:349:15 | call to operator* | TAINT | +| vector.cpp:350:3:350:14 | ... = ... | vector.cpp:350:3:350:3 | x [post update] | | +| vector.cpp:350:7:350:12 | call to source | vector.cpp:350:3:350:14 | ... = ... | | +| vector.cpp:352:7:352:8 | ref arg v3 | vector.cpp:401:1:401:1 | v3 | | +| vector.cpp:354:38:354:39 | ref arg v4 | vector.cpp:354:56:354:57 | v4 | | +| vector.cpp:354:38:354:39 | ref arg v4 | vector.cpp:357:7:357:8 | v4 | | +| vector.cpp:354:38:354:39 | ref arg v4 | vector.cpp:401:1:401:1 | v4 | | +| vector.cpp:354:38:354:39 | v4 | vector.cpp:354:41:354:45 | call to begin | TAINT | +| vector.cpp:354:41:354:45 | call to begin | vector.cpp:354:50:354:51 | it | | +| vector.cpp:354:41:354:45 | call to begin | vector.cpp:354:68:354:69 | it | | +| vector.cpp:354:41:354:45 | call to begin | vector.cpp:355:32:355:33 | it | | +| vector.cpp:354:56:354:57 | ref arg v4 | vector.cpp:354:56:354:57 | v4 | | +| vector.cpp:354:56:354:57 | ref arg v4 | vector.cpp:357:7:357:8 | v4 | | +| vector.cpp:354:56:354:57 | ref arg v4 | vector.cpp:401:1:401:1 | v4 | | +| vector.cpp:354:56:354:57 | v4 | vector.cpp:354:59:354:61 | call to end | TAINT | +| vector.cpp:354:68:354:69 | it | vector.cpp:354:66:354:66 | call to operator++ | | +| vector.cpp:354:68:354:69 | ref arg it | vector.cpp:354:50:354:51 | it | | +| vector.cpp:354:68:354:69 | ref arg it | vector.cpp:354:68:354:69 | it | | +| vector.cpp:354:68:354:69 | ref arg it | vector.cpp:355:32:355:33 | it | | +| vector.cpp:355:32:355:33 | call to iterator [post update] | vector.cpp:354:56:354:57 | v4 | | +| vector.cpp:355:32:355:33 | call to iterator [post update] | vector.cpp:357:7:357:8 | v4 | | +| vector.cpp:355:32:355:33 | call to iterator [post update] | vector.cpp:401:1:401:1 | v4 | | +| vector.cpp:355:32:355:33 | it | vector.cpp:355:32:355:33 | call to iterator | | +| vector.cpp:355:32:355:33 | it [post update] | vector.cpp:354:56:354:57 | v4 | | +| vector.cpp:355:32:355:33 | it [post update] | vector.cpp:357:7:357:8 | v4 | | +| vector.cpp:355:32:355:33 | it [post update] | vector.cpp:401:1:401:1 | v4 | | +| vector.cpp:357:7:357:8 | ref arg v4 | vector.cpp:401:1:401:1 | v4 | | +| vector.cpp:359:34:359:35 | ref arg v5 | vector.cpp:361:7:361:8 | v5 | | +| vector.cpp:359:34:359:35 | ref arg v5 | vector.cpp:363:7:363:8 | v5 | | +| vector.cpp:359:34:359:35 | ref arg v5 | vector.cpp:401:1:401:1 | v5 | | +| vector.cpp:359:34:359:35 | v5 | vector.cpp:359:37:359:41 | call to begin | TAINT | +| vector.cpp:359:37:359:41 | call to begin | vector.cpp:360:3:360:4 | i5 | | +| vector.cpp:359:37:359:41 | call to begin | vector.cpp:362:3:362:4 | i5 | | +| vector.cpp:360:2:360:2 | call to operator* [post update] | vector.cpp:361:7:361:8 | v5 | | +| vector.cpp:360:2:360:2 | call to operator* [post update] | vector.cpp:363:7:363:8 | v5 | | +| vector.cpp:360:2:360:2 | call to operator* [post update] | vector.cpp:401:1:401:1 | v5 | | +| vector.cpp:360:2:360:15 | ... = ... | vector.cpp:360:2:360:2 | call to operator* [post update] | | +| vector.cpp:360:3:360:4 | i5 | vector.cpp:360:2:360:2 | call to operator* | TAINT | +| vector.cpp:360:8:360:13 | call to source | vector.cpp:360:2:360:2 | call to operator* [post update] | TAINT | +| vector.cpp:360:8:360:13 | call to source | vector.cpp:360:2:360:15 | ... = ... | | +| vector.cpp:361:7:361:8 | ref arg v5 | vector.cpp:363:7:363:8 | v5 | | +| vector.cpp:361:7:361:8 | ref arg v5 | vector.cpp:401:1:401:1 | v5 | | +| vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:363:7:363:8 | v5 | | +| vector.cpp:362:2:362:2 | call to operator* [post update] | vector.cpp:401:1:401:1 | v5 | | +| vector.cpp:362:2:362:8 | ... = ... | vector.cpp:362:2:362:2 | call to operator* [post update] | | +| vector.cpp:362:3:362:4 | i5 | vector.cpp:362:2:362:2 | call to operator* | TAINT | +| vector.cpp:362:8:362:8 | 1 | vector.cpp:362:2:362:2 | call to operator* [post update] | TAINT | +| vector.cpp:362:8:362:8 | 1 | vector.cpp:362:2:362:8 | ... = ... | | +| vector.cpp:363:7:363:8 | ref arg v5 | vector.cpp:401:1:401:1 | v5 | | +| vector.cpp:365:34:365:35 | ref arg v6 | vector.cpp:367:7:367:8 | v6 | | +| vector.cpp:365:34:365:35 | ref arg v6 | vector.cpp:368:2:368:3 | v6 | | +| vector.cpp:365:34:365:35 | ref arg v6 | vector.cpp:369:7:369:8 | v6 | | +| vector.cpp:365:34:365:35 | ref arg v6 | vector.cpp:401:1:401:1 | v6 | | +| vector.cpp:365:34:365:35 | v6 | vector.cpp:365:37:365:41 | call to begin | TAINT | +| vector.cpp:365:37:365:41 | call to begin | vector.cpp:366:3:366:4 | i6 | | +| vector.cpp:366:2:366:2 | call to operator* [post update] | vector.cpp:367:7:367:8 | v6 | | +| vector.cpp:366:2:366:2 | call to operator* [post update] | vector.cpp:368:2:368:3 | v6 | | +| vector.cpp:366:2:366:2 | call to operator* [post update] | vector.cpp:369:7:369:8 | v6 | | +| vector.cpp:366:2:366:2 | call to operator* [post update] | vector.cpp:401:1:401:1 | v6 | | +| vector.cpp:366:2:366:15 | ... = ... | vector.cpp:366:2:366:2 | call to operator* [post update] | | +| vector.cpp:366:3:366:4 | i6 | vector.cpp:366:2:366:2 | call to operator* | TAINT | +| vector.cpp:366:8:366:13 | call to source | vector.cpp:366:2:366:2 | call to operator* [post update] | TAINT | +| vector.cpp:366:8:366:13 | call to source | vector.cpp:366:2:366:15 | ... = ... | | +| vector.cpp:367:7:367:8 | ref arg v6 | vector.cpp:368:2:368:3 | v6 | | +| vector.cpp:367:7:367:8 | ref arg v6 | vector.cpp:369:7:369:8 | v6 | | +| vector.cpp:367:7:367:8 | ref arg v6 | vector.cpp:401:1:401:1 | v6 | | +| vector.cpp:368:2:368:3 | ref arg v6 | vector.cpp:369:7:369:8 | v6 | | +| vector.cpp:368:2:368:3 | ref arg v6 | vector.cpp:401:1:401:1 | v6 | | +| vector.cpp:368:7:368:26 | call to vector | vector.cpp:368:2:368:3 | ref arg v6 | TAINT | +| vector.cpp:368:7:368:26 | call to vector | vector.cpp:368:5:368:5 | call to operator= | TAINT | +| vector.cpp:369:7:369:8 | ref arg v6 | vector.cpp:401:1:401:1 | v6 | | +| vector.cpp:371:34:371:35 | ref arg v7 | vector.cpp:374:8:374:9 | v7 | | +| vector.cpp:371:34:371:35 | ref arg v7 | vector.cpp:377:8:377:9 | v7 | | +| vector.cpp:371:34:371:35 | ref arg v7 | vector.cpp:379:7:379:8 | v7 | | +| vector.cpp:371:34:371:35 | ref arg v7 | vector.cpp:401:1:401:1 | v7 | | +| vector.cpp:371:34:371:35 | v7 | vector.cpp:371:37:371:41 | call to begin | TAINT | +| vector.cpp:371:37:371:41 | call to begin | vector.cpp:373:4:373:5 | i7 | | +| vector.cpp:371:37:371:41 | call to begin | vector.cpp:376:4:376:5 | i7 | | +| vector.cpp:373:3:373:3 | call to operator* [post update] | vector.cpp:374:8:374:9 | v7 | | +| vector.cpp:373:3:373:3 | call to operator* [post update] | vector.cpp:379:7:379:8 | v7 | | +| vector.cpp:373:3:373:3 | call to operator* [post update] | vector.cpp:401:1:401:1 | v7 | | +| vector.cpp:373:3:373:16 | ... = ... | vector.cpp:373:3:373:3 | call to operator* [post update] | | +| vector.cpp:373:4:373:5 | i7 | vector.cpp:373:3:373:3 | call to operator* | TAINT | +| vector.cpp:373:9:373:14 | call to source | vector.cpp:373:3:373:3 | call to operator* [post update] | TAINT | +| vector.cpp:373:9:373:14 | call to source | vector.cpp:373:3:373:16 | ... = ... | | +| vector.cpp:374:8:374:9 | ref arg v7 | vector.cpp:379:7:379:8 | v7 | | +| vector.cpp:374:8:374:9 | ref arg v7 | vector.cpp:401:1:401:1 | v7 | | +| vector.cpp:376:3:376:3 | call to operator* [post update] | vector.cpp:377:8:377:9 | v7 | | +| vector.cpp:376:3:376:3 | call to operator* [post update] | vector.cpp:379:7:379:8 | v7 | | +| vector.cpp:376:3:376:3 | call to operator* [post update] | vector.cpp:401:1:401:1 | v7 | | +| vector.cpp:376:3:376:9 | ... = ... | vector.cpp:376:3:376:3 | call to operator* [post update] | | +| vector.cpp:376:4:376:5 | i7 | vector.cpp:376:3:376:3 | call to operator* | TAINT | +| vector.cpp:376:9:376:9 | 1 | vector.cpp:376:3:376:3 | call to operator* [post update] | TAINT | +| vector.cpp:376:9:376:9 | 1 | vector.cpp:376:3:376:9 | ... = ... | | +| vector.cpp:377:8:377:9 | ref arg v7 | vector.cpp:379:7:379:8 | v7 | | +| vector.cpp:377:8:377:9 | ref arg v7 | vector.cpp:401:1:401:1 | v7 | | +| vector.cpp:379:7:379:8 | ref arg v7 | vector.cpp:401:1:401:1 | v7 | | +| vector.cpp:381:34:381:35 | ref arg v8 | vector.cpp:383:7:383:8 | v8 | | +| vector.cpp:381:34:381:35 | ref arg v8 | vector.cpp:385:7:385:8 | v8 | | +| vector.cpp:381:34:381:35 | ref arg v8 | vector.cpp:401:1:401:1 | v8 | | +| vector.cpp:381:34:381:35 | v8 | vector.cpp:381:37:381:41 | call to begin | TAINT | +| vector.cpp:381:37:381:41 | call to begin | vector.cpp:382:3:382:4 | i8 | | +| vector.cpp:381:37:381:41 | call to begin | vector.cpp:384:3:384:4 | i8 | | +| vector.cpp:382:2:382:2 | call to operator* [post update] | vector.cpp:383:7:383:8 | v8 | | +| vector.cpp:382:2:382:2 | call to operator* [post update] | vector.cpp:385:7:385:8 | v8 | | +| vector.cpp:382:2:382:2 | call to operator* [post update] | vector.cpp:401:1:401:1 | v8 | | +| vector.cpp:382:2:382:15 | ... = ... | vector.cpp:382:2:382:2 | call to operator* [post update] | | +| vector.cpp:382:3:382:4 | i8 | vector.cpp:382:2:382:2 | call to operator* | TAINT | +| vector.cpp:382:8:382:13 | call to source | vector.cpp:382:2:382:2 | call to operator* [post update] | TAINT | +| vector.cpp:382:8:382:13 | call to source | vector.cpp:382:2:382:15 | ... = ... | | +| vector.cpp:383:7:383:8 | ref arg v8 | vector.cpp:385:7:385:8 | v8 | | +| vector.cpp:383:7:383:8 | ref arg v8 | vector.cpp:401:1:401:1 | v8 | | +| vector.cpp:384:2:384:2 | call to operator* [post update] | vector.cpp:385:7:385:8 | v8 | | +| vector.cpp:384:2:384:2 | call to operator* [post update] | vector.cpp:401:1:401:1 | v8 | | +| vector.cpp:384:2:384:8 | ... = ... | vector.cpp:384:2:384:2 | call to operator* [post update] | | +| vector.cpp:384:3:384:4 | i8 | vector.cpp:384:2:384:2 | call to operator* | TAINT | +| vector.cpp:384:8:384:8 | 1 | vector.cpp:384:2:384:2 | call to operator* [post update] | TAINT | +| vector.cpp:384:8:384:8 | 1 | vector.cpp:384:2:384:8 | ... = ... | | +| vector.cpp:385:7:385:8 | ref arg v8 | vector.cpp:401:1:401:1 | v8 | | +| vector.cpp:387:34:387:35 | ref arg v9 | vector.cpp:392:7:392:8 | v9 | | +| vector.cpp:387:34:387:35 | ref arg v9 | vector.cpp:401:1:401:1 | v9 | | +| vector.cpp:387:34:387:35 | v9 | vector.cpp:387:37:387:41 | call to begin | TAINT | +| vector.cpp:387:37:387:41 | call to begin | vector.cpp:389:3:389:4 | i9 | | +| vector.cpp:387:37:387:41 | call to begin | vector.cpp:390:31:390:32 | i9 | | +| vector.cpp:389:2:389:2 | call to operator* [post update] | vector.cpp:392:7:392:8 | v9 | | +| vector.cpp:389:2:389:2 | call to operator* [post update] | vector.cpp:401:1:401:1 | v9 | | +| vector.cpp:389:2:389:15 | ... = ... | vector.cpp:389:2:389:2 | call to operator* [post update] | | +| vector.cpp:389:3:389:4 | i9 | vector.cpp:389:2:389:2 | call to operator* | TAINT | +| vector.cpp:389:8:389:13 | call to source | vector.cpp:389:2:389:2 | call to operator* [post update] | TAINT | +| vector.cpp:389:8:389:13 | call to source | vector.cpp:389:2:389:15 | ... = ... | | +| vector.cpp:390:31:390:32 | call to iterator [post update] | vector.cpp:392:7:392:8 | v9 | | +| vector.cpp:390:31:390:32 | call to iterator [post update] | vector.cpp:401:1:401:1 | v9 | | +| vector.cpp:390:31:390:32 | i9 | vector.cpp:390:31:390:32 | call to iterator | | +| vector.cpp:390:31:390:32 | i9 [post update] | vector.cpp:392:7:392:8 | v9 | | +| vector.cpp:390:31:390:32 | i9 [post update] | vector.cpp:401:1:401:1 | v9 | | +| vector.cpp:392:7:392:8 | ref arg v9 | vector.cpp:401:1:401:1 | v9 | | +| vector.cpp:394:35:394:37 | ref arg v10 | vector.cpp:396:7:396:9 | v10 | | +| vector.cpp:394:35:394:37 | ref arg v10 | vector.cpp:401:1:401:1 | v10 | | +| vector.cpp:394:35:394:37 | v10 | vector.cpp:394:39:394:43 | call to begin | TAINT | +| vector.cpp:394:39:394:43 | call to begin | vector.cpp:395:33:395:35 | i10 | | +| vector.cpp:395:33:395:35 | call to iterator [post update] | vector.cpp:396:7:396:9 | v10 | | +| vector.cpp:395:33:395:35 | call to iterator [post update] | vector.cpp:401:1:401:1 | v10 | | +| vector.cpp:395:33:395:35 | i10 | vector.cpp:395:33:395:35 | call to iterator | | +| vector.cpp:395:33:395:35 | i10 [post update] | vector.cpp:396:7:396:9 | v10 | | +| vector.cpp:395:33:395:35 | i10 [post update] | vector.cpp:401:1:401:1 | v10 | | +| vector.cpp:396:7:396:9 | ref arg v10 | vector.cpp:401:1:401:1 | v10 | | +| vector.cpp:398:35:398:37 | ref arg v11 | vector.cpp:400:7:400:9 | v11 | | +| vector.cpp:398:35:398:37 | ref arg v11 | vector.cpp:401:1:401:1 | v11 | | +| vector.cpp:398:35:398:37 | v11 | vector.cpp:398:39:398:43 | call to begin | TAINT | +| vector.cpp:398:39:398:43 | call to begin | vector.cpp:399:33:399:35 | i11 | | +| vector.cpp:399:33:399:35 | call to iterator [post update] | vector.cpp:400:7:400:9 | v11 | | +| vector.cpp:399:33:399:35 | call to iterator [post update] | vector.cpp:401:1:401:1 | v11 | | +| vector.cpp:399:33:399:35 | i11 | vector.cpp:399:33:399:35 | call to iterator | | +| vector.cpp:399:33:399:35 | i11 [post update] | vector.cpp:400:7:400:9 | v11 | | +| vector.cpp:399:33:399:35 | i11 [post update] | vector.cpp:401:1:401:1 | v11 | | +| vector.cpp:400:7:400:9 | ref arg v11 | vector.cpp:401:1:401:1 | v11 | | 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 2eca13801c6..f91b718bdda 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -375,16 +375,18 @@ | vector.cpp:312:7:312:7 | d | vector.cpp:303:14:303:19 | call to source | | vector.cpp:324:7:324:8 | v2 | vector.cpp:318:15:318:20 | call to source | | vector.cpp:326:7:326:8 | v4 | vector.cpp:318:15:318:20 | call to source | -| vector.cpp:338:7:338:8 | v1 | vector.cpp:337:8:337:13 | call to source | -| vector.cpp:343:7:343:8 | v2 | vector.cpp:341:9:341:14 | call to source | -| vector.cpp:353:7:353:8 | v4 | vector.cpp:330:10:330:15 | call to source | -| vector.cpp:357:7:357:8 | v5 | vector.cpp:356:8:356:13 | call to source | -| vector.cpp:359:7:359:8 | v5 | vector.cpp:356:8:356:13 | call to source | -| vector.cpp:363:7:363:8 | v6 | vector.cpp:362:8:362:13 | call to source | -| vector.cpp:365:7:365:8 | v6 | vector.cpp:362:8:362:13 | call to source | -| vector.cpp:370:8:370:9 | v7 | vector.cpp:369:9:369:14 | call to source | -| vector.cpp:375:7:375:8 | v7 | vector.cpp:369:9:369:14 | call to source | -| vector.cpp:379:7:379:8 | v8 | vector.cpp:378:8:378:13 | call to source | -| vector.cpp:381:7:381:8 | v8 | vector.cpp:378:8:378:13 | call to source | -| vector.cpp:388:7:388:8 | v9 | vector.cpp:330:10:330:15 | call to source | -| vector.cpp:388:7:388:8 | v9 | vector.cpp:385:8:385:13 | call to source | +| vector.cpp:342:7:342:8 | v1 | vector.cpp:341:8:341:13 | call to source | +| vector.cpp:347:7:347:8 | v2 | vector.cpp:345:9:345:14 | call to source | +| vector.cpp:357:7:357:8 | v4 | vector.cpp:330:10:330:15 | call to source | +| vector.cpp:361:7:361:8 | v5 | vector.cpp:360:8:360:13 | call to source | +| vector.cpp:363:7:363:8 | v5 | vector.cpp:360:8:360:13 | call to source | +| vector.cpp:367:7:367:8 | v6 | vector.cpp:366:8:366:13 | call to source | +| vector.cpp:369:7:369:8 | v6 | vector.cpp:366:8:366:13 | call to source | +| vector.cpp:374:8:374:9 | v7 | vector.cpp:373:9:373:14 | call to source | +| vector.cpp:379:7:379:8 | v7 | vector.cpp:373:9:373:14 | call to source | +| vector.cpp:383:7:383:8 | v8 | vector.cpp:382:8:382:13 | call to source | +| vector.cpp:385:7:385:8 | v8 | vector.cpp:382:8:382:13 | call to source | +| vector.cpp:392:7:392:8 | v9 | vector.cpp:330:10:330:15 | call to source | +| vector.cpp:392:7:392:8 | v9 | vector.cpp:389:8:389:13 | call to source | +| vector.cpp:396:7:396:9 | v10 | vector.cpp:399:38:399:43 | call to source | +| vector.cpp:400:7:400:9 | v11 | vector.cpp:399:38:399:43 | 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 db6bf0f3cf0..6397c1d7830 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 @@ -300,16 +300,18 @@ | vector.cpp:312:7:312:7 | vector.cpp:303:14:303:19 | AST only | | vector.cpp:324:7:324:8 | vector.cpp:318:15:318:20 | AST only | | vector.cpp:326:7:326:8 | vector.cpp:318:15:318:20 | AST only | -| vector.cpp:338:7:338:8 | vector.cpp:337:8:337:13 | AST only | -| vector.cpp:343:7:343:8 | vector.cpp:341:9:341:14 | AST only | -| vector.cpp:353:7:353:8 | vector.cpp:330:10:330:15 | AST only | -| vector.cpp:357:7:357:8 | vector.cpp:356:8:356:13 | AST only | -| vector.cpp:359:7:359:8 | vector.cpp:356:8:356:13 | AST only | -| vector.cpp:363:7:363:8 | vector.cpp:362:8:362:13 | AST only | -| vector.cpp:365:7:365:8 | vector.cpp:362:8:362:13 | AST only | -| vector.cpp:370:8:370:9 | vector.cpp:369:9:369:14 | AST only | -| vector.cpp:375:7:375:8 | vector.cpp:369:9:369:14 | AST only | -| vector.cpp:379:7:379:8 | vector.cpp:378:8:378:13 | AST only | -| vector.cpp:381:7:381:8 | vector.cpp:378:8:378:13 | AST only | -| vector.cpp:388:7:388:8 | vector.cpp:330:10:330:15 | AST only | -| vector.cpp:388:7:388:8 | vector.cpp:385:8:385:13 | AST only | +| vector.cpp:342:7:342:8 | vector.cpp:341:8:341:13 | AST only | +| vector.cpp:347:7:347:8 | vector.cpp:345:9:345:14 | AST only | +| vector.cpp:357:7:357:8 | vector.cpp:330:10:330:15 | AST only | +| vector.cpp:361:7:361:8 | vector.cpp:360:8:360:13 | AST only | +| vector.cpp:363:7:363:8 | vector.cpp:360:8:360:13 | AST only | +| vector.cpp:367:7:367:8 | vector.cpp:366:8:366:13 | AST only | +| vector.cpp:369:7:369:8 | vector.cpp:366:8:366:13 | AST only | +| vector.cpp:374:8:374:9 | vector.cpp:373:9:373:14 | AST only | +| vector.cpp:379:7:379:8 | vector.cpp:373:9:373:14 | AST only | +| vector.cpp:383:7:383:8 | vector.cpp:382:8:382:13 | AST only | +| vector.cpp:385:7:385:8 | vector.cpp:382:8:382:13 | AST only | +| vector.cpp:392:7:392:8 | vector.cpp:330:10:330:15 | AST only | +| vector.cpp:392:7:392:8 | vector.cpp:389:8:389:13 | AST only | +| vector.cpp:396:7:396:9 | vector.cpp:399:38:399:43 | AST only | +| vector.cpp:400:7:400:9 | vector.cpp:399:38:399:43 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp index 92cd5f4c9f5..0cc6570a175 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp @@ -330,8 +330,12 @@ void taint_vector_output_iterator(std::vector::iterator iter) { *iter = source(); } +void vector_iterator_assign_wrapper(std::vector::iterator iter, int i) { + *iter = i; +} + void test_vector_output_iterator(int b) { - std::vector v1(10), v2(10), v3(10), v4(10), v5(10), v6(10), v7(10), v8(10), v9(10); + std::vector v1(10), v2(10), v3(10), v4(10), v5(10), v6(10), v7(10), v8(10), v9(10), v10(10), v11(10); std::vector::iterator i1 = v1.begin(); *i1 = source(); @@ -386,4 +390,12 @@ void test_vector_output_iterator(int b) { taint_vector_output_iterator(i9); sink(v9); + + std::vector::iterator i10 = v10.begin(); + vector_iterator_assign_wrapper(i10, 10); + sink(v10); // FALSE POSITIVE + + std::vector::iterator i11 = v11.begin(); + vector_iterator_assign_wrapper(i11, source()); + sink(v11); // tainted [NOT DETECTED by IR] } From 9e3bfe1968c3c39339bf638ce47a709c9a1effc4 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 21 Sep 2020 16:17:16 -0700 Subject: [PATCH 025/411] C++: Fix iterator flow context sensitivity --- .../cpp/dataflow/internal/DataFlowPrivate.qll | 6 ++- .../cpp/dataflow/internal/DataFlowUtil.qll | 42 ++++++++++++------- .../code/cpp/dataflow/internal/FlowVar.qll | 7 ++++ .../dataflow/internal/TaintTrackingUtil.qll | 5 --- .../dataflow/taint-tests/taint.expected | 1 - .../dataflow/taint-tests/test_diff.expected | 1 - 6 files changed, 37 insertions(+), 25 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index 42c31bca69c..e737f8b2d94 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -1,6 +1,8 @@ private import cpp private import DataFlowUtil private import DataFlowDispatch +private import FlowVar + /** Gets the instance argument of a non-static call. */ private Node getInstanceArgument(Call call) { @@ -106,7 +108,7 @@ private class ExprOutNode extends OutNode, ExprNode { override DataFlowCall getCall() { result = this.getExpr() } } -private class RefOutNode extends OutNode, DefinitionByReferenceNode { +private class RefOutNode extends OutNode, DefinitionByReferenceOrIteratorNode { /** Gets the underlying call. */ override DataFlowCall getCall() { result = this.getArgument().getParent() } } @@ -120,7 +122,7 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) { kind = TNormalReturnKind() or exists(int i | - result.asDefiningArgument() = call.getArgument(i) and + result.(DefinitionByReferenceOrIteratorNode).getArgument() = call.getArgument(i) and kind = TRefReturnKind(i) ) } 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 963f1a17826..25a37f9db0f 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -182,29 +182,23 @@ class ImplicitParameterNode extends ParameterNode, TInstanceParameterNode { override predicate isParameterOf(Function fun, int i) { f = fun and i = -1 } } -/** - * A node that represents the value of a variable after a function call that - * may have changed the variable because it's passed by reference. - * - * A typical example would be a call `f(&x)`. Firstly, there will be flow into - * `x` from previous definitions of `x`. Secondly, there will be a - * `DefinitionByReferenceNode` to represent the value of `x` after the call has - * returned. This node will have its `getArgument()` equal to `&x`. - */ -class DefinitionByReferenceNode extends PartialDefinitionNode { +class DefinitionByReferenceOrIteratorNode extends PartialDefinitionNode { Expr inner; Expr argument; - DefinitionByReferenceNode() { - this.getPartialDefinition().(DefinitionByReference).definesExpressions(inner, argument) + DefinitionByReferenceOrIteratorNode() { + this.getPartialDefinition().definesExpressions(inner, argument) and + ( + this.getPartialDefinition() instanceof DefinitionByReference + or + this.getPartialDefinition() instanceof DefinitionByIterator + ) } override Function getFunction() { result = inner.getEnclosingFunction() } override Type getType() { result = inner.getType() } - override string toString() { result = "ref arg " + argument.toString() } - override Location getLocation() { result = argument.getLocation() } override ExprNode getPreUpdateNode() { result.getExpr() = argument } @@ -221,6 +215,22 @@ class DefinitionByReferenceNode extends PartialDefinitionNode { } } + +/** + * A node that represents the value of a variable after a function call that + * may have changed the variable because it's passed by reference. + * + * A typical example would be a call `f(&x)`. Firstly, there will be flow into + * `x` from previous definitions of `x`. Secondly, there will be a + * `DefinitionByReferenceNode` to represent the value of `x` after the call has + * returned. This node will have its `getArgument()` equal to `&x`. + */ +class DefinitionByReferenceNode extends DefinitionByReferenceOrIteratorNode { + override VariablePartialDefinition pd; + + override string toString() { result = "ref arg " + argument.toString() } +} + /** * The value of an uninitialized local variable, viewed as a node in a data * flow graph. @@ -551,10 +561,10 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { or // In `f(&x->a)`, this step provides the flow from post-`&` to post-`x->a`, // from which there is field flow to `x` via reverse read. - exists(VariablePartialDefinition def, Expr inner, Expr outer | + exists(PartialDefinition def, Expr inner, Expr outer | def.definesExpressions(inner, outer) and inner = nodeTo.(InnerPartialDefinitionNode).getPreUpdateNode().asExpr() and - outer = nodeFrom.(VariablePartialDefinitionNode).getPreUpdateNode().asExpr() + outer = nodeFrom.(PartialDefinitionNode).getPreUpdateNode().asExpr() ) or // Reverse flow: data that flows from the post-update node of a reference diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll index 13f11f8b275..15c15595c4f 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll @@ -243,6 +243,13 @@ private module PartialDefinitions { } } + /** + * A partial definition that's a definition by reference. + */ + class DefinitionByIterator extends IteratorPartialDefinition { + DefinitionByIterator() { exists(Call c | this = c.getAnArgument() or this = c.getQualifier()) } + } + /** * A partial definition that's a definition by reference. */ 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 3190d3e9eba..17cb9b88104 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll @@ -31,11 +31,6 @@ predicate localTaintStep(DataFlow::Node src, DataFlow::Node sink) { */ predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) { localAdditionalTaintStep(src, sink) - or - exists(FunctionCall call, int i | - sink.(DataFlow::IteratorPartialDefinitionNode).getPartialDefinition().definesExpressions(_, call.getArgument(i)) and - src.(DataFlow::RefParameterFinalValueNode).getParameter() = call.getTarget().getParameter(i) - ) } /** 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 f91b718bdda..033cd47145b 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -388,5 +388,4 @@ | vector.cpp:385:7:385:8 | v8 | vector.cpp:382:8:382:13 | call to source | | vector.cpp:392:7:392:8 | v9 | vector.cpp:330:10:330:15 | call to source | | vector.cpp:392:7:392:8 | v9 | vector.cpp:389:8:389:13 | call to source | -| vector.cpp:396:7:396:9 | v10 | vector.cpp:399:38:399:43 | call to source | | vector.cpp:400:7:400:9 | v11 | vector.cpp:399:38:399:43 | 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 6397c1d7830..3dc9b717e07 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 @@ -313,5 +313,4 @@ | vector.cpp:385:7:385:8 | vector.cpp:382:8:382:13 | AST only | | vector.cpp:392:7:392:8 | vector.cpp:330:10:330:15 | AST only | | vector.cpp:392:7:392:8 | vector.cpp:389:8:389:13 | AST only | -| vector.cpp:396:7:396:9 | vector.cpp:399:38:399:43 | AST only | | vector.cpp:400:7:400:9 | vector.cpp:399:38:399:43 | AST only | From 772a51508f09f8b8b7d2e256db11dab0fbfd33f6 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 21 Sep 2020 16:19:41 -0700 Subject: [PATCH 026/411] C++: Update test comment --- cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp index 0cc6570a175..b5dad811998 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp @@ -393,7 +393,7 @@ void test_vector_output_iterator(int b) { std::vector::iterator i10 = v10.begin(); vector_iterator_assign_wrapper(i10, 10); - sink(v10); // FALSE POSITIVE + sink(v10); std::vector::iterator i11 = v11.begin(); vector_iterator_assign_wrapper(i11, source()); From e836bae20ffaacd925a1f6d999452fa266f4d8db Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 18 Sep 2020 10:45:27 +0100 Subject: [PATCH 027/411] C++: Tidy up test stl.h a little. --- cpp/ql/test/library-tests/dataflow/taint-tests/stl.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h index f04eb5a01d4..a2ac49148fb 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h @@ -128,7 +128,12 @@ namespace std template basic_string operator+(const basic_string& lhs, const charT* rhs); typedef basic_string string; +} +// --- istring / ostream / stringstream --- + +namespace std +{ template > class basic_istream /*: virtual public basic_ios - not needed for this test */ { public: From 7dce4d0a6e5944cf349277c6da6f8d4311df4159 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 22 Sep 2020 13:39:22 +0200 Subject: [PATCH 028/411] C++: Rename: name the file the same as the class --- ...leRangeAnalysisDef.qll => SimpleRangeAnalysisDefinition.qll} | 0 .../src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/{SimpleRangeAnalysisDef.qll => SimpleRangeAnalysisDefinition.qll} (100%) diff --git a/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisDef.qll b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisDefinition.qll similarity index 100% rename from cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisDef.qll rename to cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisDefinition.qll diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index 05c2e519b46..d6e7d62435c 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -45,7 +45,7 @@ import cpp private import RangeAnalysisUtils private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr -private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisDef +private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisDefinition import RangeSSA import SimpleRangeAnalysisCached private import NanAnalysis From 8065bf15ad865d50ebed795dd12eb6f6079a8921 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 22 Sep 2020 13:37:24 +0200 Subject: [PATCH 029/411] C++: Per-variable overrides Without these changes, there was no way to tell which variables were overridden by a given instance of `SimpleRangeAnalysisDefinition`. All four overrides are needed because they fit into different mutual recursions of the `SimpleRangeAnalysis` implementation. --- .../SimpleRangeAnalysisDefinition.qll | 53 ++++++++++++++----- .../cpp/rangeanalysis/SimpleRangeAnalysis.qll | 11 ++-- 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisDefinition.qll b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisDefinition.qll index c2647e2bebc..e1d64dfcf5a 100644 --- a/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisDefinition.qll +++ b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisDefinition.qll @@ -10,25 +10,54 @@ import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis /** * EXPERIMENTAL: The API of this class may change without notice. * - * An SSA definition for which a range can be deduced. Extend this class to add - * functionality to the range analysis library. + * An SSA definition for which a range can be deduced. As with + * `RangeSsaDefinition` and `SsaDefinition`, instances of this class + * correspond to points in the program where one or more variables are defined + * or have their value constrained in some way. + * + * Extend this class to add functionality to the range analysis library. */ abstract class SimpleRangeAnalysisDefinition extends RangeSsaDefinition { - /** - * Gets the lower bound of the defomotopn. + /** + * Holds if this `SimpleRangeAnalysisDefinition` adds range information for + * `v`. Because a `SimpleRangeAnalysisDefinition` is just a point in the + * program, it's possible that more than one variable might be defined at + * this point. This predicate clarifies which variable(s) should get range + * information from `this`. * - * Implementations of this predicate should use - * `getFullyConvertedLowerBounds` and `getFullyConvertedUpperBounds` for - * recursive calls to get the bounds of their children. + * This predicate **must be overridden** to hold for any `v` that can show + * up in the other members of `SimpleRangeAnalysisDefinition`. Conversely, + * the other members **must be accurate** for any `v` in this predicate. */ - abstract float getLowerBounds(); + abstract predicate hasRangeInformationFor(StackVariable v); /** - * Gets the upper bound of the definition. + * Holds if `(this, v)` depends on the range of the unconverted expression + * `e`. This information is used to inform the range analysis about cyclic + * dependencies. Without this information, range analysis might work for + * simple cases but will go into infinite loops on complex code. + * + * For example, when modelling the definition by reference in a call to an + * overloaded `operator=`, written as `v = e`, the definition of `(this, v)` + * depends on `e`. + */ + abstract predicate dependsOnExpr(StackVariable v, Expr e); + + /** + * Gets the lower bound of the variable `v` defined by this definition. * * Implementations of this predicate should use * `getFullyConvertedLowerBounds` and `getFullyConvertedUpperBounds` for - * recursive calls to get the bounds of their children. + * recursive calls to get the bounds of their dependencies. */ - abstract float getUpperBounds(); -} \ No newline at end of file + abstract float getLowerBounds(StackVariable v); + + /** + * Gets the upper bound of the variable `v` defined by this definition. + * + * Implementations of this predicate should use + * `getFullyConvertedLowerBounds` and `getFullyConvertedUpperBounds` for + * recursive calls to get the bounds of their dependencies. + */ + abstract float getUpperBounds(StackVariable v); +} diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index d6e7d62435c..886c6347622 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -336,6 +336,11 @@ private predicate defDependsOnDef( or // Phi nodes. phiDependsOnDef(def, v, srcDef, srcVar) + or + // Extensions + exists(Expr expr | def.(SimpleRangeAnalysisDefinition).dependsOnExpr(v, expr) | + exprDependsOnDef(expr, srcDef, srcVar) + ) } /** @@ -495,7 +500,7 @@ private predicate analyzableDef(RangeSsaDefinition def, StackVariable v) { phiDependsOnDef(def, v, _, _) or // A modeled def for range analysis - def.(SimpleRangeAnalysisDefinition).getAVariable() =v + def.(SimpleRangeAnalysisDefinition).hasRangeInformationFor(v) } /** @@ -1220,7 +1225,7 @@ private float getDefLowerBoundsImpl(RangeSsaDefinition def, StackVariable v) { result = getPhiLowerBounds(v, def) or // A modeled def for range analysis - result = def.(SimpleRangeAnalysisDefinition).getLowerBounds() + result = def.(SimpleRangeAnalysisDefinition).getLowerBounds(v) or // Unanalyzable definitions. unanalyzableDefBounds(def, v, result, _) @@ -1256,7 +1261,7 @@ private float getDefUpperBoundsImpl(RangeSsaDefinition def, StackVariable v) { result = getPhiUpperBounds(v, def) or // A modeled def for range analysis - result = def.(SimpleRangeAnalysisDefinition).getUpperBounds() + result = def.(SimpleRangeAnalysisDefinition).getUpperBounds(v) or // Unanalyzable definitions. unanalyzableDefBounds(def, v, _, result) From d1f453be368103541800393a669e6014edac1092 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 22 Sep 2020 13:40:27 +0200 Subject: [PATCH 030/411] C++: import SimpleRangeAnalysisInternal This ensures that `getFullyConverted{Lower,Upper}Bounds` are available where they need to be called. --- .../cpp/models/interfaces/SimpleRangeAnalysisDefinition.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisDefinition.qll b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisDefinition.qll index e1d64dfcf5a..0cf570a72b4 100644 --- a/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisDefinition.qll +++ b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisDefinition.qll @@ -61,3 +61,5 @@ abstract class SimpleRangeAnalysisDefinition extends RangeSsaDefinition { */ abstract float getUpperBounds(StackVariable v); } + +import SimpleRangeAnalysisInternal From 826632d6a96b636f54ce674a3e0a1b8e755c71b8 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 22 Sep 2020 14:02:14 +0200 Subject: [PATCH 031/411] C++: Add a test of def overrides The def used in this test is not overridden yet. --- .../rangeanalysis/extensibility/extensibility.c | 7 ++++++- .../rangeanalysis/extensibility/extensibility.expected | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.c b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.c index afdde0b615c..288b68a0bd7 100644 --- a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.c +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.c @@ -11,4 +11,9 @@ int test_extensibility_add(int x) { int test_overridability_sub(int x) { int result = x - x; // Returns 0 due to custom modeling in QL return result; // 0 -} \ No newline at end of file +} + +void test_parameter_override(int magic_name_at_most_10, int magic_name_at_most_20) { + magic_name_at_most_10; + magic_name_at_most_20; +} diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected index ad97d9b2df5..4ae1961c247 100644 --- a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected @@ -5,3 +5,5 @@ | extensibility.c:12:16:12:16 | x | -2.147483648E9 | 2.147483647E9 | | extensibility.c:12:20:12:20 | x | -2.147483648E9 | 2.147483647E9 | | extensibility.c:13:10:13:15 | result | 0.0 | 0.0 | +| extensibility.c:17:3:17:23 | magic_name_at_most_10 | -2.147483648E9 | 2.147483647E9 | +| extensibility.c:18:3:18:23 | magic_name_at_most_20 | -2.147483648E9 | 2.147483647E9 | From 9fd8b0431ae8e58ddadce0b68cab4cd7c7befcad Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 22 Sep 2020 15:45:17 +0200 Subject: [PATCH 032/411] C++: Add a SimpleRangeAnalysisDefinition test def --- .../extensibility/extensibility.expected | 4 +-- .../extensibility/extensibility.ql | 36 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected index 4ae1961c247..cc8508a7858 100644 --- a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected @@ -5,5 +5,5 @@ | extensibility.c:12:16:12:16 | x | -2.147483648E9 | 2.147483647E9 | | extensibility.c:12:20:12:20 | x | -2.147483648E9 | 2.147483647E9 | | extensibility.c:13:10:13:15 | result | 0.0 | 0.0 | -| extensibility.c:17:3:17:23 | magic_name_at_most_10 | -2.147483648E9 | 2.147483647E9 | -| extensibility.c:18:3:18:23 | magic_name_at_most_20 | -2.147483648E9 | 2.147483647E9 | +| extensibility.c:17:3:17:23 | magic_name_at_most_10 | -2.147483648E9 | 10.0 | +| extensibility.c:18:3:18:23 | magic_name_at_most_20 | -2.147483648E9 | 20.0 | diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql index a007a5d4dab..841fe2c8e6c 100644 --- a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql @@ -1,5 +1,7 @@ import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis +import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils // for typeLowerBound import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr +import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisDefinition class CustomAddFunctionCall extends SimpleRangeAnalysisExpr, FunctionCall { CustomAddFunctionCall() { this.getTarget().hasGlobalName("custom_add_function") } @@ -37,6 +39,40 @@ class SelfSub extends SimpleRangeAnalysisExpr, SubExpr { override predicate dependsOnChild(Expr child) { child = this.getAnOperand() } } +/** + * A definition for test purposes of a parameter `p` that starts with a + * special prefix. This class is written to exploit how QL behaves when class + * fields are not functionally determined by `this`. When multiple parameters + * of the same function have the special prefix, there is still only one + * instance of this class. + */ +class MagicParameterName extends SimpleRangeAnalysisDefinition { + Parameter p; + float value; + + MagicParameterName() { + this.definedByParameter(p) and + value = p.getName().regexpCapture("magic_name_at_most_(\\d+)", 1).toFloat() + } + + override predicate hasRangeInformationFor(StackVariable v) { v = p } + + override predicate dependsOnExpr(StackVariable v, Expr e) { + // No dependencies. This sample class yields constant values. + none() + } + + override float getLowerBounds(StackVariable var) { + var = p and + result = typeLowerBound(p.getUnspecifiedType()) + } + + override float getUpperBounds(StackVariable var) { + var = p and + result = value + } +} + from VariableAccess expr, float lower, float upper where lower = lowerBound(expr) and From 4faeede5cd60ea2ec114b5865ca1f62798400801 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 22 Sep 2020 16:55:25 +0200 Subject: [PATCH 033/411] C++: Remove unnecessary comment on import --- .../library-tests/rangeanalysis/extensibility/extensibility.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql index 841fe2c8e6c..4fbfed1706d 100644 --- a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql @@ -1,5 +1,5 @@ import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis -import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils // for typeLowerBound +import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisDefinition From 252f8aa89d8a7df958805540ab827ed517cb2a8b Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Tue, 22 Sep 2020 15:20:40 +0200 Subject: [PATCH 034/411] Java: add Spring::MultipartRequest as taint source --- ...-09-23-spring-multipart-request-sources.md | 3 +++ .../semmle/code/java/dataflow/FlowSources.qll | 21 ++++++++++++++++++- .../taintsources/SpringMultiPart.java | 10 +++++++++ .../dataflow/taintsources/remote.expected | 18 ++++++++++------ 4 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 java/change-notes/2020-09-23-spring-multipart-request-sources.md diff --git a/java/change-notes/2020-09-23-spring-multipart-request-sources.md b/java/change-notes/2020-09-23-spring-multipart-request-sources.md new file mode 100644 index 00000000000..4e5f7740b85 --- /dev/null +++ b/java/change-notes/2020-09-23-spring-multipart-request-sources.md @@ -0,0 +1,3 @@ +lgtm,codescanning +* The methods of the [Spring Web MultipartRequest](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/multipart/MultipartRequest.html) + class have been added as sources of remote user input, which may lead to more results from the security queries. diff --git a/java/ql/src/semmle/code/java/dataflow/FlowSources.qll b/java/ql/src/semmle/code/java/dataflow/FlowSources.qll index b6d367bc32c..fb2a0345b8b 100644 --- a/java/ql/src/semmle/code/java/dataflow/FlowSources.qll +++ b/java/ql/src/semmle/code/java/dataflow/FlowSources.qll @@ -106,12 +106,31 @@ private class MessageBodyReaderParameterSource extends RemoteFlowSource { override string getSourceType() { result = "MessageBodyReader parameter" } } +private class SpringMultipartRequestSource extends RemoteFlowSource { + SpringMultipartRequestSource() { + exists(MethodAccess ma, Method m | + ma = this.asExpr() and + m = ma.getMethod() and + m + .getDeclaringType() + .getASourceSupertype*() + .hasQualifiedName("org.springframework.web.multipart", "MultipartRequest") and + m.getName().matches("get%") + ) + } + + override string getSourceType() { result = "Spring MultipartRequest getter" } +} + private class SpringMultipartFileSource extends RemoteFlowSource { SpringMultipartFileSource() { exists(MethodAccess ma, Method m | ma = this.asExpr() and m = ma.getMethod() and - m.getDeclaringType().hasQualifiedName("org.springframework.web.multipart", "MultipartFile") and + m + .getDeclaringType() + .getASourceSupertype*() + .hasQualifiedName("org.springframework.web.multipart", "MultipartFile") and m.getName().matches("get%") ) } diff --git a/java/ql/test/library-tests/dataflow/taintsources/SpringMultiPart.java b/java/ql/test/library-tests/dataflow/taintsources/SpringMultiPart.java index da5352dcde4..6702059ab70 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/SpringMultiPart.java +++ b/java/ql/test/library-tests/dataflow/taintsources/SpringMultiPart.java @@ -1,4 +1,5 @@ import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartRequest; public class SpringMultiPart { MultipartFile file; @@ -12,4 +13,13 @@ public class SpringMultiPart { file.getContentType(); file.getOriginalFilename(); } + + public void test(MultipartRequest request) { + request.getFile("name"); + request.getFileMap(); + request.getFileNames(); + request.getFiles("name"); + request.getMultiFileMap(); + request.getMultipartContentType("name"); + } } diff --git a/java/ql/test/library-tests/dataflow/taintsources/remote.expected b/java/ql/test/library-tests/dataflow/taintsources/remote.expected index bd2b3ac4296..21403e9f01b 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/remote.expected +++ b/java/ql/test/library-tests/dataflow/taintsources/remote.expected @@ -9,9 +9,15 @@ | RmiFlowImpl.java:4:30:4:40 | path | RmiFlowImpl.java:5:20:5:31 | ... + ... | | RmiFlowImpl.java:4:30:4:40 | path | RmiFlowImpl.java:5:28:5:31 | path | | RmiFlowImpl.java:4:30:4:40 | path | RmiFlowImpl.java:6:29:6:35 | command | -| SpringMultiPart.java:7:3:7:17 | getBytes(...) | SpringMultiPart.java:7:3:7:17 | getBytes(...) | -| SpringMultiPart.java:9:3:9:23 | getInputStream(...) | SpringMultiPart.java:9:3:9:23 | getInputStream(...) | -| SpringMultiPart.java:10:3:10:20 | getResource(...) | SpringMultiPart.java:10:3:10:20 | getResource(...) | -| SpringMultiPart.java:11:3:11:16 | getName(...) | SpringMultiPart.java:11:3:11:16 | getName(...) | -| SpringMultiPart.java:12:3:12:23 | getContentType(...) | SpringMultiPart.java:12:3:12:23 | getContentType(...) | -| SpringMultiPart.java:13:3:13:28 | getOriginalFilename(...) | SpringMultiPart.java:13:3:13:28 | getOriginalFilename(...) | +| SpringMultiPart.java:8:3:8:17 | getBytes(...) | SpringMultiPart.java:8:3:8:17 | getBytes(...) | +| SpringMultiPart.java:10:3:10:23 | getInputStream(...) | SpringMultiPart.java:10:3:10:23 | getInputStream(...) | +| SpringMultiPart.java:11:3:11:20 | getResource(...) | SpringMultiPart.java:11:3:11:20 | getResource(...) | +| SpringMultiPart.java:12:3:12:16 | getName(...) | SpringMultiPart.java:12:3:12:16 | getName(...) | +| SpringMultiPart.java:13:3:13:23 | getContentType(...) | SpringMultiPart.java:13:3:13:23 | getContentType(...) | +| SpringMultiPart.java:14:3:14:28 | getOriginalFilename(...) | SpringMultiPart.java:14:3:14:28 | getOriginalFilename(...) | +| SpringMultiPart.java:18:3:18:25 | getFile(...) | SpringMultiPart.java:18:3:18:25 | getFile(...) | +| SpringMultiPart.java:19:3:19:22 | getFileMap(...) | SpringMultiPart.java:19:3:19:22 | getFileMap(...) | +| SpringMultiPart.java:20:3:20:24 | getFileNames(...) | SpringMultiPart.java:20:3:20:24 | getFileNames(...) | +| SpringMultiPart.java:21:3:21:26 | getFiles(...) | SpringMultiPart.java:21:3:21:26 | getFiles(...) | +| SpringMultiPart.java:22:3:22:27 | getMultiFileMap(...) | SpringMultiPart.java:22:3:22:27 | getMultiFileMap(...) | +| SpringMultiPart.java:23:3:23:41 | getMultipartContentType(...) | SpringMultiPart.java:23:3:23:41 | getMultipartContentType(...) | From ec2b3f0b6ca6d07613b0b68cb13d89fc80e6f9f4 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 22 Sep 2020 21:02:26 +0200 Subject: [PATCH 035/411] better join-order fix in HTTP --- .../ql/src/semmle/javascript/frameworks/HTTP.qll | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll b/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll index 0f224ff060f..b3faa55501a 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll @@ -253,21 +253,20 @@ module HTTP { private predicate isDecoratedCall(DataFlow::CallNode call, DataFlow::FunctionNode decoratee) { // indirect route-handler `result` is given to function `outer`, which returns function `inner` which calls the function `pred`. exists(int i, DataFlow::FunctionNode outer, HTTP::RouteHandlerCandidate inner | + inner = outer.getAReturn().getALocalSource() and decoratee = call.getArgument(i).getALocalSource() and outer.getFunction() = call.getACallee() and - returnsRouteHandler(outer, inner) and - isAForwardingRouteHandlerCall(outer.getParameter(i), inner) + hasForwardingHandlerParameter(i, outer, inner) ) } /** - * Holds if `fun` returns the route-handler-candidate `routeHandler`. + * Holds if the `i`th parameter of `outer` has a call that `inner` forwards its parameters to. */ - pragma[noinline] - private predicate returnsRouteHandler( - DataFlow::FunctionNode fun, HTTP::RouteHandlerCandidate routeHandler + private predicate hasForwardingHandlerParameter( + int i, DataFlow::FunctionNode outer, HTTP::RouteHandlerCandidate inner ) { - routeHandler = fun.getAReturn().getALocalSource() + isAForwardingRouteHandlerCall(outer.getParameter(i), inner) } /** From 2868d5bf34648dddcf29ffa3f0d4107e08013740 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 22 Sep 2020 10:54:25 +0200 Subject: [PATCH 036/411] C#: Add pointer cast test cases --- .../conversion/pointer/Pointer.cs | 28 +++++++++++++++++++ .../conversion/pointer/Pointer.expected | 11 ++++++++ .../conversion/pointer/Pointer.ql | 5 ++++ 3 files changed, 44 insertions(+) create mode 100644 csharp/ql/test/library-tests/conversion/pointer/Pointer.cs create mode 100644 csharp/ql/test/library-tests/conversion/pointer/Pointer.expected create mode 100644 csharp/ql/test/library-tests/conversion/pointer/Pointer.ql diff --git a/csharp/ql/test/library-tests/conversion/pointer/Pointer.cs b/csharp/ql/test/library-tests/conversion/pointer/Pointer.cs new file mode 100644 index 00000000000..c7e12ac39b4 --- /dev/null +++ b/csharp/ql/test/library-tests/conversion/pointer/Pointer.cs @@ -0,0 +1,28 @@ +using System; + +class C +{ + unsafe static void M1(int[] arr) + { + fixed (int* i1 = arr) + { + } + + fixed (int* i2 = &arr[0]) + { + int* i3 = i2; + i3 = i3 + 1; + *i2 = *i2 + 1; + void* v2 = i2; + } + + int* i4 = null; + + int number = 1024; + byte* p = (byte*)&number; + + var s = "some string"; + fixed (char* c1 = s) + { } + } +} diff --git a/csharp/ql/test/library-tests/conversion/pointer/Pointer.expected b/csharp/ql/test/library-tests/conversion/pointer/Pointer.expected new file mode 100644 index 00000000000..7db63e5ef9f --- /dev/null +++ b/csharp/ql/test/library-tests/conversion/pointer/Pointer.expected @@ -0,0 +1,11 @@ +| Pointer.cs:7:21:7:28 | Pointer.cs:7:21:7:28 | Int32* | Int32[] | access to parameter arr | +| Pointer.cs:11:21:11:32 | Pointer.cs:11:21:11:32 | Int32* | Int32* | &... | +| Pointer.cs:13:18:13:24 | Pointer.cs:13:18:13:24 | Int32* | Int32* | access to local variable i2 | +| Pointer.cs:14:13:14:23 | Pointer.cs:14:13:14:23 | Int32* | Int32* | ... + ... | +| Pointer.cs:15:13:15:25 | Pointer.cs:15:13:15:25 | Int32 | Int32 | ... + ... | +| Pointer.cs:16:19:16:25 | Pointer.cs:16:19:16:25 | Void* | Void* | (...) ... | +| Pointer.cs:19:14:19:22 | Pointer.cs:19:14:19:22 | Int32* | null | null | +| Pointer.cs:21:13:21:25 | Pointer.cs:21:13:21:25 | Int32 | Int32 | 1024 | +| Pointer.cs:22:15:22:32 | Pointer.cs:22:15:22:32 | Byte* | Byte* | (...) ... | +| Pointer.cs:24:13:24:29 | Pointer.cs:24:13:24:29 | String | String | "some string" | +| Pointer.cs:25:22:25:27 | Pointer.cs:25:22:25:27 | Char* | String | access to local variable s | diff --git a/csharp/ql/test/library-tests/conversion/pointer/Pointer.ql b/csharp/ql/test/library-tests/conversion/pointer/Pointer.ql new file mode 100644 index 00000000000..69e7db8c1cf --- /dev/null +++ b/csharp/ql/test/library-tests/conversion/pointer/Pointer.ql @@ -0,0 +1,5 @@ +import csharp + +from Assignment a +select a.getLocation(), a.getLValue().getType().toString(), a.getRValue().getType().toString(), + a.getRValue().toString() From 48bf6d55aa3cb2807ea7776101e9e175588c936a Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 23 Sep 2020 12:19:42 +0200 Subject: [PATCH 037/411] C#: Add implicit cast from array to pointer --- .../Entities/Expressions/ImplicitCast.cs | 9 +++++++++ csharp/ql/test/experimental/ir/ir/PrintAst.expected | 3 ++- csharp/ql/test/experimental/ir/ir/raw_ir.expected | 4 ++-- .../controlflow/graph/BasicBlock.expected | 2 +- .../controlflow/graph/Dominance.expected | 12 ++++++++---- .../controlflow/graph/EnclosingCallable.expected | 2 ++ .../controlflow/graph/EntryElement.expected | 2 ++ .../controlflow/graph/ExitElement.expected | 2 ++ .../controlflow/graph/NodeGraph.expected | 6 ++++-- .../conversion/pointer/Pointer.expected | 4 ++-- .../dataflow/signanalysis/MissingSign.expected | 3 --- .../ql/test/library-tests/unsafe/PrintAst.expected | 3 ++- 12 files changed, 36 insertions(+), 16 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitCast.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitCast.cs index d8d8c80cf75..299c3aa8f72 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitCast.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitCast.cs @@ -86,6 +86,15 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions return new ImplicitCast(info); } + if (conversion.IsIdentity && conversion.IsImplicit && + convertedType.Symbol is IPointerTypeSymbol && + !(resolvedType.Symbol is IPointerTypeSymbol)) + { + // int[] -> int* + // string -> char* + return new ImplicitCast(info); + } + // Default: Just create the expression without a conversion. return Factory.Create(info); } diff --git a/csharp/ql/test/experimental/ir/ir/PrintAst.expected b/csharp/ql/test/experimental/ir/ir/PrintAst.expected index 0ba7be8a584..25ea10bc476 100644 --- a/csharp/ql/test/experimental/ir/ir/PrintAst.expected +++ b/csharp/ql/test/experimental/ir/ir/PrintAst.expected @@ -762,7 +762,8 @@ pointers.cs: # 5| 1: [LocalVariableAccess] access to local variable length # 6| 1: [FixedStmt] fixed(...) { ... } # 6| -1: [LocalVariableDeclAndInitExpr] Int32* b = ... -# 6| 0: [ParameterAccess] access to parameter arr +# 6| 0: [CastExpr] (...) ... +# 6| 0: [ParameterAccess] access to parameter arr # 6| 1: [LocalVariableAccess] access to local variable b # 7| 0: [BlockStmt] {...} # 8| 0: [LocalVariableDeclStmt] ... ...; diff --git a/csharp/ql/test/experimental/ir/ir/raw_ir.expected b/csharp/ql/test/experimental/ir/ir/raw_ir.expected index 785f3872787..e426955f9da 100644 --- a/csharp/ql/test/experimental/ir/ir/raw_ir.expected +++ b/csharp/ql/test/experimental/ir/ir/raw_ir.expected @@ -1327,8 +1327,8 @@ pointers.cs: # 6| r6_1(glval) = VariableAddress[b] : # 6| r6_2(glval) = VariableAddress[arr] : # 6| r6_3(Int32[]) = Load : &:r6_2, ~m? -# 6| r6_4(Int32*) = Convert : r6_3 -# 6| mu6_5(Int32*) = Store : &:r6_1, r6_3 +# 6| r6_4(Int32*) = CheckedConvertOrThrow : r6_3 +# 6| mu6_5(Int32*) = Store : &:r6_1, r6_4 # 8| r8_1(glval) = VariableAddress[p] : # 8| r8_2(glval) = VariableAddress[b] : # 8| r8_3(Int32*) = Load : &:r8_2, ~m? diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index cf6a34b5ba7..d7ca5bdd073 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -725,7 +725,7 @@ | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:7:13:7:22 | ... is ... | 14 | | TypeAccesses.cs:7:25:7:25 | ; | TypeAccesses.cs:7:25:7:25 | ; | 1 | | TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:3:10:3:10 | exit M | 4 | -| VarDecls.cs:5:18:5:19 | enter M1 | VarDecls.cs:5:18:5:19 | exit M1 | 16 | +| VarDecls.cs:5:18:5:19 | enter M1 | VarDecls.cs:5:18:5:19 | exit M1 | 18 | | VarDecls.cs:13:12:13:13 | enter M2 | VarDecls.cs:13:12:13:13 | exit M2 | 12 | | VarDecls.cs:19:7:19:8 | enter M3 | VarDecls.cs:25:20:25:20 | access to parameter b | 12 | | VarDecls.cs:25:13:25:29 | return ...; | VarDecls.cs:19:7:19:8 | exit M3 | 2 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index 9faece057e1..773e3cd0204 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -2568,11 +2568,13 @@ dominance | VarDecls.cs:7:9:10:9 | fixed(...) { ... } | VarDecls.cs:7:27:7:33 | access to parameter strings | | VarDecls.cs:7:22:7:36 | Char* c1 = ... | VarDecls.cs:7:44:7:50 | access to parameter strings | | VarDecls.cs:7:27:7:33 | access to parameter strings | VarDecls.cs:7:35:7:35 | 0 | -| VarDecls.cs:7:27:7:36 | access to array element | VarDecls.cs:7:22:7:36 | Char* c1 = ... | +| VarDecls.cs:7:27:7:36 | (...) ... | VarDecls.cs:7:22:7:36 | Char* c1 = ... | +| VarDecls.cs:7:27:7:36 | access to array element | VarDecls.cs:7:27:7:36 | (...) ... | | VarDecls.cs:7:35:7:35 | 0 | VarDecls.cs:7:27:7:36 | access to array element | | VarDecls.cs:7:39:7:53 | Char* c2 = ... | VarDecls.cs:8:9:10:9 | {...} | | VarDecls.cs:7:44:7:50 | access to parameter strings | VarDecls.cs:7:52:7:52 | 1 | -| VarDecls.cs:7:44:7:53 | access to array element | VarDecls.cs:7:39:7:53 | Char* c2 = ... | +| VarDecls.cs:7:44:7:53 | (...) ... | VarDecls.cs:7:39:7:53 | Char* c2 = ... | +| VarDecls.cs:7:44:7:53 | access to array element | VarDecls.cs:7:44:7:53 | (...) ... | | VarDecls.cs:7:52:7:52 | 1 | VarDecls.cs:7:44:7:53 | access to array element | | VarDecls.cs:8:9:10:9 | {...} | VarDecls.cs:9:27:9:28 | access to local variable c1 | | VarDecls.cs:9:13:9:29 | return ...; | VarDecls.cs:5:18:5:19 | exit M1 | @@ -5703,12 +5705,14 @@ postDominance | VarDecls.cs:5:18:5:19 | exit M1 | VarDecls.cs:9:13:9:29 | return ...; | | VarDecls.cs:6:5:11:5 | {...} | VarDecls.cs:5:18:5:19 | enter M1 | | VarDecls.cs:7:9:10:9 | fixed(...) { ... } | VarDecls.cs:6:5:11:5 | {...} | -| VarDecls.cs:7:22:7:36 | Char* c1 = ... | VarDecls.cs:7:27:7:36 | access to array element | +| VarDecls.cs:7:22:7:36 | Char* c1 = ... | VarDecls.cs:7:27:7:36 | (...) ... | | VarDecls.cs:7:27:7:33 | access to parameter strings | VarDecls.cs:7:9:10:9 | fixed(...) { ... } | +| VarDecls.cs:7:27:7:36 | (...) ... | VarDecls.cs:7:27:7:36 | access to array element | | VarDecls.cs:7:27:7:36 | access to array element | VarDecls.cs:7:35:7:35 | 0 | | VarDecls.cs:7:35:7:35 | 0 | VarDecls.cs:7:27:7:33 | access to parameter strings | -| VarDecls.cs:7:39:7:53 | Char* c2 = ... | VarDecls.cs:7:44:7:53 | access to array element | +| VarDecls.cs:7:39:7:53 | Char* c2 = ... | VarDecls.cs:7:44:7:53 | (...) ... | | VarDecls.cs:7:44:7:50 | access to parameter strings | VarDecls.cs:7:22:7:36 | Char* c1 = ... | +| VarDecls.cs:7:44:7:53 | (...) ... | VarDecls.cs:7:44:7:53 | access to array element | | VarDecls.cs:7:44:7:53 | access to array element | VarDecls.cs:7:52:7:52 | 1 | | VarDecls.cs:7:52:7:52 | 1 | VarDecls.cs:7:44:7:50 | access to parameter strings | | VarDecls.cs:8:9:10:9 | {...} | VarDecls.cs:7:39:7:53 | Char* c2 = ... | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected index 6dbf1e568b0..10afd142066 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected @@ -2931,10 +2931,12 @@ nodeEnclosing | VarDecls.cs:7:9:10:9 | fixed(...) { ... } | VarDecls.cs:5:18:5:19 | M1 | | VarDecls.cs:7:22:7:36 | Char* c1 = ... | VarDecls.cs:5:18:5:19 | M1 | | VarDecls.cs:7:27:7:33 | access to parameter strings | VarDecls.cs:5:18:5:19 | M1 | +| VarDecls.cs:7:27:7:36 | (...) ... | VarDecls.cs:5:18:5:19 | M1 | | VarDecls.cs:7:27:7:36 | access to array element | VarDecls.cs:5:18:5:19 | M1 | | VarDecls.cs:7:35:7:35 | 0 | VarDecls.cs:5:18:5:19 | M1 | | VarDecls.cs:7:39:7:53 | Char* c2 = ... | VarDecls.cs:5:18:5:19 | M1 | | VarDecls.cs:7:44:7:50 | access to parameter strings | VarDecls.cs:5:18:5:19 | M1 | +| VarDecls.cs:7:44:7:53 | (...) ... | VarDecls.cs:5:18:5:19 | M1 | | VarDecls.cs:7:44:7:53 | access to array element | VarDecls.cs:5:18:5:19 | M1 | | VarDecls.cs:7:52:7:52 | 1 | VarDecls.cs:5:18:5:19 | M1 | | VarDecls.cs:8:9:10:9 | {...} | VarDecls.cs:5:18:5:19 | M1 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected index 8751b4d35f7..cf3a8c054eb 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected @@ -2064,10 +2064,12 @@ | VarDecls.cs:7:9:10:9 | fixed(...) { ... } | VarDecls.cs:7:9:10:9 | fixed(...) { ... } | | VarDecls.cs:7:22:7:36 | Char* c1 = ... | VarDecls.cs:7:27:7:33 | access to parameter strings | | VarDecls.cs:7:27:7:33 | access to parameter strings | VarDecls.cs:7:27:7:33 | access to parameter strings | +| VarDecls.cs:7:27:7:36 | (...) ... | VarDecls.cs:7:27:7:33 | access to parameter strings | | VarDecls.cs:7:27:7:36 | access to array element | VarDecls.cs:7:27:7:33 | access to parameter strings | | VarDecls.cs:7:35:7:35 | 0 | VarDecls.cs:7:35:7:35 | 0 | | VarDecls.cs:7:39:7:53 | Char* c2 = ... | VarDecls.cs:7:44:7:50 | access to parameter strings | | VarDecls.cs:7:44:7:50 | access to parameter strings | VarDecls.cs:7:44:7:50 | access to parameter strings | +| VarDecls.cs:7:44:7:53 | (...) ... | VarDecls.cs:7:44:7:50 | access to parameter strings | | VarDecls.cs:7:44:7:53 | access to array element | VarDecls.cs:7:44:7:50 | access to parameter strings | | VarDecls.cs:7:52:7:52 | 1 | VarDecls.cs:7:52:7:52 | 1 | | VarDecls.cs:8:9:10:9 | {...} | VarDecls.cs:8:9:10:9 | {...} | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index 96165e8fe19..428ddfeca24 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -2770,10 +2770,12 @@ | VarDecls.cs:7:9:10:9 | fixed(...) { ... } | VarDecls.cs:9:13:9:29 | return ...; | return | | VarDecls.cs:7:22:7:36 | Char* c1 = ... | VarDecls.cs:7:22:7:36 | Char* c1 = ... | normal | | VarDecls.cs:7:27:7:33 | access to parameter strings | VarDecls.cs:7:27:7:33 | access to parameter strings | normal | +| VarDecls.cs:7:27:7:36 | (...) ... | VarDecls.cs:7:27:7:36 | (...) ... | normal | | VarDecls.cs:7:27:7:36 | access to array element | VarDecls.cs:7:27:7:36 | access to array element | normal | | VarDecls.cs:7:35:7:35 | 0 | VarDecls.cs:7:35:7:35 | 0 | normal | | VarDecls.cs:7:39:7:53 | Char* c2 = ... | VarDecls.cs:7:39:7:53 | Char* c2 = ... | normal | | VarDecls.cs:7:44:7:50 | access to parameter strings | VarDecls.cs:7:44:7:50 | access to parameter strings | normal | +| VarDecls.cs:7:44:7:53 | (...) ... | VarDecls.cs:7:44:7:53 | (...) ... | normal | | VarDecls.cs:7:44:7:53 | access to array element | VarDecls.cs:7:44:7:53 | access to array element | normal | | VarDecls.cs:7:52:7:52 | 1 | VarDecls.cs:7:52:7:52 | 1 | normal | | VarDecls.cs:8:9:10:9 | {...} | VarDecls.cs:9:13:9:29 | return ...; | return | diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 03cbc257d26..7feee30c18b 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -2937,11 +2937,13 @@ | VarDecls.cs:7:9:10:9 | fixed(...) { ... } | VarDecls.cs:7:27:7:33 | access to parameter strings | semmle.label | successor | | VarDecls.cs:7:22:7:36 | Char* c1 = ... | VarDecls.cs:7:44:7:50 | access to parameter strings | semmle.label | successor | | VarDecls.cs:7:27:7:33 | access to parameter strings | VarDecls.cs:7:35:7:35 | 0 | semmle.label | successor | -| VarDecls.cs:7:27:7:36 | access to array element | VarDecls.cs:7:22:7:36 | Char* c1 = ... | semmle.label | successor | +| VarDecls.cs:7:27:7:36 | (...) ... | VarDecls.cs:7:22:7:36 | Char* c1 = ... | semmle.label | successor | +| VarDecls.cs:7:27:7:36 | access to array element | VarDecls.cs:7:27:7:36 | (...) ... | semmle.label | successor | | VarDecls.cs:7:35:7:35 | 0 | VarDecls.cs:7:27:7:36 | access to array element | semmle.label | successor | | VarDecls.cs:7:39:7:53 | Char* c2 = ... | VarDecls.cs:8:9:10:9 | {...} | semmle.label | successor | | VarDecls.cs:7:44:7:50 | access to parameter strings | VarDecls.cs:7:52:7:52 | 1 | semmle.label | successor | -| VarDecls.cs:7:44:7:53 | access to array element | VarDecls.cs:7:39:7:53 | Char* c2 = ... | semmle.label | successor | +| VarDecls.cs:7:44:7:53 | (...) ... | VarDecls.cs:7:39:7:53 | Char* c2 = ... | semmle.label | successor | +| VarDecls.cs:7:44:7:53 | access to array element | VarDecls.cs:7:44:7:53 | (...) ... | semmle.label | successor | | VarDecls.cs:7:52:7:52 | 1 | VarDecls.cs:7:44:7:53 | access to array element | semmle.label | successor | | VarDecls.cs:8:9:10:9 | {...} | VarDecls.cs:9:27:9:28 | access to local variable c1 | semmle.label | successor | | VarDecls.cs:9:13:9:29 | return ...; | VarDecls.cs:5:18:5:19 | exit M1 | semmle.label | return | diff --git a/csharp/ql/test/library-tests/conversion/pointer/Pointer.expected b/csharp/ql/test/library-tests/conversion/pointer/Pointer.expected index 7db63e5ef9f..5aca5582d14 100644 --- a/csharp/ql/test/library-tests/conversion/pointer/Pointer.expected +++ b/csharp/ql/test/library-tests/conversion/pointer/Pointer.expected @@ -1,4 +1,4 @@ -| Pointer.cs:7:21:7:28 | Pointer.cs:7:21:7:28 | Int32* | Int32[] | access to parameter arr | +| Pointer.cs:7:21:7:28 | Pointer.cs:7:21:7:28 | Int32* | Int32* | (...) ... | | Pointer.cs:11:21:11:32 | Pointer.cs:11:21:11:32 | Int32* | Int32* | &... | | Pointer.cs:13:18:13:24 | Pointer.cs:13:18:13:24 | Int32* | Int32* | access to local variable i2 | | Pointer.cs:14:13:14:23 | Pointer.cs:14:13:14:23 | Int32* | Int32* | ... + ... | @@ -8,4 +8,4 @@ | Pointer.cs:21:13:21:25 | Pointer.cs:21:13:21:25 | Int32 | Int32 | 1024 | | Pointer.cs:22:15:22:32 | Pointer.cs:22:15:22:32 | Byte* | Byte* | (...) ... | | Pointer.cs:24:13:24:29 | Pointer.cs:24:13:24:29 | String | String | "some string" | -| Pointer.cs:25:22:25:27 | Pointer.cs:25:22:25:27 | Char* | String | access to local variable s | +| Pointer.cs:25:22:25:27 | Pointer.cs:25:22:25:27 | Char* | Char* | (...) ... | diff --git a/csharp/ql/test/library-tests/dataflow/signanalysis/MissingSign.expected b/csharp/ql/test/library-tests/dataflow/signanalysis/MissingSign.expected index 72f1bdadeda..2fd751f77e0 100644 --- a/csharp/ql/test/library-tests/dataflow/signanalysis/MissingSign.expected +++ b/csharp/ql/test/library-tests/dataflow/signanalysis/MissingSign.expected @@ -1,4 +1 @@ | SignAnalysis.cs:428:23:428:24 | access to constant A | -| SignAnalysis.cs:448:22:448:29 | Byte* to = ... | -| SignAnalysis.cs:450:38:450:44 | (...) ... | -| SignAnalysis.cs:450:43:450:44 | access to local variable to | diff --git a/csharp/ql/test/library-tests/unsafe/PrintAst.expected b/csharp/ql/test/library-tests/unsafe/PrintAst.expected index b4e9ce56c64..079719907c7 100644 --- a/csharp/ql/test/library-tests/unsafe/PrintAst.expected +++ b/csharp/ql/test/library-tests/unsafe/PrintAst.expected @@ -109,7 +109,8 @@ unsafe.cs: # 36| 1: [LocalVariableAccess] access to local variable data # 37| 1: [FixedStmt] fixed(...) { ... } # 37| -1: [LocalVariableDeclAndInitExpr] Int32* p = ... -# 37| 0: [LocalVariableAccess] access to local variable data +# 37| 0: [CastExpr] (...) ... +# 37| 0: [LocalVariableAccess] access to local variable data # 37| 1: [LocalVariableAccess] access to local variable p # 38| 0: [BlockStmt] {...} # 44| 2: [Class] SafeClass From 71a605b7d9b691ecee102e7226d1b4944815e726 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 18 Sep 2020 10:11:34 +0100 Subject: [PATCH 038/411] C++: Add tests for std::pair. --- .../dataflow/taint-tests/localTaint.expected | 161 +++++++++++++++++- .../dataflow/taint-tests/map.cpp | 93 ++++++++++ .../library-tests/dataflow/taint-tests/stl.h | 22 ++- .../dataflow/taint-tests/taint.expected | 2 + .../dataflow/taint-tests/test_ir.expected | 2 + 5 files changed, 273 insertions(+), 7 deletions(-) create mode 100644 cpp/ql/test/library-tests/dataflow/taint-tests/map.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 87e4566b2d8..b571ac46520 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -260,6 +260,7 @@ | file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | | | file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | | | file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | | +| file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | | | format.cpp:16:21:16:21 | s | format.cpp:22:22:22:22 | s | | | format.cpp:16:31:16:31 | n | format.cpp:22:25:22:25 | n | | | format.cpp:16:46:16:51 | format | format.cpp:22:28:22:33 | format | | @@ -390,6 +391,144 @@ | format.cpp:158:13:158:18 | call to wcslen | format.cpp:158:13:158:26 | ... / ... | TAINT | | format.cpp:158:13:158:26 | ... / ... | format.cpp:158:7:158:27 | ... + ... | TAINT | | format.cpp:158:26:158:26 | 2 | format.cpp:158:13:158:26 | ... / ... | TAINT | +| map.cpp:14:28:14:28 | call to pair | map.cpp:16:2:16:2 | a | | +| map.cpp:14:28:14:28 | call to pair | map.cpp:17:7:17:7 | a | | +| map.cpp:14:28:14:28 | call to pair | map.cpp:18:7:18:7 | a | | +| map.cpp:14:28:14:28 | call to pair | map.cpp:19:7:19:7 | a | | +| map.cpp:14:31:14:31 | call to pair | map.cpp:21:2:21:2 | b | | +| map.cpp:14:31:14:31 | call to pair | map.cpp:22:7:22:7 | b | | +| map.cpp:14:31:14:31 | call to pair | map.cpp:23:7:23:7 | b | | +| map.cpp:14:31:14:31 | call to pair | map.cpp:24:7:24:7 | b | | +| map.cpp:14:34:14:34 | call to pair | map.cpp:26:2:26:2 | c | | +| map.cpp:14:34:14:34 | call to pair | map.cpp:27:7:27:7 | c | | +| map.cpp:14:34:14:34 | call to pair | map.cpp:28:7:28:7 | c | | +| map.cpp:14:34:14:34 | call to pair | map.cpp:29:7:29:7 | c | | +| map.cpp:16:2:16:2 | a [post update] | map.cpp:17:7:17:7 | a | | +| map.cpp:16:2:16:2 | a [post update] | map.cpp:18:7:18:7 | a | | +| map.cpp:16:2:16:2 | a [post update] | map.cpp:19:7:19:7 | a | | +| map.cpp:16:2:16:16 | ... = ... | map.cpp:16:4:16:8 | first [post update] | | +| map.cpp:16:2:16:16 | ... = ... | map.cpp:17:9:17:13 | first | | +| map.cpp:16:12:16:16 | 123 | map.cpp:16:2:16:16 | ... = ... | | +| map.cpp:17:7:17:7 | a [post update] | map.cpp:18:7:18:7 | a | | +| map.cpp:17:7:17:7 | a [post update] | map.cpp:19:7:19:7 | a | | +| map.cpp:18:7:18:7 | a [post update] | map.cpp:19:7:19:7 | a | | +| map.cpp:21:2:21:2 | b [post update] | map.cpp:22:7:22:7 | b | | +| map.cpp:21:2:21:2 | b [post update] | map.cpp:23:7:23:7 | b | | +| map.cpp:21:2:21:2 | b [post update] | map.cpp:24:7:24:7 | b | | +| map.cpp:21:2:21:19 | ... = ... | map.cpp:21:4:21:8 | first [post update] | | +| map.cpp:21:2:21:19 | ... = ... | map.cpp:22:9:22:13 | first | | +| map.cpp:21:12:21:17 | call to source | map.cpp:21:2:21:19 | ... = ... | | +| map.cpp:22:7:22:7 | b [post update] | map.cpp:23:7:23:7 | b | | +| map.cpp:22:7:22:7 | b [post update] | map.cpp:24:7:24:7 | b | | +| map.cpp:23:7:23:7 | b [post update] | map.cpp:24:7:24:7 | b | | +| map.cpp:26:2:26:2 | c [post update] | map.cpp:27:7:27:7 | c | | +| map.cpp:26:2:26:2 | c [post update] | map.cpp:28:7:28:7 | c | | +| map.cpp:26:2:26:2 | c [post update] | map.cpp:29:7:29:7 | c | | +| map.cpp:26:2:26:20 | ... = ... | map.cpp:26:4:26:9 | second [post update] | | +| map.cpp:26:2:26:20 | ... = ... | map.cpp:28:9:28:14 | second | | +| map.cpp:26:13:26:18 | call to source | map.cpp:26:2:26:20 | ... = ... | | +| map.cpp:27:7:27:7 | c [post update] | map.cpp:28:7:28:7 | c | | +| map.cpp:27:7:27:7 | c [post update] | map.cpp:29:7:29:7 | c | | +| map.cpp:28:7:28:7 | c [post update] | map.cpp:29:7:29:7 | c | | +| map.cpp:31:30:31:42 | call to pair | map.cpp:32:7:32:7 | d | | +| map.cpp:31:30:31:42 | call to pair | map.cpp:33:7:33:7 | d | | +| map.cpp:31:30:31:42 | call to pair | map.cpp:34:7:34:7 | d | | +| map.cpp:32:7:32:7 | d [post update] | map.cpp:33:7:33:7 | d | | +| map.cpp:32:7:32:7 | d [post update] | map.cpp:34:7:34:7 | d | | +| map.cpp:33:7:33:7 | d [post update] | map.cpp:34:7:34:7 | d | | +| map.cpp:36:30:36:45 | call to pair | map.cpp:37:7:37:7 | e | | +| map.cpp:36:30:36:45 | call to pair | map.cpp:38:7:38:7 | e | | +| map.cpp:36:30:36:45 | call to pair | map.cpp:39:7:39:7 | e | | +| map.cpp:37:7:37:7 | e [post update] | map.cpp:38:7:38:7 | e | | +| map.cpp:37:7:37:7 | e [post update] | map.cpp:39:7:39:7 | e | | +| map.cpp:38:7:38:7 | e [post update] | map.cpp:39:7:39:7 | e | | +| map.cpp:41:30:41:45 | call to pair | map.cpp:42:7:42:7 | f | | +| map.cpp:41:30:41:45 | call to pair | map.cpp:43:7:43:7 | f | | +| map.cpp:41:30:41:45 | call to pair | map.cpp:44:7:44:7 | f | | +| map.cpp:41:30:41:45 | call to pair | map.cpp:46:30:46:30 | f | | +| map.cpp:41:30:41:45 | call to pair | map.cpp:47:7:47:7 | f | | +| map.cpp:41:30:41:45 | call to pair | map.cpp:48:7:48:7 | f | | +| map.cpp:41:30:41:45 | call to pair | map.cpp:49:7:49:7 | f | | +| map.cpp:41:30:41:45 | call to pair | map.cpp:52:6:52:6 | f | | +| map.cpp:42:7:42:7 | f [post update] | map.cpp:43:7:43:7 | f | | +| map.cpp:42:7:42:7 | f [post update] | map.cpp:44:7:44:7 | f | | +| map.cpp:42:7:42:7 | f [post update] | map.cpp:46:30:46:30 | f | | +| map.cpp:42:7:42:7 | f [post update] | map.cpp:47:7:47:7 | f | | +| map.cpp:42:7:42:7 | f [post update] | map.cpp:48:7:48:7 | f | | +| map.cpp:42:7:42:7 | f [post update] | map.cpp:49:7:49:7 | f | | +| map.cpp:42:7:42:7 | f [post update] | map.cpp:52:6:52:6 | f | | +| map.cpp:43:7:43:7 | f [post update] | map.cpp:44:7:44:7 | f | | +| map.cpp:43:7:43:7 | f [post update] | map.cpp:46:30:46:30 | f | | +| map.cpp:43:7:43:7 | f [post update] | map.cpp:47:7:47:7 | f | | +| map.cpp:43:7:43:7 | f [post update] | map.cpp:48:7:48:7 | f | | +| map.cpp:43:7:43:7 | f [post update] | map.cpp:49:7:49:7 | f | | +| map.cpp:43:7:43:7 | f [post update] | map.cpp:52:6:52:6 | f | | +| map.cpp:47:7:47:7 | f [post update] | map.cpp:48:7:48:7 | f | | +| map.cpp:47:7:47:7 | f [post update] | map.cpp:49:7:49:7 | f | | +| map.cpp:47:7:47:7 | f [post update] | map.cpp:52:6:52:6 | f | | +| map.cpp:48:7:48:7 | f [post update] | map.cpp:49:7:49:7 | f | | +| map.cpp:48:7:48:7 | f [post update] | map.cpp:52:6:52:6 | f | | +| map.cpp:52:6:52:6 | f | map.cpp:52:2:52:6 | ... = ... | | +| map.cpp:52:6:52:6 | f | map.cpp:53:7:53:7 | h | | +| map.cpp:52:6:52:6 | f | map.cpp:54:7:54:7 | h | | +| map.cpp:52:6:52:6 | f | map.cpp:55:7:55:7 | h | | +| map.cpp:53:7:53:7 | h [post update] | map.cpp:54:7:54:7 | h | | +| map.cpp:53:7:53:7 | h [post update] | map.cpp:55:7:55:7 | h | | +| map.cpp:54:7:54:7 | h [post update] | map.cpp:55:7:55:7 | h | | +| map.cpp:57:30:57:42 | call to pair | map.cpp:61:3:61:3 | i | | +| map.cpp:57:30:57:42 | call to pair | map.cpp:63:7:63:7 | i | | +| map.cpp:57:30:57:42 | call to pair | map.cpp:64:7:64:7 | i | | +| map.cpp:57:30:57:42 | call to pair | map.cpp:65:7:65:7 | i | | +| map.cpp:58:30:58:45 | call to pair | map.cpp:61:10:61:10 | j | | +| map.cpp:58:30:58:45 | call to pair | map.cpp:66:7:66:7 | j | | +| map.cpp:58:30:58:45 | call to pair | map.cpp:67:7:67:7 | j | | +| map.cpp:58:30:58:45 | call to pair | map.cpp:68:7:68:7 | j | | +| map.cpp:59:30:59:45 | call to pair | map.cpp:62:2:62:2 | k | | +| map.cpp:59:30:59:45 | call to pair | map.cpp:69:7:69:7 | k | | +| map.cpp:59:30:59:45 | call to pair | map.cpp:70:7:70:7 | k | | +| map.cpp:59:30:59:45 | call to pair | map.cpp:71:7:71:7 | k | | +| map.cpp:60:30:60:42 | call to pair | map.cpp:62:9:62:9 | l | | +| map.cpp:60:30:60:42 | call to pair | map.cpp:72:7:72:7 | l | | +| map.cpp:60:30:60:42 | call to pair | map.cpp:73:7:73:7 | l | | +| map.cpp:60:30:60:42 | call to pair | map.cpp:74:7:74:7 | l | | +| map.cpp:61:3:61:3 | ref arg i | map.cpp:63:7:63:7 | i | | +| map.cpp:61:3:61:3 | ref arg i | map.cpp:64:7:64:7 | i | | +| map.cpp:61:3:61:3 | ref arg i | map.cpp:65:7:65:7 | i | | +| map.cpp:61:10:61:10 | ref arg j | map.cpp:66:7:66:7 | j | | +| map.cpp:61:10:61:10 | ref arg j | map.cpp:67:7:67:7 | j | | +| map.cpp:61:10:61:10 | ref arg j | map.cpp:68:7:68:7 | j | | +| map.cpp:62:2:62:2 | ref arg k | map.cpp:69:7:69:7 | k | | +| map.cpp:62:2:62:2 | ref arg k | map.cpp:70:7:70:7 | k | | +| map.cpp:62:2:62:2 | ref arg k | map.cpp:71:7:71:7 | k | | +| map.cpp:62:9:62:9 | ref arg l | map.cpp:72:7:72:7 | l | | +| map.cpp:62:9:62:9 | ref arg l | map.cpp:73:7:73:7 | l | | +| map.cpp:62:9:62:9 | ref arg l | map.cpp:74:7:74:7 | l | | +| map.cpp:63:7:63:7 | i [post update] | map.cpp:64:7:64:7 | i | | +| map.cpp:63:7:63:7 | i [post update] | map.cpp:65:7:65:7 | i | | +| map.cpp:64:7:64:7 | i [post update] | map.cpp:65:7:65:7 | i | | +| map.cpp:66:7:66:7 | j [post update] | map.cpp:67:7:67:7 | j | | +| map.cpp:66:7:66:7 | j [post update] | map.cpp:68:7:68:7 | j | | +| map.cpp:67:7:67:7 | j [post update] | map.cpp:68:7:68:7 | j | | +| map.cpp:69:7:69:7 | k [post update] | map.cpp:70:7:70:7 | k | | +| map.cpp:69:7:69:7 | k [post update] | map.cpp:71:7:71:7 | k | | +| map.cpp:70:7:70:7 | k [post update] | map.cpp:71:7:71:7 | k | | +| map.cpp:72:7:72:7 | l [post update] | map.cpp:73:7:73:7 | l | | +| map.cpp:72:7:72:7 | l [post update] | map.cpp:74:7:74:7 | l | | +| map.cpp:73:7:73:7 | l [post update] | map.cpp:74:7:74:7 | l | | +| map.cpp:76:7:76:15 | call to make_pair | map.cpp:76:7:76:29 | call to pair | TAINT | +| map.cpp:79:7:79:15 | call to make_pair | map.cpp:79:7:79:32 | call to pair | TAINT | +| map.cpp:82:7:82:15 | call to make_pair | map.cpp:82:7:82:32 | call to pair | TAINT | +| map.cpp:87:6:87:14 | call to make_pair | map.cpp:87:6:87:49 | call to pair | TAINT | +| map.cpp:87:6:87:49 | call to pair | map.cpp:87:2:87:49 | ... = ... | | +| map.cpp:87:6:87:49 | call to pair | map.cpp:88:7:88:7 | m | | +| map.cpp:87:6:87:49 | call to pair | map.cpp:89:7:89:7 | m | | +| map.cpp:87:6:87:49 | call to pair | map.cpp:90:7:90:7 | m | | +| map.cpp:87:6:87:49 | call to pair | map.cpp:91:7:91:7 | m | | +| map.cpp:87:6:87:49 | call to pair | map.cpp:92:7:92:7 | m | | +| map.cpp:88:7:88:7 | m | map.cpp:88:7:88:7 | call to pair | TAINT | +| map.cpp:90:7:90:7 | m [post update] | map.cpp:91:7:91:7 | m | | +| map.cpp:90:7:90:7 | m [post update] | map.cpp:92:7:92:7 | m | | +| map.cpp:91:7:91:7 | m [post update] | map.cpp:92:7:92:7 | m | | | movableclass.cpp:8:2:8:15 | this | movableclass.cpp:8:27:8:31 | constructor init of field v [pre-this] | | | movableclass.cpp:8:21:8:22 | _v | movableclass.cpp:8:29:8:30 | _v | | | movableclass.cpp:8:29:8:30 | _v | movableclass.cpp:8:27:8:31 | constructor init of field v | TAINT | @@ -514,12 +653,22 @@ | standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:53:12:53:18 | source1 | | | standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:54:14:54:20 | source1 | | | standalone_iterators.cpp:53:12:53:18 | ref arg source1 | standalone_iterators.cpp:54:14:54:20 | source1 | | -| stl.h:216:30:216:40 | call to allocator | stl.h:216:21:216:41 | noexcept(...) | TAINT | -| stl.h:216:30:216:40 | call to allocator | stl.h:216:21:216:41 | noexcept(...) | TAINT | -| stl.h:216:30:216:40 | call to allocator | stl.h:216:21:216:41 | noexcept(...) | TAINT | -| stl.h:216:30:216:40 | call to allocator | stl.h:216:21:216:41 | noexcept(...) | TAINT | -| stl.h:216:30:216:40 | call to allocator | stl.h:216:21:216:41 | noexcept(...) | TAINT | -| stl.h:216:53:216:63 | 0 | stl.h:216:46:216:64 | (no string representation) | TAINT | +| stl.h:221:30:221:40 | call to allocator | stl.h:221:21:221:41 | noexcept(...) | TAINT | +| stl.h:221:30:221:40 | call to allocator | stl.h:221:21:221:41 | noexcept(...) | TAINT | +| stl.h:221:30:221:40 | call to allocator | stl.h:221:21:221:41 | noexcept(...) | TAINT | +| stl.h:221:30:221:40 | call to allocator | stl.h:221:21:221:41 | noexcept(...) | TAINT | +| stl.h:221:30:221:40 | call to allocator | stl.h:221:21:221:41 | noexcept(...) | TAINT | +| stl.h:221:53:221:63 | 0 | stl.h:221:46:221:64 | (no string representation) | TAINT | +| stl.h:314:9:314:9 | Unknown literal | stl.h:314:9:314:9 | constructor init of field first | TAINT | +| stl.h:314:9:314:9 | Unknown literal | stl.h:314:9:314:9 | constructor init of field first | TAINT | +| stl.h:314:9:314:9 | Unknown literal | stl.h:314:9:314:9 | constructor init of field second | TAINT | +| stl.h:314:9:314:9 | Unknown literal | stl.h:314:9:314:9 | constructor init of field second | TAINT | +| stl.h:314:9:314:9 | constructor init of field first [post-this] | stl.h:314:9:314:9 | constructor init of field second [pre-this] | | +| stl.h:314:9:314:9 | constructor init of field first [post-this] | stl.h:314:9:314:9 | constructor init of field second [pre-this] | | +| stl.h:314:9:314:9 | constructor init of field first [pre-this] | stl.h:314:9:314:9 | constructor init of field second [pre-this] | | +| stl.h:314:9:314:9 | constructor init of field first [pre-this] | stl.h:314:9:314:9 | constructor init of field second [pre-this] | | +| stl.h:314:9:314:9 | this | stl.h:314:9:314:9 | constructor init of field first [pre-this] | | +| stl.h:314:9:314:9 | this | stl.h:314:9:314:9 | constructor init of field first [pre-this] | | | string.cpp:24:12:24:17 | call to source | string.cpp:28:7:28:7 | a | | | string.cpp:25:16:25:20 | 123 | string.cpp:25:16:25:21 | call to basic_string | TAINT | | string.cpp:25:16:25:21 | call to basic_string | string.cpp:29:7:29:7 | b | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp new file mode 100644 index 00000000000..0da7369cda2 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp @@ -0,0 +1,93 @@ + +#include "stl.h" + +using namespace std; + +char *source(); + +void sink(char *); +void sink(const char *); +void sink(std::pair); + +void test_pair() +{ + std::pair a, b, c; + + a.first = "123"; + sink(a.first); + sink(a.second); + sink(a); + + b.first = source(); + sink(b.first); // tainted + sink(b.second); + sink(b); // tainted [NOT DETECTED] + + c.second = source(); + sink(c.first); + sink(c.second); // tainted + sink(c); // tainted [NOT DETECTED] + + std::pair d("123", "456"); + sink(d.first); + sink(d.second); + sink(d); + + std::pair e(source(), "456"); + sink(e.first); // tainted [NOT DETECTED] + sink(e.second); + sink(e); // tainted [NOT DETECTED] + + std::pair f("123", source()); + sink(f.first); + sink(f.second); // tainted [NOT DETECTED] + sink(f); // tainted [NOT DETECTED] + + std::pair g(f); + sink(f.first); + sink(f.second); // tainted [NOT DETECTED] + sink(f); // tainted [NOT DETECTED] + + std::pair h; + h = f; + sink(h.first); + sink(h.second); // tainted [NOT DETECTED] + sink(h); // tainted [NOT DETECTED] + + std::pair i("123", "456"); + std::pair j("123", source()); + std::pair k("123", source()); + std::pair l("123", "456"); + i.swap(j); + k.swap(l); + sink(i.first); + sink(i.second); // tainted [NOT DETECTED] + sink(i); // tainted [NOT DETECTED] + sink(j.first); + sink(j.second); + sink(j); + sink(k.first); + sink(k.second); + sink(k); + sink(l.first); + sink(l.second); // tainted [NOT DETECTED] + sink(l); // tainted [NOT DETECTED] + + sink(make_pair("123", "456")); + sink(make_pair("123", "456").first); + sink(make_pair("123", "456").second); + sink(make_pair(source(), "456")); // tainted [NOT DETECTED] + sink(make_pair(source(), "456").first); // tainted [NOT DETECTED] + sink(make_pair(source(), "456").second); + sink(make_pair("123", source())); // tainted [NOT DETECTED] + sink(make_pair("123", source()).first); + sink(make_pair("123", source()).second); // tainted [NOT DETECTED] + + std::pair, char *> m; + m = make_pair(make_pair("123", source()), "789"); + sink(m); // tainted [NOT DETECTED] + sink(m.first); // tainted [NOT DETECTED] + sink(m.first.first); + sink(m.first.second); // tainted [NOT DETECTED] + sink(m.second); +} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h index a2ac49148fb..c6b2150510f 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h @@ -305,4 +305,24 @@ namespace std { template unique_ptr make_unique(Args&&...); template shared_ptr make_shared(Args&&...); -} \ No newline at end of file +} + +// --- pair --- + +namespace std { + template + struct pair { + typedef T1 first_type; + typedef T2 second_type; + + T1 first; + T2 second; + pair(); + pair(const T1& x, const T2& y); + template pair(const pair &p); + + void swap(pair& p) /*noexcept(...)*/; + }; + + template pair make_pair(T1, T2); +} 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 69d57d3bab0..7032d498666 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -33,6 +33,8 @@ | format.cpp:115:8:115:13 | buffer | format.cpp:114:37:114:50 | call to source | | format.cpp:157:7:157:22 | access to array | format.cpp:147:12:147:25 | call to source | | format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source | +| map.cpp:22:9:22:13 | first | map.cpp:21:12:21:17 | call to source | +| map.cpp:28:9:28:14 | second | map.cpp:26:13:26:18 | call to source | | movableclass.cpp:44:8:44:9 | s1 | movableclass.cpp:39:21:39:26 | call to source | | movableclass.cpp:45:8:45:9 | s2 | movableclass.cpp:40:23:40:28 | call to source | | movableclass.cpp:46:8:46:9 | s3 | movableclass.cpp:42:8:42:13 | 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 07aa8b78d1d..ce708a75747 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 @@ -42,6 +42,8 @@ | format.cpp:115:8:115:13 | Argument 0 indirection | format.cpp:114:37:114:50 | call to source | | format.cpp:157:7:157:22 | access to array | format.cpp:147:12:147:25 | call to source | | format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source | +| map.cpp:22:9:22:13 | first | map.cpp:21:12:21:17 | call to source | +| map.cpp:28:9:28:14 | second | map.cpp:26:13:26:18 | call to source | | movableclass.cpp:44:8:44:9 | s1 | movableclass.cpp:39:21:39:26 | call to source | | movableclass.cpp:45:8:45:9 | s2 | movableclass.cpp:40:23:40:28 | call to source | | movableclass.cpp:46:8:46:9 | s3 | movableclass.cpp:42:8:42:13 | call to source | From 774dcc7c5292696d69e3b5a1726b7aa164028450 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 23 Sep 2020 15:29:37 -0700 Subject: [PATCH 039/411] C++: New model class for iterator op* and op[] --- .../dataflow/internal/TaintTrackingUtil.qll | 10 ++-------- .../cpp/models/implementations/Iterator.qll | 14 +++++++++++--- .../code/cpp/models/interfaces/Iterator.qll | 19 +++++++++++++++++++ 3 files changed, 32 insertions(+), 11 deletions(-) create mode 100644 cpp/ql/src/semmle/code/cpp/models/interfaces/Iterator.qll 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 17cb9b88104..1ef340c4f21 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll @@ -10,7 +10,7 @@ private import semmle.code.cpp.models.interfaces.DataFlow private import semmle.code.cpp.models.interfaces.Taint -private import semmle.code.cpp.models.implementations.Iterator +private import semmle.code.cpp.models.interfaces.Iterator private module DataFlow { import semmle.code.cpp.dataflow.internal.DataFlowUtil @@ -264,10 +264,4 @@ private predicate exprToPartialDefinitionStep(Expr exprIn, Expr exprOut) { ) } -private predicate iteratorDereference(Call c) { - c.getTarget() instanceof IteratorArrayMemberOperator - or - c.getTarget() instanceof IteratorPointerDereferenceMemberOperator - or - c.getTarget() instanceof IteratorPointerDereferenceOperator -} +private predicate iteratorDereference(Call c) { c.getTarget() instanceof IteratorReferenceFunction } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll index 93a04d5ef90..c1b8e24e7db 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll @@ -8,6 +8,7 @@ import cpp import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.DataFlow +import semmle.code.cpp.models.interfaces.Iterator /** * An instantiation of the `std::iterator_traits` template. @@ -80,7 +81,7 @@ private FunctionInput getIteratorArgumentInput(Operator op, int index) { /** * A non-member prefix `operator*` function for an iterator type. */ -class IteratorPointerDereferenceOperator extends Operator, TaintFunction { +class IteratorPointerDereferenceOperator extends Operator, TaintFunction, IteratorReferenceFunction { FunctionInput iteratorInput; IteratorPointerDereferenceOperator() { @@ -92,6 +93,8 @@ class IteratorPointerDereferenceOperator extends Operator, TaintFunction { input = iteratorInput and output.isReturnValue() } + + override FunctionInput getIteratorInput() { result = iteratorInput } } /** @@ -169,12 +172,15 @@ class IteratorAssignArithmeticOperator extends Operator, DataFlowFunction, Taint /** * A prefix `operator*` member function for an iterator type. */ -class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunction { +class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunction, + IteratorReferenceFunction { IteratorPointerDereferenceMemberOperator() { this.hasName("operator*") and this.getDeclaringType() instanceof Iterator } + override FunctionInput getIteratorInput() { result.isQualifierObject() } + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isQualifierObject() and output.isReturnValue() @@ -260,7 +266,7 @@ class IteratorAssignArithmeticMemberOperator extends MemberFunction, DataFlowFun /** * An `operator[]` member function of an iterator class. */ -class IteratorArrayMemberOperator extends MemberFunction, TaintFunction { +class IteratorArrayMemberOperator extends MemberFunction, TaintFunction, IteratorReferenceFunction { IteratorArrayMemberOperator() { this.hasName("operator[]") and this.getDeclaringType() instanceof Iterator @@ -270,6 +276,8 @@ class IteratorArrayMemberOperator extends MemberFunction, TaintFunction { input.isQualifierObject() and output.isReturnValue() } + + override FunctionInput getIteratorInput() { result.isQualifierObject() } } /** diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/Iterator.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/Iterator.qll new file mode 100644 index 00000000000..ea9ce04e530 --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/Iterator.qll @@ -0,0 +1,19 @@ +/** + * Provides an abstract class for accurate modeling of flow through output + * iterators. To use this QL library, create a QL class extending + * `IteratorReferenceFunction` with a characteristic predicate that selects the + * function or set of functions you are modeling. Within that class, override + * the predicates provided by `AliasFunction` to match the flow within that + * function. + */ + +import cpp +import semmle.code.cpp.models.Models + +/** + * A function which takes an iterator argument and returns a reference that + * can be used to write to the iterator's underlying collection. + */ +abstract class IteratorReferenceFunction extends Function { + abstract FunctionInput getIteratorInput(); +} From 89332ca3037ac3b8c0c664cfe0ad90f9e44a421c Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 23 Sep 2020 15:29:51 -0700 Subject: [PATCH 040/411] C++: autoformat --- cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll | 1 - 1 file changed, 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index e737f8b2d94..4562eb3fd19 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -3,7 +3,6 @@ private import DataFlowUtil private import DataFlowDispatch private import FlowVar - /** Gets the instance argument of a non-static call. */ private Node getInstanceArgument(Call call) { result.asExpr() = call.getQualifier() From 45651cf1236a6aa2c4aeb723c7b49a664d63baa4 Mon Sep 17 00:00:00 2001 From: Joe Date: Wed, 23 Sep 2020 16:58:35 +0100 Subject: [PATCH 041/411] Java: PrintAst: Add a synthetic node for the initialisers of for statements --- java/ql/src/semmle/code/java/PrintAst.qll | 31 ++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/PrintAst.qll b/java/ql/src/semmle/code/java/PrintAst.qll index a3f4807661d..b26db2704ee 100644 --- a/java/ql/src/semmle/code/java/PrintAst.qll +++ b/java/ql/src/semmle/code/java/PrintAst.qll @@ -113,6 +113,7 @@ private predicate locationSortKeys(Element ast, string file, int line, int colum */ private newtype TPrintAstNode = TElementNode(Element el) { shouldPrint(el, _) } or + TForInitNode(ForStmt fs) { shouldPrint(fs, _) and exists(fs.getAnInit()) } or TAnnotationsNode(Annotatable ann) { shouldPrint(ann, _) and ann.hasAnnotation() and not partOfAnnotation(ann) } or @@ -248,7 +249,11 @@ final class ExprStmtNode extends ElementNode { override PrintAstNode getChild(int childIndex) { exists(Element el | result.(ElementNode).getElement() = el | el.(Expr).isNthChildOf(element, childIndex) and - not partOfAnnotation(element) + not partOfAnnotation(element) and + not ( + element instanceof ForStmt and + childIndex <= 0 + ) or el.(Stmt).isNthChildOf(element, childIndex) or @@ -271,6 +276,9 @@ final class ExprStmtNode extends ElementNode { childIndex = -2 and el = element.(LocalVariableDeclExpr).getVariable() ) + or + childIndex = 0 and + result.(ForInitNode).getForStmt() = element } } @@ -432,6 +440,27 @@ final class TypeVariableNode extends ElementNode { } } +/** + * A node representing the initializers of a `ForStmt`. + */ +final class ForInitNode extends PrintAstNode, TForInitNode { + ForStmt fs; + + ForInitNode() { this = TForInitNode(fs) } + + override string toString() { result = "(For Initializers) "} + + override ElementNode getChild(int childIndex) { + childIndex >= 0 and + result.getElement().(Expr).isNthChildOf(fs, -childIndex) + } + + /** + * Gets the underlying `ForStmt`. + */ + ForStmt getForStmt() {result = fs} +} + /** * A node representing the annotations of an `Annotatable`. * Only rendered if there is at least one annotation. From 1f9960762425b676b64a9a150ded4015a6ff9606 Mon Sep 17 00:00:00 2001 From: Joe Date: Wed, 23 Sep 2020 17:11:20 +0100 Subject: [PATCH 042/411] Java: PrintAst: Improve test --- java/ql/test/library-tests/printAst/A.java | 6 ++ .../library-tests/printAst/PrintAst.expected | 77 +++++++++++++------ 2 files changed, 61 insertions(+), 22 deletions(-) diff --git a/java/ql/test/library-tests/printAst/A.java b/java/ql/test/library-tests/printAst/A.java index b0eeb9276a1..c3176cc14f3 100644 --- a/java/ql/test/library-tests/printAst/A.java +++ b/java/ql/test/library-tests/printAst/A.java @@ -18,6 +18,12 @@ class A { /** Does something */ @Deprecated static int doSomething(@SuppressWarnings("all") String text) { + int i=0, j=1; + + for(i=0, j=1; i<3; i++) {} + + for(int m=0, n=1; m<3; m++) {} + return 0; } diff --git a/java/ql/test/library-tests/printAst/PrintAst.expected b/java/ql/test/library-tests/printAst/PrintAst.expected index b23ed34ea82..c8f22de6950 100644 --- a/java/ql/test/library-tests/printAst/PrintAst.expected +++ b/java/ql/test/library-tests/printAst/PrintAst.expected @@ -31,26 +31,59 @@ A.java: # 20| 1: [StringLiteral] "all" # 20| 0: [TypeAccess] String # 20| 5: [BlockStmt] stmt -# 21| 0: [ReturnStmt] stmt -# 21| 0: [IntegerLiteral] 0 -# 24| 6: [FieldDeclaration] int counter, ...; -# 24| -1: [TypeAccess] int -# 24| 0: [IntegerLiteral] 1 -# 26| 7: [BlockStmt] stmt -# 27| 0: [ExprStmt] stmt -# 27| 0: [AssignExpr] ...=... -# 27| 0: [VarAccess] counter -# 27| 1: [MethodAccess] doSomething(...) -# 27| 0: [StringLiteral] "hi" -# 36| 8: [Method] doSomethingElse +# 21| 0: [LocalVariableDeclStmt] stmt +# 21| 0: [TypeAccess] int +# 21| 1: [LocalVariableDeclExpr] i +# 21| 0: [IntegerLiteral] 0 +# 21| 2: [LocalVariableDeclExpr] j +# 21| 0: [IntegerLiteral] 1 +# 23| 1: [ForStmt] stmt +#-----| 0: (For Initializers) +# 23| 1: [AssignExpr] ...=... +# 23| 0: [VarAccess] i +# 23| 1: [IntegerLiteral] 0 +# 23| 2: [AssignExpr] ...=... +# 23| 0: [VarAccess] j +# 23| 1: [IntegerLiteral] 1 +# 23| 1: [LTExpr] ... < ... +# 23| 0: [VarAccess] i +# 23| 1: [IntegerLiteral] 3 +# 23| 2: [BlockStmt] stmt +# 23| 3: [PostIncExpr] ...++ +# 23| 0: [VarAccess] i +# 25| 2: [ForStmt] stmt +#-----| 0: (For Initializers) +# 25| 0: [TypeAccess] int +# 25| 1: [LocalVariableDeclExpr] m +# 25| 0: [IntegerLiteral] 0 +# 25| 2: [LocalVariableDeclExpr] n +# 25| 0: [IntegerLiteral] 1 +# 25| 1: [LTExpr] ... < ... +# 25| 0: [VarAccess] m +# 25| 1: [IntegerLiteral] 3 +# 25| 2: [BlockStmt] stmt +# 25| 3: [PostIncExpr] ...++ +# 25| 0: [VarAccess] m +# 27| 3: [ReturnStmt] stmt +# 27| 0: [IntegerLiteral] 0 +# 30| 6: [FieldDeclaration] int counter, ...; +# 30| -1: [TypeAccess] int +# 30| 0: [IntegerLiteral] 1 +# 32| 7: [BlockStmt] stmt +# 33| 0: [ExprStmt] stmt +# 33| 0: [AssignExpr] ...=... +# 33| 0: [VarAccess] counter +# 33| 1: [MethodAccess] doSomething(...) +# 33| 0: [StringLiteral] "hi" +# 42| 8: [Method] doSomethingElse #-----| 1: (Annotations) -# 30| 1: [Annotation] Ann1 -# 31| 1: [StringLiteral] "a" -# 32| 2: [ArrayInit] {...} -# 33| 1: [Annotation] Ann2 -# 34| 2: [Annotation] Ann2 -# 34| 1: [IntegerLiteral] 7 -# 36| 3: [TypeAccess] String -# 36| 5: [BlockStmt] stmt -# 36| 0: [ReturnStmt] stmt -# 36| 0: [StringLiteral] "c" +# 36| 1: [Annotation] Ann1 +# 37| 1: [StringLiteral] "a" +# 38| 2: [ArrayInit] {...} +# 39| 1: [Annotation] Ann2 +# 40| 2: [Annotation] Ann2 +# 40| 1: [IntegerLiteral] 7 +# 42| 3: [TypeAccess] String +# 42| 5: [BlockStmt] stmt +# 42| 0: [ReturnStmt] stmt +# 42| 0: [StringLiteral] "c" From 3e960c1e0bdac2062fbe047152acc9d73f75f30c Mon Sep 17 00:00:00 2001 From: Joe Date: Wed, 23 Sep 2020 17:53:30 +0100 Subject: [PATCH 043/411] Java: PrintAst: Refactor exceptions to the usual AST of expressions and statements using dispatch --- java/ql/src/semmle/code/java/PrintAst.qll | 132 +++++++++++++++------- 1 file changed, 90 insertions(+), 42 deletions(-) diff --git a/java/ql/src/semmle/code/java/PrintAst.qll b/java/ql/src/semmle/code/java/PrintAst.qll index b26db2704ee..08b108c8e47 100644 --- a/java/ql/src/semmle/code/java/PrintAst.qll +++ b/java/ql/src/semmle/code/java/PrintAst.qll @@ -222,6 +222,24 @@ abstract class ElementNode extends PrintAstNode, TElementNode { final Element getElement() { result = element } } +/** + * A node representing an `Expr` or a `Stmt`. + */ +class ExprStmtNode extends ElementNode { + ExprStmtNode() { element instanceof ExprOrStmt } + + override PrintAstNode getChild(int childIndex) { + exists(Element el | result.(ElementNode).getElement() = el | + el.(Expr).isNthChildOf(element, childIndex) + or + el.(Stmt).isNthChildOf(element, childIndex) + ) + } +} + +/** + * Holds if the given expression is part of an annotation. + */ private predicate partOfAnnotation(Expr e) { e instanceof Annotation or @@ -229,53 +247,83 @@ private predicate partOfAnnotation(Expr e) { partOfAnnotation(e.getParent()) } -private Expr getAnAnnotationChild(Expr e) { - partOfAnnotation(e) and - ( - result = e.(Annotation).getValue(_) - or - result = e.(ArrayInit).getAnInit() - or - result = e.(ArrayInit).(Annotatable).getAnAnnotation() - ) +/** + * A node representing an `Expr` that is part of an annotation. + */ +final class AnnotationPartNode extends ExprStmtNode { + AnnotationPartNode() { partOfAnnotation(element) } + + override ElementNode getChild(int childIndex) { + result.getElement() = + rank[childIndex](Element ch, string file, int line, int column | + ch = getAnAnnotationChild() and locationSortKeys(ch, file, line, column) + | + ch order by file, line, column + ) + } + + private Expr getAnAnnotationChild() { + ( + result = element.(Annotation).getValue(_) + or + result = element.(ArrayInit).getAnInit() + or + result = element.(ArrayInit).(Annotatable).getAnAnnotation() + ) + } } /** - * An node representing an `Expr` or a `Stmt`. + * A node representing a `LocalVariableDeclExpr`. */ -final class ExprStmtNode extends ElementNode { - ExprStmtNode() { element instanceof ExprOrStmt } +final class LocalVarDeclExprNode extends ExprStmtNode { + LocalVarDeclExprNode() { element instanceof LocalVariableDeclExpr } override PrintAstNode getChild(int childIndex) { - exists(Element el | result.(ElementNode).getElement() = el | - el.(Expr).isNthChildOf(element, childIndex) and - not partOfAnnotation(element) and - not ( - element instanceof ForStmt and - childIndex <= 0 - ) - or - el.(Stmt).isNthChildOf(element, childIndex) - or - childIndex = -4 and - el = element.(ClassInstanceExpr).getAnonymousClass() - or - childIndex = 0 and - el = element.(LocalClassDeclStmt).getLocalClass() - or - partOfAnnotation(element) and - el = - rank[childIndex](Element ch, string file, int line, int column | - ch = getAnAnnotationChild(element) and locationSortKeys(ch, file, line, column) - | - ch order by file, line, column - ) - ) + result = super.getChild(childIndex) or - exists(Element el | result.(AnnotationsNode).getAnnotated() = el | - childIndex = -2 and - el = element.(LocalVariableDeclExpr).getVariable() - ) + childIndex = -2 and + result.(AnnotationsNode).getAnnotated() = element.(LocalVariableDeclExpr).getVariable() + } +} + +/** + * A node representing a `ClassInstanceExpr`. + */ +final class ClassInstanceExprNode extends ExprStmtNode { + ClassInstanceExprNode() { element instanceof ClassInstanceExpr } + + override ElementNode getChild(int childIndex) { + result = super.getChild(childIndex) + or + childIndex = -4 and + result.getElement() = element.(ClassInstanceExpr).getAnonymousClass() + } +} + +/** + * A node representing a `LocalClassDeclStmt`. + */ +final class LocalClassDeclStmtNode extends ExprStmtNode { + LocalClassDeclStmtNode() { element instanceof LocalClassDeclStmt } + + override ElementNode getChild(int childIndex) { + result = super.getChild(childIndex) + or + childIndex = 0 and + result.getElement() = element.(LocalClassDeclStmt).getLocalClass() + } +} + +/** + * A node representing a `ForStmt`. + */ +final class ForStmtNode extends ExprStmtNode { + ForStmtNode() { element instanceof ForStmt } + + override PrintAstNode getChild(int childIndex) { + childIndex >= 1 and + result = super.getChild(childIndex) or childIndex = 0 and result.(ForInitNode).getForStmt() = element @@ -448,7 +496,7 @@ final class ForInitNode extends PrintAstNode, TForInitNode { ForInitNode() { this = TForInitNode(fs) } - override string toString() { result = "(For Initializers) "} + override string toString() { result = "(For Initializers) " } override ElementNode getChild(int childIndex) { childIndex >= 0 and @@ -458,7 +506,7 @@ final class ForInitNode extends PrintAstNode, TForInitNode { /** * Gets the underlying `ForStmt`. */ - ForStmt getForStmt() {result = fs} + ForStmt getForStmt() { result = fs } } /** From 9c8a4682377ea2a65985552531754e27ebfda030 Mon Sep 17 00:00:00 2001 From: Joe Date: Thu, 24 Sep 2020 12:12:28 +0100 Subject: [PATCH 044/411] Java: PrintAst: Add synthetic nodes for other declarations --- java/ql/src/semmle/code/java/PrintAst.qll | 67 +++++++++++++++++++ .../java7/MultiCatch/PrintAst.expected | 23 ++++--- 2 files changed, 80 insertions(+), 10 deletions(-) diff --git a/java/ql/src/semmle/code/java/PrintAst.qll b/java/ql/src/semmle/code/java/PrintAst.qll index 08b108c8e47..ca1daf6c2a4 100644 --- a/java/ql/src/semmle/code/java/PrintAst.qll +++ b/java/ql/src/semmle/code/java/PrintAst.qll @@ -114,6 +114,9 @@ private predicate locationSortKeys(Element ast, string file, int line, int colum private newtype TPrintAstNode = TElementNode(Element el) { shouldPrint(el, _) } or TForInitNode(ForStmt fs) { shouldPrint(fs, _) and exists(fs.getAnInit()) } or + TLocalVarDeclNode(LocalVariableDeclExpr lvde) { + shouldPrint(lvde, _) and lvde.getParent() instanceof LocalVarDeclParent + } or TAnnotationsNode(Annotatable ann) { shouldPrint(ann, _) and ann.hasAnnotation() and not partOfAnnotation(ann) } or @@ -330,6 +333,46 @@ final class ForStmtNode extends ExprStmtNode { } } +/** + * An element that can be the parent of a `LocalVariableDeclExpr` for which we want + * to use a synthetic node to hold the variable declaration and its `TypeAccess`. + */ +private class LocalVarDeclParent extends ExprOrStmt { + LocalVarDeclParent() { + this instanceof EnhancedForStmt or + this instanceof CatchClause or + this.(InstanceOfExpr).isPattern() + } + + /** Gets the variable declaration that this element contains */ + LocalVariableDeclExpr getVariable() { result.getParent() = this } + + /** Gets the type access of the variable */ + Expr getTypeAccess() { result = getVariable().getTypeAccess() } +} + +/** + * A node representing an element that can be the parent of a `LocalVariableDeclExpr` for which we + * want to use a synthetic node to variable declaration and its type access. + * + * Excludes: + * - `LocalVariableDeclStmt` because a synthetic node isn't needed + * - `ForStmt` becasue a different synthetic node is already used + */ +final class LocalVarDeclParentNode extends ExprStmtNode { + LocalVarDeclParent lvdp; + + LocalVarDeclParentNode() { lvdp = element } + + override PrintAstNode getChild(int childIndex) { + result = super.getChild(childIndex) and + not result.(ElementNode).getElement() = [lvdp.getVariable(), lvdp.getTypeAccess()] + or + childIndex = lvdp.getVariable().getIndex() and + result.(LocalVarDeclSynthNode).getVariable() = lvdp.getVariable() + } +} + /** * A node representing a `Callable`, such as method declaration. */ @@ -509,6 +552,30 @@ final class ForInitNode extends PrintAstNode, TForInitNode { ForStmt getForStmt() { result = fs } } +/** + * A synthetic node holding a `LocalVariableDeclExpr` and its type access. + */ +final class LocalVarDeclSynthNode extends PrintAstNode, TLocalVarDeclNode { + LocalVariableDeclExpr lvde; + + LocalVarDeclSynthNode() { this = TLocalVarDeclNode(lvde) } + + override string toString() { result = "(Local Variable Declaration)" } + + override ElementNode getChild(int childIndex) { + childIndex = 0 and + result.getElement() = lvde.getTypeAccess() + or + childIndex = 1 and + result.getElement() = lvde + } + + /** + * Gets the underlying `LocalVariableDeclExpr` + */ + LocalVariableDeclExpr getVariable() { result = lvde } +} + /** * A node representing the annotations of an `Annotatable`. * Only rendered if there is at least one annotation. diff --git a/java/ql/test/library-tests/java7/MultiCatch/PrintAst.expected b/java/ql/test/library-tests/java7/MultiCatch/PrintAst.expected index 8b8fe959628..98172ceff75 100644 --- a/java/ql/test/library-tests/java7/MultiCatch/PrintAst.expected +++ b/java/ql/test/library-tests/java7/MultiCatch/PrintAst.expected @@ -21,10 +21,11 @@ MultiCatch.java: # 14| 0: [ClassInstanceExpr] new SQLException(...) # 14| -3: [TypeAccess] SQLException # 15| 0: [CatchClause] stmt -# 15| -1: [UnionTypeAccess] ...|... -# 15| 0: [TypeAccess] IOException -# 15| 1: [TypeAccess] SQLException -# 15| 0: [LocalVariableDeclExpr] e +#-----| 0: (Local Variable Declaration) +# 15| 0: [UnionTypeAccess] ...|... +# 15| 0: [TypeAccess] IOException +# 15| 1: [TypeAccess] SQLException +# 15| 1: [LocalVariableDeclExpr] e # 16| 1: [BlockStmt] stmt # 17| 0: [ExprStmt] stmt # 17| 0: [MethodAccess] printStackTrace(...) @@ -55,10 +56,11 @@ MultiCatch.java: # 30| 0: [ClassInstanceExpr] new Exception(...) # 30| -3: [TypeAccess] Exception # 31| 0: [CatchClause] stmt -# 31| -1: [UnionTypeAccess] ...|... -# 31| 0: [TypeAccess] IOException -# 31| 1: [TypeAccess] SQLException -# 31| 0: [LocalVariableDeclExpr] e +#-----| 0: (Local Variable Declaration) +# 31| 0: [UnionTypeAccess] ...|... +# 31| 0: [TypeAccess] IOException +# 31| 1: [TypeAccess] SQLException +# 31| 1: [LocalVariableDeclExpr] e # 32| 1: [BlockStmt] stmt # 35| 4: [Method] ordinaryCatch # 35| 3: [TypeAccess] void @@ -69,6 +71,7 @@ MultiCatch.java: # 39| 0: [ClassInstanceExpr] new IOException(...) # 39| -3: [TypeAccess] IOException # 40| 0: [CatchClause] stmt -# 40| -1: [TypeAccess] Exception -# 40| 0: [LocalVariableDeclExpr] e +#-----| 0: (Local Variable Declaration) +# 40| 0: [TypeAccess] Exception +# 40| 1: [LocalVariableDeclExpr] e # 41| 1: [BlockStmt] stmt From 49f9a76c547bbfe86c2f84a03375c81d58c4fb9c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 22 Sep 2020 13:21:17 +0100 Subject: [PATCH 045/411] C++: Add tests for std::map and std::unordered_map. --- .../dataflow/taint-tests/localTaint.expected | 1369 +++++++++++++++-- .../dataflow/taint-tests/map.cpp | 311 +++- .../library-tests/dataflow/taint-tests/stl.h | 135 ++ .../dataflow/taint-tests/taint.expected | 8 +- .../dataflow/taint-tests/test_ir.expected | 8 +- 5 files changed, 1671 insertions(+), 160 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 b571ac46520..18e8a873303 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -391,144 +391,1207 @@ | format.cpp:158:13:158:18 | call to wcslen | format.cpp:158:13:158:26 | ... / ... | TAINT | | format.cpp:158:13:158:26 | ... / ... | format.cpp:158:7:158:27 | ... + ... | TAINT | | format.cpp:158:26:158:26 | 2 | format.cpp:158:13:158:26 | ... / ... | TAINT | -| map.cpp:14:28:14:28 | call to pair | map.cpp:16:2:16:2 | a | | -| map.cpp:14:28:14:28 | call to pair | map.cpp:17:7:17:7 | a | | -| map.cpp:14:28:14:28 | call to pair | map.cpp:18:7:18:7 | a | | -| map.cpp:14:28:14:28 | call to pair | map.cpp:19:7:19:7 | a | | -| map.cpp:14:31:14:31 | call to pair | map.cpp:21:2:21:2 | b | | -| map.cpp:14:31:14:31 | call to pair | map.cpp:22:7:22:7 | b | | -| map.cpp:14:31:14:31 | call to pair | map.cpp:23:7:23:7 | b | | -| map.cpp:14:31:14:31 | call to pair | map.cpp:24:7:24:7 | b | | -| map.cpp:14:34:14:34 | call to pair | map.cpp:26:2:26:2 | c | | -| map.cpp:14:34:14:34 | call to pair | map.cpp:27:7:27:7 | c | | -| map.cpp:14:34:14:34 | call to pair | map.cpp:28:7:28:7 | c | | -| map.cpp:14:34:14:34 | call to pair | map.cpp:29:7:29:7 | c | | -| map.cpp:16:2:16:2 | a [post update] | map.cpp:17:7:17:7 | a | | -| map.cpp:16:2:16:2 | a [post update] | map.cpp:18:7:18:7 | a | | -| map.cpp:16:2:16:2 | a [post update] | map.cpp:19:7:19:7 | a | | -| map.cpp:16:2:16:16 | ... = ... | map.cpp:16:4:16:8 | first [post update] | | -| map.cpp:16:2:16:16 | ... = ... | map.cpp:17:9:17:13 | first | | -| map.cpp:16:12:16:16 | 123 | map.cpp:16:2:16:16 | ... = ... | | -| map.cpp:17:7:17:7 | a [post update] | map.cpp:18:7:18:7 | a | | -| map.cpp:17:7:17:7 | a [post update] | map.cpp:19:7:19:7 | a | | -| map.cpp:18:7:18:7 | a [post update] | map.cpp:19:7:19:7 | a | | -| map.cpp:21:2:21:2 | b [post update] | map.cpp:22:7:22:7 | b | | -| map.cpp:21:2:21:2 | b [post update] | map.cpp:23:7:23:7 | b | | -| map.cpp:21:2:21:2 | b [post update] | map.cpp:24:7:24:7 | b | | -| map.cpp:21:2:21:19 | ... = ... | map.cpp:21:4:21:8 | first [post update] | | -| map.cpp:21:2:21:19 | ... = ... | map.cpp:22:9:22:13 | first | | -| map.cpp:21:12:21:17 | call to source | map.cpp:21:2:21:19 | ... = ... | | -| map.cpp:22:7:22:7 | b [post update] | map.cpp:23:7:23:7 | b | | -| map.cpp:22:7:22:7 | b [post update] | map.cpp:24:7:24:7 | b | | -| map.cpp:23:7:23:7 | b [post update] | map.cpp:24:7:24:7 | b | | -| map.cpp:26:2:26:2 | c [post update] | map.cpp:27:7:27:7 | c | | -| map.cpp:26:2:26:2 | c [post update] | map.cpp:28:7:28:7 | c | | -| map.cpp:26:2:26:2 | c [post update] | map.cpp:29:7:29:7 | c | | -| map.cpp:26:2:26:20 | ... = ... | map.cpp:26:4:26:9 | second [post update] | | -| map.cpp:26:2:26:20 | ... = ... | map.cpp:28:9:28:14 | second | | -| map.cpp:26:13:26:18 | call to source | map.cpp:26:2:26:20 | ... = ... | | -| map.cpp:27:7:27:7 | c [post update] | map.cpp:28:7:28:7 | c | | -| map.cpp:27:7:27:7 | c [post update] | map.cpp:29:7:29:7 | c | | -| map.cpp:28:7:28:7 | c [post update] | map.cpp:29:7:29:7 | c | | -| map.cpp:31:30:31:42 | call to pair | map.cpp:32:7:32:7 | d | | -| map.cpp:31:30:31:42 | call to pair | map.cpp:33:7:33:7 | d | | -| map.cpp:31:30:31:42 | call to pair | map.cpp:34:7:34:7 | d | | -| map.cpp:32:7:32:7 | d [post update] | map.cpp:33:7:33:7 | d | | -| map.cpp:32:7:32:7 | d [post update] | map.cpp:34:7:34:7 | d | | -| map.cpp:33:7:33:7 | d [post update] | map.cpp:34:7:34:7 | d | | -| map.cpp:36:30:36:45 | call to pair | map.cpp:37:7:37:7 | e | | -| map.cpp:36:30:36:45 | call to pair | map.cpp:38:7:38:7 | e | | -| map.cpp:36:30:36:45 | call to pair | map.cpp:39:7:39:7 | e | | -| map.cpp:37:7:37:7 | e [post update] | map.cpp:38:7:38:7 | e | | -| map.cpp:37:7:37:7 | e [post update] | map.cpp:39:7:39:7 | e | | -| map.cpp:38:7:38:7 | e [post update] | map.cpp:39:7:39:7 | e | | -| map.cpp:41:30:41:45 | call to pair | map.cpp:42:7:42:7 | f | | -| map.cpp:41:30:41:45 | call to pair | map.cpp:43:7:43:7 | f | | -| map.cpp:41:30:41:45 | call to pair | map.cpp:44:7:44:7 | f | | -| map.cpp:41:30:41:45 | call to pair | map.cpp:46:30:46:30 | f | | -| map.cpp:41:30:41:45 | call to pair | map.cpp:47:7:47:7 | f | | -| map.cpp:41:30:41:45 | call to pair | map.cpp:48:7:48:7 | f | | -| map.cpp:41:30:41:45 | call to pair | map.cpp:49:7:49:7 | f | | -| map.cpp:41:30:41:45 | call to pair | map.cpp:52:6:52:6 | f | | -| map.cpp:42:7:42:7 | f [post update] | map.cpp:43:7:43:7 | f | | -| map.cpp:42:7:42:7 | f [post update] | map.cpp:44:7:44:7 | f | | -| map.cpp:42:7:42:7 | f [post update] | map.cpp:46:30:46:30 | f | | -| map.cpp:42:7:42:7 | f [post update] | map.cpp:47:7:47:7 | f | | -| map.cpp:42:7:42:7 | f [post update] | map.cpp:48:7:48:7 | f | | -| map.cpp:42:7:42:7 | f [post update] | map.cpp:49:7:49:7 | f | | -| map.cpp:42:7:42:7 | f [post update] | map.cpp:52:6:52:6 | f | | -| map.cpp:43:7:43:7 | f [post update] | map.cpp:44:7:44:7 | f | | -| map.cpp:43:7:43:7 | f [post update] | map.cpp:46:30:46:30 | f | | -| map.cpp:43:7:43:7 | f [post update] | map.cpp:47:7:47:7 | f | | -| map.cpp:43:7:43:7 | f [post update] | map.cpp:48:7:48:7 | f | | -| map.cpp:43:7:43:7 | f [post update] | map.cpp:49:7:49:7 | f | | -| map.cpp:43:7:43:7 | f [post update] | map.cpp:52:6:52:6 | f | | +| map.cpp:18:28:18:28 | call to pair | map.cpp:20:2:20:2 | a | | +| map.cpp:18:28:18:28 | call to pair | map.cpp:21:7:21:7 | a | | +| map.cpp:18:28:18:28 | call to pair | map.cpp:22:7:22:7 | a | | +| map.cpp:18:28:18:28 | call to pair | map.cpp:23:7:23:7 | a | | +| map.cpp:18:31:18:31 | call to pair | map.cpp:25:2:25:2 | b | | +| map.cpp:18:31:18:31 | call to pair | map.cpp:26:7:26:7 | b | | +| map.cpp:18:31:18:31 | call to pair | map.cpp:27:7:27:7 | b | | +| map.cpp:18:31:18:31 | call to pair | map.cpp:28:7:28:7 | b | | +| map.cpp:18:34:18:34 | call to pair | map.cpp:30:2:30:2 | c | | +| map.cpp:18:34:18:34 | call to pair | map.cpp:31:7:31:7 | c | | +| map.cpp:18:34:18:34 | call to pair | map.cpp:32:7:32:7 | c | | +| map.cpp:18:34:18:34 | call to pair | map.cpp:33:7:33:7 | c | | +| map.cpp:20:2:20:2 | a [post update] | map.cpp:21:7:21:7 | a | | +| map.cpp:20:2:20:2 | a [post update] | map.cpp:22:7:22:7 | a | | +| map.cpp:20:2:20:2 | a [post update] | map.cpp:23:7:23:7 | a | | +| map.cpp:20:2:20:16 | ... = ... | map.cpp:20:4:20:8 | first [post update] | | +| map.cpp:20:2:20:16 | ... = ... | map.cpp:21:9:21:13 | first | | +| map.cpp:20:12:20:16 | 123 | map.cpp:20:2:20:16 | ... = ... | | +| map.cpp:21:7:21:7 | a [post update] | map.cpp:22:7:22:7 | a | | +| map.cpp:21:7:21:7 | a [post update] | map.cpp:23:7:23:7 | a | | +| map.cpp:22:7:22:7 | a [post update] | map.cpp:23:7:23:7 | a | | +| map.cpp:25:2:25:2 | b [post update] | map.cpp:26:7:26:7 | b | | +| map.cpp:25:2:25:2 | b [post update] | map.cpp:27:7:27:7 | b | | +| map.cpp:25:2:25:2 | b [post update] | map.cpp:28:7:28:7 | b | | +| map.cpp:25:2:25:19 | ... = ... | map.cpp:25:4:25:8 | first [post update] | | +| map.cpp:25:2:25:19 | ... = ... | map.cpp:26:9:26:13 | first | | +| map.cpp:25:12:25:17 | call to source | map.cpp:25:2:25:19 | ... = ... | | +| map.cpp:26:7:26:7 | b [post update] | map.cpp:27:7:27:7 | b | | +| map.cpp:26:7:26:7 | b [post update] | map.cpp:28:7:28:7 | b | | +| map.cpp:27:7:27:7 | b [post update] | map.cpp:28:7:28:7 | b | | +| map.cpp:30:2:30:2 | c [post update] | map.cpp:31:7:31:7 | c | | +| map.cpp:30:2:30:2 | c [post update] | map.cpp:32:7:32:7 | c | | +| map.cpp:30:2:30:2 | c [post update] | map.cpp:33:7:33:7 | c | | +| map.cpp:30:2:30:20 | ... = ... | map.cpp:30:4:30:9 | second [post update] | | +| map.cpp:30:2:30:20 | ... = ... | map.cpp:32:9:32:14 | second | | +| map.cpp:30:13:30:18 | call to source | map.cpp:30:2:30:20 | ... = ... | | +| map.cpp:31:7:31:7 | c [post update] | map.cpp:32:7:32:7 | c | | +| map.cpp:31:7:31:7 | c [post update] | map.cpp:33:7:33:7 | c | | +| map.cpp:32:7:32:7 | c [post update] | map.cpp:33:7:33:7 | c | | +| map.cpp:35:30:35:42 | call to pair | map.cpp:36:7:36:7 | d | | +| map.cpp:35:30:35:42 | call to pair | map.cpp:37:7:37:7 | d | | +| map.cpp:35:30:35:42 | call to pair | map.cpp:38:7:38:7 | d | | +| map.cpp:36:7:36:7 | d [post update] | map.cpp:37:7:37:7 | d | | +| map.cpp:36:7:36:7 | d [post update] | map.cpp:38:7:38:7 | d | | +| map.cpp:37:7:37:7 | d [post update] | map.cpp:38:7:38:7 | d | | +| map.cpp:40:30:40:45 | call to pair | map.cpp:41:7:41:7 | e | | +| map.cpp:40:30:40:45 | call to pair | map.cpp:42:7:42:7 | e | | +| map.cpp:40:30:40:45 | call to pair | map.cpp:43:7:43:7 | e | | +| map.cpp:41:7:41:7 | e [post update] | map.cpp:42:7:42:7 | e | | +| map.cpp:41:7:41:7 | e [post update] | map.cpp:43:7:43:7 | e | | +| map.cpp:42:7:42:7 | e [post update] | map.cpp:43:7:43:7 | e | | +| map.cpp:45:30:45:45 | call to pair | map.cpp:46:7:46:7 | f | | +| map.cpp:45:30:45:45 | call to pair | map.cpp:47:7:47:7 | f | | +| map.cpp:45:30:45:45 | call to pair | map.cpp:48:7:48:7 | f | | +| map.cpp:45:30:45:45 | call to pair | map.cpp:50:30:50:30 | f | | +| map.cpp:45:30:45:45 | call to pair | map.cpp:56:6:56:6 | f | | +| map.cpp:46:7:46:7 | f [post update] | map.cpp:47:7:47:7 | f | | +| map.cpp:46:7:46:7 | f [post update] | map.cpp:48:7:48:7 | f | | +| map.cpp:46:7:46:7 | f [post update] | map.cpp:50:30:50:30 | f | | +| map.cpp:46:7:46:7 | f [post update] | map.cpp:56:6:56:6 | f | | | map.cpp:47:7:47:7 | f [post update] | map.cpp:48:7:48:7 | f | | -| map.cpp:47:7:47:7 | f [post update] | map.cpp:49:7:49:7 | f | | -| map.cpp:47:7:47:7 | f [post update] | map.cpp:52:6:52:6 | f | | -| map.cpp:48:7:48:7 | f [post update] | map.cpp:49:7:49:7 | f | | -| map.cpp:48:7:48:7 | f [post update] | map.cpp:52:6:52:6 | f | | -| map.cpp:52:6:52:6 | f | map.cpp:52:2:52:6 | ... = ... | | -| map.cpp:52:6:52:6 | f | map.cpp:53:7:53:7 | h | | -| map.cpp:52:6:52:6 | f | map.cpp:54:7:54:7 | h | | -| map.cpp:52:6:52:6 | f | map.cpp:55:7:55:7 | h | | -| map.cpp:53:7:53:7 | h [post update] | map.cpp:54:7:54:7 | h | | -| map.cpp:53:7:53:7 | h [post update] | map.cpp:55:7:55:7 | h | | -| map.cpp:54:7:54:7 | h [post update] | map.cpp:55:7:55:7 | h | | -| map.cpp:57:30:57:42 | call to pair | map.cpp:61:3:61:3 | i | | -| map.cpp:57:30:57:42 | call to pair | map.cpp:63:7:63:7 | i | | -| map.cpp:57:30:57:42 | call to pair | map.cpp:64:7:64:7 | i | | -| map.cpp:57:30:57:42 | call to pair | map.cpp:65:7:65:7 | i | | -| map.cpp:58:30:58:45 | call to pair | map.cpp:61:10:61:10 | j | | -| map.cpp:58:30:58:45 | call to pair | map.cpp:66:7:66:7 | j | | -| map.cpp:58:30:58:45 | call to pair | map.cpp:67:7:67:7 | j | | -| map.cpp:58:30:58:45 | call to pair | map.cpp:68:7:68:7 | j | | -| map.cpp:59:30:59:45 | call to pair | map.cpp:62:2:62:2 | k | | -| map.cpp:59:30:59:45 | call to pair | map.cpp:69:7:69:7 | k | | -| map.cpp:59:30:59:45 | call to pair | map.cpp:70:7:70:7 | k | | -| map.cpp:59:30:59:45 | call to pair | map.cpp:71:7:71:7 | k | | -| map.cpp:60:30:60:42 | call to pair | map.cpp:62:9:62:9 | l | | -| map.cpp:60:30:60:42 | call to pair | map.cpp:72:7:72:7 | l | | -| map.cpp:60:30:60:42 | call to pair | map.cpp:73:7:73:7 | l | | -| map.cpp:60:30:60:42 | call to pair | map.cpp:74:7:74:7 | l | | -| map.cpp:61:3:61:3 | ref arg i | map.cpp:63:7:63:7 | i | | -| map.cpp:61:3:61:3 | ref arg i | map.cpp:64:7:64:7 | i | | -| map.cpp:61:3:61:3 | ref arg i | map.cpp:65:7:65:7 | i | | -| map.cpp:61:10:61:10 | ref arg j | map.cpp:66:7:66:7 | j | | -| map.cpp:61:10:61:10 | ref arg j | map.cpp:67:7:67:7 | j | | -| map.cpp:61:10:61:10 | ref arg j | map.cpp:68:7:68:7 | j | | -| map.cpp:62:2:62:2 | ref arg k | map.cpp:69:7:69:7 | k | | -| map.cpp:62:2:62:2 | ref arg k | map.cpp:70:7:70:7 | k | | -| map.cpp:62:2:62:2 | ref arg k | map.cpp:71:7:71:7 | k | | -| map.cpp:62:9:62:9 | ref arg l | map.cpp:72:7:72:7 | l | | -| map.cpp:62:9:62:9 | ref arg l | map.cpp:73:7:73:7 | l | | -| map.cpp:62:9:62:9 | ref arg l | map.cpp:74:7:74:7 | l | | -| map.cpp:63:7:63:7 | i [post update] | map.cpp:64:7:64:7 | i | | -| map.cpp:63:7:63:7 | i [post update] | map.cpp:65:7:65:7 | i | | -| map.cpp:64:7:64:7 | i [post update] | map.cpp:65:7:65:7 | i | | -| map.cpp:66:7:66:7 | j [post update] | map.cpp:67:7:67:7 | j | | -| map.cpp:66:7:66:7 | j [post update] | map.cpp:68:7:68:7 | j | | -| map.cpp:67:7:67:7 | j [post update] | map.cpp:68:7:68:7 | j | | -| map.cpp:69:7:69:7 | k [post update] | map.cpp:70:7:70:7 | k | | -| map.cpp:69:7:69:7 | k [post update] | map.cpp:71:7:71:7 | k | | -| map.cpp:70:7:70:7 | k [post update] | map.cpp:71:7:71:7 | k | | -| map.cpp:72:7:72:7 | l [post update] | map.cpp:73:7:73:7 | l | | -| map.cpp:72:7:72:7 | l [post update] | map.cpp:74:7:74:7 | l | | -| map.cpp:73:7:73:7 | l [post update] | map.cpp:74:7:74:7 | l | | -| map.cpp:76:7:76:15 | call to make_pair | map.cpp:76:7:76:29 | call to pair | TAINT | -| map.cpp:79:7:79:15 | call to make_pair | map.cpp:79:7:79:32 | call to pair | TAINT | -| map.cpp:82:7:82:15 | call to make_pair | map.cpp:82:7:82:32 | call to pair | TAINT | -| map.cpp:87:6:87:14 | call to make_pair | map.cpp:87:6:87:49 | call to pair | TAINT | -| map.cpp:87:6:87:49 | call to pair | map.cpp:87:2:87:49 | ... = ... | | -| map.cpp:87:6:87:49 | call to pair | map.cpp:88:7:88:7 | m | | -| map.cpp:87:6:87:49 | call to pair | map.cpp:89:7:89:7 | m | | -| map.cpp:87:6:87:49 | call to pair | map.cpp:90:7:90:7 | m | | -| map.cpp:87:6:87:49 | call to pair | map.cpp:91:7:91:7 | m | | -| map.cpp:87:6:87:49 | call to pair | map.cpp:92:7:92:7 | m | | -| map.cpp:88:7:88:7 | m | map.cpp:88:7:88:7 | call to pair | TAINT | -| map.cpp:90:7:90:7 | m [post update] | map.cpp:91:7:91:7 | m | | -| map.cpp:90:7:90:7 | m [post update] | map.cpp:92:7:92:7 | m | | -| map.cpp:91:7:91:7 | m [post update] | map.cpp:92:7:92:7 | m | | +| map.cpp:47:7:47:7 | f [post update] | map.cpp:50:30:50:30 | f | | +| map.cpp:47:7:47:7 | f [post update] | map.cpp:56:6:56:6 | f | | +| map.cpp:50:30:50:30 | f | map.cpp:51:7:51:7 | g | | +| map.cpp:50:30:50:30 | f | map.cpp:52:7:52:7 | g | | +| map.cpp:50:30:50:30 | f | map.cpp:53:7:53:7 | g | | +| map.cpp:51:7:51:7 | g [post update] | map.cpp:52:7:52:7 | g | | +| map.cpp:51:7:51:7 | g [post update] | map.cpp:53:7:53:7 | g | | +| map.cpp:52:7:52:7 | g [post update] | map.cpp:53:7:53:7 | g | | +| map.cpp:56:6:56:6 | f | map.cpp:56:2:56:6 | ... = ... | | +| map.cpp:56:6:56:6 | f | map.cpp:57:7:57:7 | h | | +| map.cpp:56:6:56:6 | f | map.cpp:58:7:58:7 | h | | +| map.cpp:56:6:56:6 | f | map.cpp:59:7:59:7 | h | | +| map.cpp:57:7:57:7 | h [post update] | map.cpp:58:7:58:7 | h | | +| map.cpp:57:7:57:7 | h [post update] | map.cpp:59:7:59:7 | h | | +| map.cpp:58:7:58:7 | h [post update] | map.cpp:59:7:59:7 | h | | +| map.cpp:61:30:61:42 | call to pair | map.cpp:65:3:65:3 | i | | +| map.cpp:61:30:61:42 | call to pair | map.cpp:67:7:67:7 | i | | +| map.cpp:61:30:61:42 | call to pair | map.cpp:68:7:68:7 | i | | +| map.cpp:61:30:61:42 | call to pair | map.cpp:69:7:69:7 | i | | +| map.cpp:62:30:62:45 | call to pair | map.cpp:65:10:65:10 | j | | +| map.cpp:62:30:62:45 | call to pair | map.cpp:70:7:70:7 | j | | +| map.cpp:62:30:62:45 | call to pair | map.cpp:71:7:71:7 | j | | +| map.cpp:62:30:62:45 | call to pair | map.cpp:72:7:72:7 | j | | +| map.cpp:63:30:63:45 | call to pair | map.cpp:66:2:66:2 | k | | +| map.cpp:63:30:63:45 | call to pair | map.cpp:73:7:73:7 | k | | +| map.cpp:63:30:63:45 | call to pair | map.cpp:74:7:74:7 | k | | +| map.cpp:63:30:63:45 | call to pair | map.cpp:75:7:75:7 | k | | +| map.cpp:64:30:64:42 | call to pair | map.cpp:66:9:66:9 | l | | +| map.cpp:64:30:64:42 | call to pair | map.cpp:76:7:76:7 | l | | +| map.cpp:64:30:64:42 | call to pair | map.cpp:77:7:77:7 | l | | +| map.cpp:64:30:64:42 | call to pair | map.cpp:78:7:78:7 | l | | +| map.cpp:65:3:65:3 | ref arg i | map.cpp:67:7:67:7 | i | | +| map.cpp:65:3:65:3 | ref arg i | map.cpp:68:7:68:7 | i | | +| map.cpp:65:3:65:3 | ref arg i | map.cpp:69:7:69:7 | i | | +| map.cpp:65:10:65:10 | ref arg j | map.cpp:70:7:70:7 | j | | +| map.cpp:65:10:65:10 | ref arg j | map.cpp:71:7:71:7 | j | | +| map.cpp:65:10:65:10 | ref arg j | map.cpp:72:7:72:7 | j | | +| map.cpp:66:2:66:2 | ref arg k | map.cpp:73:7:73:7 | k | | +| map.cpp:66:2:66:2 | ref arg k | map.cpp:74:7:74:7 | k | | +| map.cpp:66:2:66:2 | ref arg k | map.cpp:75:7:75:7 | k | | +| map.cpp:66:9:66:9 | ref arg l | map.cpp:76:7:76:7 | l | | +| map.cpp:66:9:66:9 | ref arg l | map.cpp:77:7:77:7 | l | | +| map.cpp:66:9:66:9 | ref arg l | map.cpp:78:7:78:7 | l | | +| map.cpp:67:7:67:7 | i [post update] | map.cpp:68:7:68:7 | i | | +| map.cpp:67:7:67:7 | i [post update] | map.cpp:69:7:69:7 | i | | +| map.cpp:68:7:68:7 | i [post update] | map.cpp:69:7:69:7 | i | | +| map.cpp:70:7:70:7 | j [post update] | map.cpp:71:7:71:7 | j | | +| map.cpp:70:7:70:7 | j [post update] | map.cpp:72:7:72:7 | j | | +| map.cpp:71:7:71:7 | j [post update] | map.cpp:72:7:72:7 | j | | +| map.cpp:73:7:73:7 | k [post update] | map.cpp:74:7:74:7 | k | | +| map.cpp:73:7:73:7 | k [post update] | map.cpp:75:7:75:7 | k | | +| map.cpp:74:7:74:7 | k [post update] | map.cpp:75:7:75:7 | k | | +| map.cpp:76:7:76:7 | l [post update] | map.cpp:77:7:77:7 | l | | +| map.cpp:76:7:76:7 | l [post update] | map.cpp:78:7:78:7 | l | | +| map.cpp:77:7:77:7 | l [post update] | map.cpp:78:7:78:7 | l | | +| map.cpp:80:7:80:15 | call to make_pair | map.cpp:80:7:80:29 | call to pair | TAINT | +| map.cpp:83:7:83:15 | call to make_pair | map.cpp:83:7:83:32 | call to pair | TAINT | +| map.cpp:86:7:86:15 | call to make_pair | map.cpp:86:7:86:32 | call to pair | TAINT | +| map.cpp:91:6:91:14 | call to make_pair | map.cpp:91:6:91:49 | call to pair | TAINT | +| map.cpp:91:6:91:49 | call to pair | map.cpp:91:2:91:49 | ... = ... | | +| map.cpp:91:6:91:49 | call to pair | map.cpp:92:7:92:7 | m | | +| map.cpp:91:6:91:49 | call to pair | map.cpp:93:7:93:7 | m | | +| map.cpp:91:6:91:49 | call to pair | map.cpp:94:7:94:7 | m | | +| map.cpp:91:6:91:49 | call to pair | map.cpp:95:7:95:7 | m | | +| map.cpp:91:6:91:49 | call to pair | map.cpp:96:7:96:7 | m | | +| map.cpp:92:7:92:7 | m | map.cpp:92:7:92:7 | call to pair | TAINT | +| map.cpp:94:7:94:7 | m [post update] | map.cpp:95:7:95:7 | m | | +| map.cpp:94:7:94:7 | m [post update] | map.cpp:96:7:96:7 | m | | +| map.cpp:95:7:95:7 | m [post update] | map.cpp:96:7:96:7 | m | | +| map.cpp:102:27:102:28 | call to map | map.cpp:104:7:104:8 | m1 | | +| map.cpp:102:27:102:28 | call to map | map.cpp:110:7:110:8 | m1 | | +| map.cpp:102:27:102:28 | call to map | map.cpp:116:7:116:8 | m1 | | +| map.cpp:102:27:102:28 | call to map | map.cpp:122:7:122:8 | m1 | | +| map.cpp:102:27:102:28 | call to map | map.cpp:143:12:143:13 | m1 | | +| map.cpp:102:27:102:28 | call to map | map.cpp:143:30:143:31 | m1 | | +| map.cpp:102:27:102:28 | call to map | map.cpp:249:1:249:1 | m1 | | +| map.cpp:102:31:102:32 | call to map | map.cpp:105:7:105:8 | m2 | | +| map.cpp:102:31:102:32 | call to map | map.cpp:111:7:111:8 | m2 | | +| map.cpp:102:31:102:32 | call to map | map.cpp:117:7:117:8 | m2 | | +| map.cpp:102:31:102:32 | call to map | map.cpp:123:7:123:8 | m2 | | +| map.cpp:102:31:102:32 | call to map | map.cpp:130:30:130:31 | m2 | | +| map.cpp:102:31:102:32 | call to map | map.cpp:131:32:131:33 | m2 | | +| map.cpp:102:31:102:32 | call to map | map.cpp:133:7:133:8 | m2 | | +| map.cpp:102:31:102:32 | call to map | map.cpp:149:12:149:13 | m2 | | +| map.cpp:102:31:102:32 | call to map | map.cpp:149:30:149:31 | m2 | | +| map.cpp:102:31:102:32 | call to map | map.cpp:179:7:179:8 | m2 | | +| map.cpp:102:31:102:32 | call to map | map.cpp:180:7:180:8 | m2 | | +| map.cpp:102:31:102:32 | call to map | map.cpp:181:7:181:8 | m2 | | +| map.cpp:102:31:102:32 | call to map | map.cpp:182:7:182:8 | m2 | | +| map.cpp:102:31:102:32 | call to map | map.cpp:183:7:183:8 | m2 | | +| map.cpp:102:31:102:32 | call to map | map.cpp:184:7:184:8 | m2 | | +| map.cpp:102:31:102:32 | call to map | map.cpp:249:1:249:1 | m2 | | +| map.cpp:102:35:102:36 | call to map | map.cpp:106:7:106:8 | m3 | | +| map.cpp:102:35:102:36 | call to map | map.cpp:112:7:112:8 | m3 | | +| map.cpp:102:35:102:36 | call to map | map.cpp:118:7:118:8 | m3 | | +| map.cpp:102:35:102:36 | call to map | map.cpp:124:7:124:8 | m3 | | +| map.cpp:102:35:102:36 | call to map | map.cpp:155:12:155:13 | m3 | | +| map.cpp:102:35:102:36 | call to map | map.cpp:155:30:155:31 | m3 | | +| map.cpp:102:35:102:36 | call to map | map.cpp:249:1:249:1 | m3 | | +| map.cpp:102:39:102:40 | call to map | map.cpp:107:7:107:8 | m4 | | +| map.cpp:102:39:102:40 | call to map | map.cpp:107:17:107:18 | m4 | | +| map.cpp:102:39:102:40 | call to map | map.cpp:113:7:113:8 | m4 | | +| map.cpp:102:39:102:40 | call to map | map.cpp:119:7:119:8 | m4 | | +| map.cpp:102:39:102:40 | call to map | map.cpp:125:7:125:8 | m4 | | +| map.cpp:102:39:102:40 | call to map | map.cpp:249:1:249:1 | m4 | | +| map.cpp:102:43:102:44 | call to map | map.cpp:108:7:108:8 | m5 | | +| map.cpp:102:43:102:44 | call to map | map.cpp:114:7:114:8 | m5 | | +| map.cpp:102:43:102:44 | call to map | map.cpp:120:7:120:8 | m5 | | +| map.cpp:102:43:102:44 | call to map | map.cpp:126:7:126:8 | m5 | | +| map.cpp:102:43:102:44 | call to map | map.cpp:249:1:249:1 | m5 | | +| map.cpp:102:47:102:48 | call to map | map.cpp:109:7:109:8 | m6 | | +| map.cpp:102:47:102:48 | call to map | map.cpp:109:27:109:28 | m6 | | +| map.cpp:102:47:102:48 | call to map | map.cpp:115:7:115:8 | m6 | | +| map.cpp:102:47:102:48 | call to map | map.cpp:121:7:121:8 | m6 | | +| map.cpp:102:47:102:48 | call to map | map.cpp:127:7:127:8 | m6 | | +| map.cpp:102:47:102:48 | call to map | map.cpp:249:1:249:1 | m6 | | +| map.cpp:104:7:104:8 | ref arg m1 | map.cpp:110:7:110:8 | m1 | | +| map.cpp:104:7:104:8 | ref arg m1 | map.cpp:116:7:116:8 | m1 | | +| map.cpp:104:7:104:8 | ref arg m1 | map.cpp:122:7:122:8 | m1 | | +| map.cpp:104:7:104:8 | ref arg m1 | map.cpp:143:12:143:13 | m1 | | +| map.cpp:104:7:104:8 | ref arg m1 | map.cpp:143:30:143:31 | m1 | | +| map.cpp:104:7:104:8 | ref arg m1 | map.cpp:249:1:249:1 | m1 | | +| map.cpp:104:17:104:30 | call to make_pair | map.cpp:104:17:104:44 | call to pair | TAINT | +| map.cpp:104:47:104:51 | first | map.cpp:104:7:104:51 | call to iterator | | +| map.cpp:105:7:105:8 | ref arg m2 | map.cpp:111:7:111:8 | m2 | | +| map.cpp:105:7:105:8 | ref arg m2 | map.cpp:117:7:117:8 | m2 | | +| map.cpp:105:7:105:8 | ref arg m2 | map.cpp:123:7:123:8 | m2 | | +| map.cpp:105:7:105:8 | ref arg m2 | map.cpp:130:30:130:31 | m2 | | +| map.cpp:105:7:105:8 | ref arg m2 | map.cpp:131:32:131:33 | m2 | | +| map.cpp:105:7:105:8 | ref arg m2 | map.cpp:133:7:133:8 | m2 | | +| map.cpp:105:7:105:8 | ref arg m2 | map.cpp:149:12:149:13 | m2 | | +| map.cpp:105:7:105:8 | ref arg m2 | map.cpp:149:30:149:31 | m2 | | +| map.cpp:105:7:105:8 | ref arg m2 | map.cpp:179:7:179:8 | m2 | | +| map.cpp:105:7:105:8 | ref arg m2 | map.cpp:180:7:180:8 | m2 | | +| map.cpp:105:7:105:8 | ref arg m2 | map.cpp:181:7:181:8 | m2 | | +| map.cpp:105:7:105:8 | ref arg m2 | map.cpp:182:7:182:8 | m2 | | +| map.cpp:105:7:105:8 | ref arg m2 | map.cpp:183:7:183:8 | m2 | | +| map.cpp:105:7:105:8 | ref arg m2 | map.cpp:184:7:184:8 | m2 | | +| map.cpp:105:7:105:8 | ref arg m2 | map.cpp:249:1:249:1 | m2 | | +| map.cpp:105:17:105:30 | call to make_pair | map.cpp:105:17:105:47 | call to pair | TAINT | +| map.cpp:105:50:105:54 | first | map.cpp:105:7:105:54 | call to iterator | | +| map.cpp:106:7:106:8 | ref arg m3 | map.cpp:112:7:112:8 | m3 | | +| map.cpp:106:7:106:8 | ref arg m3 | map.cpp:118:7:118:8 | m3 | | +| map.cpp:106:7:106:8 | ref arg m3 | map.cpp:124:7:124:8 | m3 | | +| map.cpp:106:7:106:8 | ref arg m3 | map.cpp:155:12:155:13 | m3 | | +| map.cpp:106:7:106:8 | ref arg m3 | map.cpp:155:30:155:31 | m3 | | +| map.cpp:106:7:106:8 | ref arg m3 | map.cpp:249:1:249:1 | m3 | | +| map.cpp:106:17:106:30 | call to make_pair | map.cpp:106:17:106:47 | call to pair | TAINT | +| map.cpp:106:50:106:54 | first | map.cpp:106:7:106:54 | call to iterator | | +| map.cpp:107:7:107:8 | ref arg m4 | map.cpp:113:7:113:8 | m4 | | +| map.cpp:107:7:107:8 | ref arg m4 | map.cpp:119:7:119:8 | m4 | | +| map.cpp:107:7:107:8 | ref arg m4 | map.cpp:125:7:125:8 | m4 | | +| map.cpp:107:7:107:8 | ref arg m4 | map.cpp:249:1:249:1 | m4 | | +| map.cpp:107:17:107:18 | ref arg m4 | map.cpp:107:7:107:8 | m4 | | +| map.cpp:107:17:107:18 | ref arg m4 | map.cpp:113:7:113:8 | m4 | | +| map.cpp:107:17:107:18 | ref arg m4 | map.cpp:119:7:119:8 | m4 | | +| map.cpp:107:17:107:18 | ref arg m4 | map.cpp:125:7:125:8 | m4 | | +| map.cpp:107:17:107:18 | ref arg m4 | map.cpp:249:1:249:1 | m4 | | +| map.cpp:107:20:107:24 | call to begin | map.cpp:107:17:107:26 | call to iterator | TAINT | +| map.cpp:107:29:107:70 | call to pair | map.cpp:107:29:107:70 | call to pair | TAINT | +| map.cpp:108:7:108:8 | ref arg m5 | map.cpp:114:7:114:8 | m5 | | +| map.cpp:108:7:108:8 | ref arg m5 | map.cpp:120:7:120:8 | m5 | | +| map.cpp:108:7:108:8 | ref arg m5 | map.cpp:126:7:126:8 | m5 | | +| map.cpp:108:7:108:8 | ref arg m5 | map.cpp:249:1:249:1 | m5 | | +| map.cpp:108:44:108:48 | first | map.cpp:108:7:108:48 | call to iterator | | +| map.cpp:109:7:109:8 | ref arg m6 | map.cpp:115:7:115:8 | m6 | | +| map.cpp:109:7:109:8 | ref arg m6 | map.cpp:121:7:121:8 | m6 | | +| map.cpp:109:7:109:8 | ref arg m6 | map.cpp:127:7:127:8 | m6 | | +| map.cpp:109:7:109:8 | ref arg m6 | map.cpp:249:1:249:1 | m6 | | +| map.cpp:109:27:109:28 | ref arg m6 | map.cpp:109:7:109:8 | m6 | | +| map.cpp:109:27:109:28 | ref arg m6 | map.cpp:115:7:115:8 | m6 | | +| map.cpp:109:27:109:28 | ref arg m6 | map.cpp:121:7:121:8 | m6 | | +| map.cpp:109:27:109:28 | ref arg m6 | map.cpp:127:7:127:8 | m6 | | +| map.cpp:109:27:109:28 | ref arg m6 | map.cpp:249:1:249:1 | m6 | | +| map.cpp:109:30:109:34 | call to begin | map.cpp:109:27:109:36 | call to iterator | TAINT | +| map.cpp:110:7:110:8 | m1 | map.cpp:110:7:110:8 | call to map | | +| map.cpp:111:7:111:8 | m2 | map.cpp:111:7:111:8 | call to map | | +| map.cpp:112:7:112:8 | m3 | map.cpp:112:7:112:8 | call to map | | +| map.cpp:113:7:113:8 | m4 | map.cpp:113:7:113:8 | call to map | | +| map.cpp:114:7:114:8 | m5 | map.cpp:114:7:114:8 | call to map | | +| map.cpp:115:7:115:8 | m6 | map.cpp:115:7:115:8 | call to map | | +| map.cpp:116:7:116:8 | ref arg m1 | map.cpp:122:7:122:8 | m1 | | +| map.cpp:116:7:116:8 | ref arg m1 | map.cpp:143:12:143:13 | m1 | | +| map.cpp:116:7:116:8 | ref arg m1 | map.cpp:143:30:143:31 | m1 | | +| map.cpp:116:7:116:8 | ref arg m1 | map.cpp:249:1:249:1 | m1 | | +| map.cpp:117:7:117:8 | ref arg m2 | map.cpp:123:7:123:8 | m2 | | +| map.cpp:117:7:117:8 | ref arg m2 | map.cpp:130:30:130:31 | m2 | | +| map.cpp:117:7:117:8 | ref arg m2 | map.cpp:131:32:131:33 | m2 | | +| map.cpp:117:7:117:8 | ref arg m2 | map.cpp:133:7:133:8 | m2 | | +| map.cpp:117:7:117:8 | ref arg m2 | map.cpp:149:12:149:13 | m2 | | +| map.cpp:117:7:117:8 | ref arg m2 | map.cpp:149:30:149:31 | m2 | | +| map.cpp:117:7:117:8 | ref arg m2 | map.cpp:179:7:179:8 | m2 | | +| map.cpp:117:7:117:8 | ref arg m2 | map.cpp:180:7:180:8 | m2 | | +| map.cpp:117:7:117:8 | ref arg m2 | map.cpp:181:7:181:8 | m2 | | +| map.cpp:117:7:117:8 | ref arg m2 | map.cpp:182:7:182:8 | m2 | | +| map.cpp:117:7:117:8 | ref arg m2 | map.cpp:183:7:183:8 | m2 | | +| map.cpp:117:7:117:8 | ref arg m2 | map.cpp:184:7:184:8 | m2 | | +| map.cpp:117:7:117:8 | ref arg m2 | map.cpp:249:1:249:1 | m2 | | +| map.cpp:118:7:118:8 | ref arg m3 | map.cpp:124:7:124:8 | m3 | | +| map.cpp:118:7:118:8 | ref arg m3 | map.cpp:155:12:155:13 | m3 | | +| map.cpp:118:7:118:8 | ref arg m3 | map.cpp:155:30:155:31 | m3 | | +| map.cpp:118:7:118:8 | ref arg m3 | map.cpp:249:1:249:1 | m3 | | +| map.cpp:119:7:119:8 | ref arg m4 | map.cpp:125:7:125:8 | m4 | | +| map.cpp:119:7:119:8 | ref arg m4 | map.cpp:249:1:249:1 | m4 | | +| map.cpp:120:7:120:8 | ref arg m5 | map.cpp:126:7:126:8 | m5 | | +| map.cpp:120:7:120:8 | ref arg m5 | map.cpp:249:1:249:1 | m5 | | +| map.cpp:121:7:121:8 | ref arg m6 | map.cpp:127:7:127:8 | m6 | | +| map.cpp:121:7:121:8 | ref arg m6 | map.cpp:249:1:249:1 | m6 | | +| map.cpp:122:7:122:8 | ref arg m1 | map.cpp:143:12:143:13 | m1 | | +| map.cpp:122:7:122:8 | ref arg m1 | map.cpp:143:30:143:31 | m1 | | +| map.cpp:122:7:122:8 | ref arg m1 | map.cpp:249:1:249:1 | m1 | | +| map.cpp:123:7:123:8 | ref arg m2 | map.cpp:130:30:130:31 | m2 | | +| map.cpp:123:7:123:8 | ref arg m2 | map.cpp:131:32:131:33 | m2 | | +| map.cpp:123:7:123:8 | ref arg m2 | map.cpp:133:7:133:8 | m2 | | +| map.cpp:123:7:123:8 | ref arg m2 | map.cpp:149:12:149:13 | m2 | | +| map.cpp:123:7:123:8 | ref arg m2 | map.cpp:149:30:149:31 | m2 | | +| map.cpp:123:7:123:8 | ref arg m2 | map.cpp:179:7:179:8 | m2 | | +| map.cpp:123:7:123:8 | ref arg m2 | map.cpp:180:7:180:8 | m2 | | +| map.cpp:123:7:123:8 | ref arg m2 | map.cpp:181:7:181:8 | m2 | | +| map.cpp:123:7:123:8 | ref arg m2 | map.cpp:182:7:182:8 | m2 | | +| map.cpp:123:7:123:8 | ref arg m2 | map.cpp:183:7:183:8 | m2 | | +| map.cpp:123:7:123:8 | ref arg m2 | map.cpp:184:7:184:8 | m2 | | +| map.cpp:123:7:123:8 | ref arg m2 | map.cpp:249:1:249:1 | m2 | | +| map.cpp:124:7:124:8 | ref arg m3 | map.cpp:155:12:155:13 | m3 | | +| map.cpp:124:7:124:8 | ref arg m3 | map.cpp:155:30:155:31 | m3 | | +| map.cpp:124:7:124:8 | ref arg m3 | map.cpp:249:1:249:1 | m3 | | +| map.cpp:125:7:125:8 | ref arg m4 | map.cpp:249:1:249:1 | m4 | | +| map.cpp:126:7:126:8 | ref arg m5 | map.cpp:249:1:249:1 | m5 | | +| map.cpp:127:7:127:8 | ref arg m6 | map.cpp:249:1:249:1 | m6 | | +| map.cpp:130:30:130:31 | m2 | map.cpp:130:30:130:32 | call to map | | +| map.cpp:130:30:130:32 | call to map | map.cpp:134:7:134:8 | m7 | | +| map.cpp:130:30:130:32 | call to map | map.cpp:137:7:137:8 | m7 | | +| map.cpp:130:30:130:32 | call to map | map.cpp:249:1:249:1 | m7 | | +| map.cpp:131:31:131:33 | call to map | map.cpp:135:7:135:8 | m8 | | +| map.cpp:131:31:131:33 | call to map | map.cpp:138:7:138:8 | m8 | | +| map.cpp:131:31:131:33 | call to map | map.cpp:249:1:249:1 | m8 | | +| map.cpp:131:32:131:33 | m2 | map.cpp:131:31:131:33 | call to map | | +| map.cpp:132:27:132:28 | call to map | map.cpp:133:2:133:3 | m9 | | +| map.cpp:132:27:132:28 | call to map | map.cpp:136:7:136:8 | m9 | | +| map.cpp:132:27:132:28 | call to map | map.cpp:139:7:139:8 | m9 | | +| map.cpp:132:27:132:28 | call to map | map.cpp:249:1:249:1 | m9 | | +| map.cpp:133:2:133:3 | ref arg m9 | map.cpp:136:7:136:8 | m9 | | +| map.cpp:133:2:133:3 | ref arg m9 | map.cpp:139:7:139:8 | m9 | | +| map.cpp:133:2:133:3 | ref arg m9 | map.cpp:249:1:249:1 | m9 | | +| map.cpp:133:7:133:8 | m2 | map.cpp:133:2:133:3 | ref arg m9 | TAINT | +| map.cpp:133:7:133:8 | m2 | map.cpp:133:5:133:5 | call to operator= | TAINT | +| map.cpp:134:7:134:8 | m7 | map.cpp:134:7:134:8 | call to map | | +| map.cpp:135:7:135:8 | m8 | map.cpp:135:7:135:8 | call to map | | +| map.cpp:136:7:136:8 | m9 | map.cpp:136:7:136:8 | call to map | | +| map.cpp:137:7:137:8 | ref arg m7 | map.cpp:249:1:249:1 | m7 | | +| map.cpp:138:7:138:8 | ref arg m8 | map.cpp:249:1:249:1 | m8 | | +| map.cpp:139:7:139:8 | ref arg m9 | map.cpp:249:1:249:1 | m9 | | +| map.cpp:143:12:143:13 | ref arg m1 | map.cpp:143:30:143:31 | m1 | | +| map.cpp:143:12:143:13 | ref arg m1 | map.cpp:249:1:249:1 | m1 | | +| map.cpp:143:15:143:19 | call to begin | map.cpp:143:7:143:21 | ... = ... | | +| map.cpp:143:15:143:19 | call to begin | map.cpp:143:24:143:25 | i1 | | +| map.cpp:143:15:143:19 | call to begin | map.cpp:143:40:143:41 | i1 | | +| map.cpp:143:15:143:19 | call to begin | map.cpp:145:9:145:10 | i1 | | +| map.cpp:143:15:143:19 | call to begin | map.cpp:146:8:146:9 | i1 | | +| map.cpp:143:15:143:19 | call to begin | map.cpp:147:8:147:9 | i1 | | +| map.cpp:143:30:143:31 | ref arg m1 | map.cpp:143:30:143:31 | m1 | | +| map.cpp:143:30:143:31 | ref arg m1 | map.cpp:249:1:249:1 | m1 | | +| map.cpp:143:40:143:41 | i1 | map.cpp:143:42:143:42 | call to operator++ | | +| map.cpp:143:40:143:41 | ref arg i1 | map.cpp:143:24:143:25 | i1 | | +| map.cpp:143:40:143:41 | ref arg i1 | map.cpp:143:40:143:41 | i1 | | +| map.cpp:143:40:143:41 | ref arg i1 | map.cpp:145:9:145:10 | i1 | | +| map.cpp:143:40:143:41 | ref arg i1 | map.cpp:146:8:146:9 | i1 | | +| map.cpp:143:40:143:41 | ref arg i1 | map.cpp:147:8:147:9 | i1 | | +| map.cpp:145:8:145:8 | call to operator* | map.cpp:145:8:145:10 | call to pair | TAINT | +| map.cpp:145:9:145:10 | i1 | map.cpp:145:8:145:8 | call to operator* | TAINT | +| map.cpp:146:8:146:9 | i1 | map.cpp:146:10:146:10 | call to operator-> | TAINT | +| map.cpp:147:8:147:9 | i1 | map.cpp:147:10:147:10 | call to operator-> | TAINT | +| map.cpp:149:12:149:13 | ref arg m2 | map.cpp:149:30:149:31 | m2 | | +| map.cpp:149:12:149:13 | ref arg m2 | map.cpp:179:7:179:8 | m2 | | +| map.cpp:149:12:149:13 | ref arg m2 | map.cpp:180:7:180:8 | m2 | | +| map.cpp:149:12:149:13 | ref arg m2 | map.cpp:181:7:181:8 | m2 | | +| map.cpp:149:12:149:13 | ref arg m2 | map.cpp:182:7:182:8 | m2 | | +| map.cpp:149:12:149:13 | ref arg m2 | map.cpp:183:7:183:8 | m2 | | +| map.cpp:149:12:149:13 | ref arg m2 | map.cpp:184:7:184:8 | m2 | | +| map.cpp:149:12:149:13 | ref arg m2 | map.cpp:249:1:249:1 | m2 | | +| map.cpp:149:15:149:19 | call to begin | map.cpp:149:7:149:21 | ... = ... | | +| map.cpp:149:15:149:19 | call to begin | map.cpp:149:24:149:25 | i2 | | +| map.cpp:149:15:149:19 | call to begin | map.cpp:149:40:149:41 | i2 | | +| map.cpp:149:15:149:19 | call to begin | map.cpp:151:9:151:10 | i2 | | +| map.cpp:149:15:149:19 | call to begin | map.cpp:152:8:152:9 | i2 | | +| map.cpp:149:15:149:19 | call to begin | map.cpp:153:8:153:9 | i2 | | +| map.cpp:149:15:149:19 | call to begin | map.cpp:158:8:158:9 | i2 | | +| map.cpp:149:15:149:19 | call to begin | map.cpp:159:8:159:9 | i2 | | +| map.cpp:149:30:149:31 | ref arg m2 | map.cpp:149:30:149:31 | m2 | | +| map.cpp:149:30:149:31 | ref arg m2 | map.cpp:179:7:179:8 | m2 | | +| map.cpp:149:30:149:31 | ref arg m2 | map.cpp:180:7:180:8 | m2 | | +| map.cpp:149:30:149:31 | ref arg m2 | map.cpp:181:7:181:8 | m2 | | +| map.cpp:149:30:149:31 | ref arg m2 | map.cpp:182:7:182:8 | m2 | | +| map.cpp:149:30:149:31 | ref arg m2 | map.cpp:183:7:183:8 | m2 | | +| map.cpp:149:30:149:31 | ref arg m2 | map.cpp:184:7:184:8 | m2 | | +| map.cpp:149:30:149:31 | ref arg m2 | map.cpp:249:1:249:1 | m2 | | +| map.cpp:149:40:149:41 | i2 | map.cpp:149:42:149:42 | call to operator++ | | +| map.cpp:149:40:149:41 | ref arg i2 | map.cpp:149:24:149:25 | i2 | | +| map.cpp:149:40:149:41 | ref arg i2 | map.cpp:149:40:149:41 | i2 | | +| map.cpp:149:40:149:41 | ref arg i2 | map.cpp:151:9:151:10 | i2 | | +| map.cpp:149:40:149:41 | ref arg i2 | map.cpp:152:8:152:9 | i2 | | +| map.cpp:149:40:149:41 | ref arg i2 | map.cpp:153:8:153:9 | i2 | | +| map.cpp:149:40:149:41 | ref arg i2 | map.cpp:158:8:158:9 | i2 | | +| map.cpp:149:40:149:41 | ref arg i2 | map.cpp:159:8:159:9 | i2 | | +| map.cpp:151:8:151:8 | call to operator* | map.cpp:151:8:151:10 | call to pair | TAINT | +| map.cpp:151:9:151:10 | i2 | map.cpp:151:8:151:8 | call to operator* | TAINT | +| map.cpp:152:8:152:9 | i2 | map.cpp:152:10:152:10 | call to operator-> | TAINT | +| map.cpp:153:8:153:9 | i2 | map.cpp:153:10:153:10 | call to operator-> | TAINT | +| map.cpp:155:12:155:13 | ref arg m3 | map.cpp:155:30:155:31 | m3 | | +| map.cpp:155:12:155:13 | ref arg m3 | map.cpp:249:1:249:1 | m3 | | +| map.cpp:155:15:155:19 | call to begin | map.cpp:155:7:155:21 | ... = ... | | +| map.cpp:155:15:155:19 | call to begin | map.cpp:155:24:155:25 | i3 | | +| map.cpp:155:15:155:19 | call to begin | map.cpp:155:40:155:41 | i3 | | +| map.cpp:155:15:155:19 | call to begin | map.cpp:157:9:157:10 | i3 | | +| map.cpp:155:30:155:31 | ref arg m3 | map.cpp:155:30:155:31 | m3 | | +| map.cpp:155:30:155:31 | ref arg m3 | map.cpp:249:1:249:1 | m3 | | +| map.cpp:155:40:155:41 | i3 | map.cpp:155:42:155:42 | call to operator++ | | +| map.cpp:155:40:155:41 | ref arg i3 | map.cpp:155:24:155:25 | i3 | | +| map.cpp:155:40:155:41 | ref arg i3 | map.cpp:155:40:155:41 | i3 | | +| map.cpp:155:40:155:41 | ref arg i3 | map.cpp:157:9:157:10 | i3 | | +| map.cpp:157:8:157:8 | call to operator* | map.cpp:157:8:157:10 | call to pair | TAINT | +| map.cpp:157:9:157:10 | i3 | map.cpp:157:8:157:8 | call to operator* | TAINT | +| map.cpp:158:8:158:9 | i2 | map.cpp:158:10:158:10 | call to operator-> | TAINT | +| map.cpp:159:8:159:9 | i2 | map.cpp:159:10:159:10 | call to operator-> | TAINT | +| map.cpp:163:27:163:29 | call to map | map.cpp:164:7:164:9 | m10 | | +| map.cpp:163:27:163:29 | call to map | map.cpp:168:7:168:9 | m10 | | +| map.cpp:163:27:163:29 | call to map | map.cpp:249:1:249:1 | m10 | | +| map.cpp:163:32:163:34 | call to map | map.cpp:165:7:165:9 | m11 | | +| map.cpp:163:32:163:34 | call to map | map.cpp:169:7:169:9 | m11 | | +| map.cpp:163:32:163:34 | call to map | map.cpp:249:1:249:1 | m11 | | +| map.cpp:163:37:163:39 | call to map | map.cpp:166:7:166:9 | m12 | | +| map.cpp:163:37:163:39 | call to map | map.cpp:170:7:170:9 | m12 | | +| map.cpp:163:37:163:39 | call to map | map.cpp:249:1:249:1 | m12 | | +| map.cpp:163:42:163:44 | call to map | map.cpp:167:7:167:9 | m13 | | +| map.cpp:163:42:163:44 | call to map | map.cpp:171:7:171:9 | m13 | | +| map.cpp:163:42:163:44 | call to map | map.cpp:249:1:249:1 | m13 | | +| map.cpp:164:7:164:9 | ref arg m10 | map.cpp:168:7:168:9 | m10 | | +| map.cpp:164:7:164:9 | ref arg m10 | map.cpp:249:1:249:1 | m10 | | +| map.cpp:164:7:164:24 | ... = ... | map.cpp:164:10:164:10 | call to operator[] [post update] | | +| map.cpp:164:20:164:24 | def | map.cpp:164:7:164:24 | ... = ... | | +| map.cpp:165:7:165:9 | ref arg m11 | map.cpp:169:7:169:9 | m11 | | +| map.cpp:165:7:165:9 | ref arg m11 | map.cpp:249:1:249:1 | m11 | | +| map.cpp:165:7:165:27 | ... = ... | map.cpp:165:10:165:10 | call to operator[] [post update] | | +| map.cpp:165:20:165:25 | call to source | map.cpp:165:7:165:27 | ... = ... | | +| map.cpp:166:7:166:9 | ref arg m12 | map.cpp:170:7:170:9 | m12 | | +| map.cpp:166:7:166:9 | ref arg m12 | map.cpp:249:1:249:1 | m12 | | +| map.cpp:166:7:166:27 | ... = ... | map.cpp:166:11:166:12 | call to at [post update] | | +| map.cpp:166:23:166:27 | def | map.cpp:166:7:166:27 | ... = ... | | +| map.cpp:167:7:167:9 | ref arg m13 | map.cpp:171:7:171:9 | m13 | | +| map.cpp:167:7:167:9 | ref arg m13 | map.cpp:249:1:249:1 | m13 | | +| map.cpp:167:7:167:30 | ... = ... | map.cpp:167:11:167:12 | call to at [post update] | | +| map.cpp:167:23:167:28 | call to source | map.cpp:167:7:167:30 | ... = ... | | +| map.cpp:168:7:168:9 | ref arg m10 | map.cpp:249:1:249:1 | m10 | | +| map.cpp:169:7:169:9 | ref arg m11 | map.cpp:249:1:249:1 | m11 | | +| map.cpp:170:7:170:9 | ref arg m12 | map.cpp:249:1:249:1 | m12 | | +| map.cpp:171:7:171:9 | ref arg m13 | map.cpp:249:1:249:1 | m13 | | +| map.cpp:174:27:174:29 | call to map | map.cpp:175:2:175:4 | m14 | | +| map.cpp:174:27:174:29 | call to map | map.cpp:176:2:176:4 | m14 | | +| map.cpp:174:27:174:29 | call to map | map.cpp:177:2:177:4 | m14 | | +| map.cpp:174:27:174:29 | call to map | map.cpp:178:2:178:4 | m14 | | +| map.cpp:174:27:174:29 | call to map | map.cpp:249:1:249:1 | m14 | | +| map.cpp:175:2:175:4 | ref arg m14 | map.cpp:176:2:176:4 | m14 | | +| map.cpp:175:2:175:4 | ref arg m14 | map.cpp:177:2:177:4 | m14 | | +| map.cpp:175:2:175:4 | ref arg m14 | map.cpp:178:2:178:4 | m14 | | +| map.cpp:175:2:175:4 | ref arg m14 | map.cpp:249:1:249:1 | m14 | | +| map.cpp:175:13:175:26 | call to make_pair | map.cpp:175:13:175:36 | call to pair | TAINT | +| map.cpp:176:2:176:4 | ref arg m14 | map.cpp:177:2:177:4 | m14 | | +| map.cpp:176:2:176:4 | ref arg m14 | map.cpp:178:2:178:4 | m14 | | +| map.cpp:176:2:176:4 | ref arg m14 | map.cpp:249:1:249:1 | m14 | | +| map.cpp:176:13:176:26 | call to make_pair | map.cpp:176:13:176:41 | call to pair | TAINT | +| map.cpp:177:2:177:4 | ref arg m14 | map.cpp:178:2:178:4 | m14 | | +| map.cpp:177:2:177:4 | ref arg m14 | map.cpp:249:1:249:1 | m14 | | +| map.cpp:177:13:177:26 | call to make_pair | map.cpp:177:13:177:41 | call to pair | TAINT | +| map.cpp:178:2:178:4 | ref arg m14 | map.cpp:249:1:249:1 | m14 | | +| map.cpp:178:13:178:26 | call to make_pair | map.cpp:178:13:178:36 | call to pair | TAINT | +| map.cpp:179:7:179:8 | ref arg m2 | map.cpp:180:7:180:8 | m2 | | +| map.cpp:179:7:179:8 | ref arg m2 | map.cpp:181:7:181:8 | m2 | | +| map.cpp:179:7:179:8 | ref arg m2 | map.cpp:182:7:182:8 | m2 | | +| map.cpp:179:7:179:8 | ref arg m2 | map.cpp:183:7:183:8 | m2 | | +| map.cpp:179:7:179:8 | ref arg m2 | map.cpp:184:7:184:8 | m2 | | +| map.cpp:179:7:179:8 | ref arg m2 | map.cpp:249:1:249:1 | m2 | | +| map.cpp:180:7:180:8 | ref arg m2 | map.cpp:181:7:181:8 | m2 | | +| map.cpp:180:7:180:8 | ref arg m2 | map.cpp:182:7:182:8 | m2 | | +| map.cpp:180:7:180:8 | ref arg m2 | map.cpp:183:7:183:8 | m2 | | +| map.cpp:180:7:180:8 | ref arg m2 | map.cpp:184:7:184:8 | m2 | | +| map.cpp:180:7:180:8 | ref arg m2 | map.cpp:249:1:249:1 | m2 | | +| map.cpp:181:7:181:8 | ref arg m2 | map.cpp:182:7:182:8 | m2 | | +| map.cpp:181:7:181:8 | ref arg m2 | map.cpp:183:7:183:8 | m2 | | +| map.cpp:181:7:181:8 | ref arg m2 | map.cpp:184:7:184:8 | m2 | | +| map.cpp:181:7:181:8 | ref arg m2 | map.cpp:249:1:249:1 | m2 | | +| map.cpp:181:27:181:31 | first | map.cpp:181:7:181:31 | call to iterator | | +| map.cpp:182:7:182:8 | ref arg m2 | map.cpp:183:7:183:8 | m2 | | +| map.cpp:182:7:182:8 | ref arg m2 | map.cpp:184:7:184:8 | m2 | | +| map.cpp:182:7:182:8 | ref arg m2 | map.cpp:249:1:249:1 | m2 | | +| map.cpp:182:27:182:32 | second | map.cpp:182:7:182:32 | call to iterator | | +| map.cpp:183:7:183:8 | ref arg m2 | map.cpp:184:7:184:8 | m2 | | +| map.cpp:183:7:183:8 | ref arg m2 | map.cpp:249:1:249:1 | m2 | | +| map.cpp:184:7:184:8 | ref arg m2 | map.cpp:249:1:249:1 | m2 | | +| map.cpp:184:27:184:32 | second | map.cpp:184:7:184:32 | call to iterator | | +| map.cpp:187:27:187:29 | call to map | map.cpp:188:2:188:4 | m15 | | +| map.cpp:187:27:187:29 | call to map | map.cpp:190:7:190:9 | m15 | | +| map.cpp:187:27:187:29 | call to map | map.cpp:194:2:194:4 | m15 | | +| map.cpp:187:27:187:29 | call to map | map.cpp:196:7:196:9 | m15 | | +| map.cpp:187:27:187:29 | call to map | map.cpp:211:2:211:4 | m15 | | +| map.cpp:187:27:187:29 | call to map | map.cpp:249:1:249:1 | m15 | | +| map.cpp:187:32:187:34 | call to map | map.cpp:191:7:191:9 | m16 | | +| map.cpp:187:32:187:34 | call to map | map.cpp:194:11:194:13 | m16 | | +| map.cpp:187:32:187:34 | call to map | map.cpp:197:7:197:9 | m16 | | +| map.cpp:187:32:187:34 | call to map | map.cpp:211:12:211:14 | m16 | | +| map.cpp:187:32:187:34 | call to map | map.cpp:249:1:249:1 | m16 | | +| map.cpp:187:37:187:39 | call to map | map.cpp:192:7:192:9 | m17 | | +| map.cpp:187:37:187:39 | call to map | map.cpp:195:2:195:4 | m17 | | +| map.cpp:187:37:187:39 | call to map | map.cpp:198:7:198:9 | m17 | | +| map.cpp:187:37:187:39 | call to map | map.cpp:212:2:212:4 | m17 | | +| map.cpp:187:37:187:39 | call to map | map.cpp:249:1:249:1 | m17 | | +| map.cpp:187:42:187:44 | call to map | map.cpp:189:2:189:4 | m18 | | +| map.cpp:187:42:187:44 | call to map | map.cpp:193:7:193:9 | m18 | | +| map.cpp:187:42:187:44 | call to map | map.cpp:195:11:195:13 | m18 | | +| map.cpp:187:42:187:44 | call to map | map.cpp:199:7:199:9 | m18 | | +| map.cpp:187:42:187:44 | call to map | map.cpp:212:12:212:14 | m18 | | +| map.cpp:187:42:187:44 | call to map | map.cpp:249:1:249:1 | m18 | | +| map.cpp:188:2:188:4 | ref arg m15 | map.cpp:190:7:190:9 | m15 | | +| map.cpp:188:2:188:4 | ref arg m15 | map.cpp:194:2:194:4 | m15 | | +| map.cpp:188:2:188:4 | ref arg m15 | map.cpp:196:7:196:9 | m15 | | +| map.cpp:188:2:188:4 | ref arg m15 | map.cpp:211:2:211:4 | m15 | | +| map.cpp:188:2:188:4 | ref arg m15 | map.cpp:249:1:249:1 | m15 | | +| map.cpp:188:13:188:57 | call to pair | map.cpp:188:13:188:57 | call to pair | TAINT | +| map.cpp:189:2:189:4 | ref arg m18 | map.cpp:193:7:193:9 | m18 | | +| map.cpp:189:2:189:4 | ref arg m18 | map.cpp:195:11:195:13 | m18 | | +| map.cpp:189:2:189:4 | ref arg m18 | map.cpp:199:7:199:9 | m18 | | +| map.cpp:189:2:189:4 | ref arg m18 | map.cpp:212:12:212:14 | m18 | | +| map.cpp:189:2:189:4 | ref arg m18 | map.cpp:249:1:249:1 | m18 | | +| map.cpp:189:13:189:57 | call to pair | map.cpp:189:13:189:57 | call to pair | TAINT | +| map.cpp:190:7:190:9 | m15 | map.cpp:190:7:190:9 | call to map | | +| map.cpp:191:7:191:9 | m16 | map.cpp:191:7:191:9 | call to map | | +| map.cpp:192:7:192:9 | m17 | map.cpp:192:7:192:9 | call to map | | +| map.cpp:193:7:193:9 | m18 | map.cpp:193:7:193:9 | call to map | | +| map.cpp:194:2:194:4 | ref arg m15 | map.cpp:196:7:196:9 | m15 | | +| map.cpp:194:2:194:4 | ref arg m15 | map.cpp:211:2:211:4 | m15 | | +| map.cpp:194:2:194:4 | ref arg m15 | map.cpp:249:1:249:1 | m15 | | +| map.cpp:194:11:194:13 | ref arg m16 | map.cpp:197:7:197:9 | m16 | | +| map.cpp:194:11:194:13 | ref arg m16 | map.cpp:211:12:211:14 | m16 | | +| map.cpp:194:11:194:13 | ref arg m16 | map.cpp:249:1:249:1 | m16 | | +| map.cpp:195:2:195:4 | ref arg m17 | map.cpp:198:7:198:9 | m17 | | +| map.cpp:195:2:195:4 | ref arg m17 | map.cpp:212:2:212:4 | m17 | | +| map.cpp:195:2:195:4 | ref arg m17 | map.cpp:249:1:249:1 | m17 | | +| map.cpp:195:11:195:13 | ref arg m18 | map.cpp:199:7:199:9 | m18 | | +| map.cpp:195:11:195:13 | ref arg m18 | map.cpp:212:12:212:14 | m18 | | +| map.cpp:195:11:195:13 | ref arg m18 | map.cpp:249:1:249:1 | m18 | | +| map.cpp:196:7:196:9 | m15 | map.cpp:196:7:196:9 | call to map | | +| map.cpp:197:7:197:9 | m16 | map.cpp:197:7:197:9 | call to map | | +| map.cpp:198:7:198:9 | m17 | map.cpp:198:7:198:9 | call to map | | +| map.cpp:199:7:199:9 | m18 | map.cpp:199:7:199:9 | call to map | | +| map.cpp:202:27:202:29 | call to map | map.cpp:203:2:203:4 | m19 | | +| map.cpp:202:27:202:29 | call to map | map.cpp:207:7:207:9 | m19 | | +| map.cpp:202:27:202:29 | call to map | map.cpp:213:7:213:9 | m19 | | +| map.cpp:202:27:202:29 | call to map | map.cpp:249:1:249:1 | m19 | | +| map.cpp:202:32:202:34 | call to map | map.cpp:204:2:204:4 | m20 | | +| map.cpp:202:32:202:34 | call to map | map.cpp:208:7:208:9 | m20 | | +| map.cpp:202:32:202:34 | call to map | map.cpp:214:7:214:9 | m20 | | +| map.cpp:202:32:202:34 | call to map | map.cpp:249:1:249:1 | m20 | | +| map.cpp:202:37:202:39 | call to map | map.cpp:205:2:205:4 | m21 | | +| map.cpp:202:37:202:39 | call to map | map.cpp:209:7:209:9 | m21 | | +| map.cpp:202:37:202:39 | call to map | map.cpp:215:7:215:9 | m21 | | +| map.cpp:202:37:202:39 | call to map | map.cpp:249:1:249:1 | m21 | | +| map.cpp:202:42:202:44 | call to map | map.cpp:206:2:206:4 | m22 | | +| map.cpp:202:42:202:44 | call to map | map.cpp:210:7:210:9 | m22 | | +| map.cpp:202:42:202:44 | call to map | map.cpp:216:7:216:9 | m22 | | +| map.cpp:202:42:202:44 | call to map | map.cpp:249:1:249:1 | m22 | | +| map.cpp:203:2:203:4 | ref arg m19 | map.cpp:207:7:207:9 | m19 | | +| map.cpp:203:2:203:4 | ref arg m19 | map.cpp:213:7:213:9 | m19 | | +| map.cpp:203:2:203:4 | ref arg m19 | map.cpp:249:1:249:1 | m19 | | +| map.cpp:203:13:203:57 | call to pair | map.cpp:203:13:203:57 | call to pair | TAINT | +| map.cpp:204:2:204:4 | ref arg m20 | map.cpp:208:7:208:9 | m20 | | +| map.cpp:204:2:204:4 | ref arg m20 | map.cpp:214:7:214:9 | m20 | | +| map.cpp:204:2:204:4 | ref arg m20 | map.cpp:249:1:249:1 | m20 | | +| map.cpp:204:13:204:51 | call to pair | map.cpp:204:13:204:51 | call to pair | TAINT | +| map.cpp:205:2:205:4 | ref arg m21 | map.cpp:209:7:209:9 | m21 | | +| map.cpp:205:2:205:4 | ref arg m21 | map.cpp:215:7:215:9 | m21 | | +| map.cpp:205:2:205:4 | ref arg m21 | map.cpp:249:1:249:1 | m21 | | +| map.cpp:205:13:205:51 | call to pair | map.cpp:205:13:205:51 | call to pair | TAINT | +| map.cpp:206:2:206:4 | ref arg m22 | map.cpp:210:7:210:9 | m22 | | +| map.cpp:206:2:206:4 | ref arg m22 | map.cpp:216:7:216:9 | m22 | | +| map.cpp:206:2:206:4 | ref arg m22 | map.cpp:249:1:249:1 | m22 | | +| map.cpp:206:13:206:57 | call to pair | map.cpp:206:13:206:57 | call to pair | TAINT | +| map.cpp:207:7:207:9 | m19 | map.cpp:207:7:207:9 | call to map | | +| map.cpp:208:7:208:9 | m20 | map.cpp:208:7:208:9 | call to map | | +| map.cpp:209:7:209:9 | m21 | map.cpp:209:7:209:9 | call to map | | +| map.cpp:210:7:210:9 | m22 | map.cpp:210:7:210:9 | call to map | | +| map.cpp:211:2:211:4 | ref arg m15 | map.cpp:249:1:249:1 | m15 | | +| map.cpp:211:12:211:14 | ref arg m16 | map.cpp:249:1:249:1 | m16 | | +| map.cpp:212:2:212:4 | ref arg m17 | map.cpp:249:1:249:1 | m17 | | +| map.cpp:212:12:212:14 | ref arg m18 | map.cpp:249:1:249:1 | m18 | | +| map.cpp:213:7:213:9 | m19 | map.cpp:213:7:213:9 | call to map | | +| map.cpp:214:7:214:9 | m20 | map.cpp:214:7:214:9 | call to map | | +| map.cpp:215:7:215:9 | m21 | map.cpp:215:7:215:9 | call to map | | +| map.cpp:216:7:216:9 | m22 | map.cpp:216:7:216:9 | call to map | | +| map.cpp:219:27:219:29 | call to map | map.cpp:220:2:220:4 | m23 | | +| map.cpp:219:27:219:29 | call to map | map.cpp:221:2:221:4 | m23 | | +| map.cpp:219:27:219:29 | call to map | map.cpp:222:7:222:9 | m23 | | +| map.cpp:219:27:219:29 | call to map | map.cpp:223:7:223:9 | m23 | | +| map.cpp:219:27:219:29 | call to map | map.cpp:223:17:223:19 | m23 | | +| map.cpp:219:27:219:29 | call to map | map.cpp:224:7:224:9 | m23 | | +| map.cpp:219:27:219:29 | call to map | map.cpp:225:2:225:4 | m23 | | +| map.cpp:219:27:219:29 | call to map | map.cpp:226:7:226:9 | m23 | | +| map.cpp:219:27:219:29 | call to map | map.cpp:249:1:249:1 | m23 | | +| map.cpp:220:2:220:4 | ref arg m23 | map.cpp:221:2:221:4 | m23 | | +| map.cpp:220:2:220:4 | ref arg m23 | map.cpp:222:7:222:9 | m23 | | +| map.cpp:220:2:220:4 | ref arg m23 | map.cpp:223:7:223:9 | m23 | | +| map.cpp:220:2:220:4 | ref arg m23 | map.cpp:223:17:223:19 | m23 | | +| map.cpp:220:2:220:4 | ref arg m23 | map.cpp:224:7:224:9 | m23 | | +| map.cpp:220:2:220:4 | ref arg m23 | map.cpp:225:2:225:4 | m23 | | +| map.cpp:220:2:220:4 | ref arg m23 | map.cpp:226:7:226:9 | m23 | | +| map.cpp:220:2:220:4 | ref arg m23 | map.cpp:249:1:249:1 | m23 | | +| map.cpp:220:13:220:57 | call to pair | map.cpp:220:13:220:57 | call to pair | TAINT | +| map.cpp:221:2:221:4 | ref arg m23 | map.cpp:222:7:222:9 | m23 | | +| map.cpp:221:2:221:4 | ref arg m23 | map.cpp:223:7:223:9 | m23 | | +| map.cpp:221:2:221:4 | ref arg m23 | map.cpp:223:17:223:19 | m23 | | +| map.cpp:221:2:221:4 | ref arg m23 | map.cpp:224:7:224:9 | m23 | | +| map.cpp:221:2:221:4 | ref arg m23 | map.cpp:225:2:225:4 | m23 | | +| map.cpp:221:2:221:4 | ref arg m23 | map.cpp:226:7:226:9 | m23 | | +| map.cpp:221:2:221:4 | ref arg m23 | map.cpp:249:1:249:1 | m23 | | +| map.cpp:221:13:221:57 | call to pair | map.cpp:221:13:221:57 | call to pair | TAINT | +| map.cpp:222:7:222:9 | m23 | map.cpp:222:7:222:9 | call to map | | +| map.cpp:223:7:223:9 | ref arg m23 | map.cpp:224:7:224:9 | m23 | | +| map.cpp:223:7:223:9 | ref arg m23 | map.cpp:225:2:225:4 | m23 | | +| map.cpp:223:7:223:9 | ref arg m23 | map.cpp:226:7:226:9 | m23 | | +| map.cpp:223:7:223:9 | ref arg m23 | map.cpp:249:1:249:1 | m23 | | +| map.cpp:223:17:223:19 | ref arg m23 | map.cpp:223:7:223:9 | m23 | | +| map.cpp:223:17:223:19 | ref arg m23 | map.cpp:224:7:224:9 | m23 | | +| map.cpp:223:17:223:19 | ref arg m23 | map.cpp:225:2:225:4 | m23 | | +| map.cpp:223:17:223:19 | ref arg m23 | map.cpp:226:7:226:9 | m23 | | +| map.cpp:223:17:223:19 | ref arg m23 | map.cpp:249:1:249:1 | m23 | | +| map.cpp:224:7:224:9 | m23 | map.cpp:224:7:224:9 | call to map | | +| map.cpp:225:2:225:4 | ref arg m23 | map.cpp:226:7:226:9 | m23 | | +| map.cpp:225:2:225:4 | ref arg m23 | map.cpp:249:1:249:1 | m23 | | +| map.cpp:226:7:226:9 | m23 | map.cpp:226:7:226:9 | call to map | | +| map.cpp:229:27:229:29 | call to map | map.cpp:230:7:230:9 | m24 | | +| map.cpp:229:27:229:29 | call to map | map.cpp:231:7:231:9 | m24 | | +| map.cpp:229:27:229:29 | call to map | map.cpp:232:7:232:9 | m24 | | +| map.cpp:229:27:229:29 | call to map | map.cpp:233:7:233:9 | m24 | | +| map.cpp:229:27:229:29 | call to map | map.cpp:249:1:249:1 | m24 | | +| map.cpp:229:32:229:34 | call to map | map.cpp:234:7:234:9 | m25 | | +| map.cpp:229:32:229:34 | call to map | map.cpp:234:24:234:26 | m25 | | +| map.cpp:229:32:229:34 | call to map | map.cpp:235:7:235:9 | m25 | | +| map.cpp:229:32:229:34 | call to map | map.cpp:236:7:236:9 | m25 | | +| map.cpp:229:32:229:34 | call to map | map.cpp:236:24:236:26 | m25 | | +| map.cpp:229:32:229:34 | call to map | map.cpp:237:7:237:9 | m25 | | +| map.cpp:229:32:229:34 | call to map | map.cpp:249:1:249:1 | m25 | | +| map.cpp:230:7:230:9 | ref arg m24 | map.cpp:231:7:231:9 | m24 | | +| map.cpp:230:7:230:9 | ref arg m24 | map.cpp:232:7:232:9 | m24 | | +| map.cpp:230:7:230:9 | ref arg m24 | map.cpp:233:7:233:9 | m24 | | +| map.cpp:230:7:230:9 | ref arg m24 | map.cpp:249:1:249:1 | m24 | | +| map.cpp:230:33:230:37 | first | map.cpp:230:7:230:37 | call to iterator | | +| map.cpp:231:7:231:9 | m24 | map.cpp:231:7:231:9 | call to map | | +| map.cpp:232:7:232:9 | ref arg m24 | map.cpp:233:7:233:9 | m24 | | +| map.cpp:232:7:232:9 | ref arg m24 | map.cpp:249:1:249:1 | m24 | | +| map.cpp:232:36:232:40 | first | map.cpp:232:7:232:40 | call to iterator | | +| map.cpp:233:7:233:9 | m24 | map.cpp:233:7:233:9 | call to map | | +| map.cpp:234:7:234:9 | ref arg m25 | map.cpp:235:7:235:9 | m25 | | +| map.cpp:234:7:234:9 | ref arg m25 | map.cpp:236:7:236:9 | m25 | | +| map.cpp:234:7:234:9 | ref arg m25 | map.cpp:236:24:236:26 | m25 | | +| map.cpp:234:7:234:9 | ref arg m25 | map.cpp:237:7:237:9 | m25 | | +| map.cpp:234:7:234:9 | ref arg m25 | map.cpp:249:1:249:1 | m25 | | +| map.cpp:234:24:234:26 | ref arg m25 | map.cpp:234:7:234:9 | m25 | | +| map.cpp:234:24:234:26 | ref arg m25 | map.cpp:235:7:235:9 | m25 | | +| map.cpp:234:24:234:26 | ref arg m25 | map.cpp:236:7:236:9 | m25 | | +| map.cpp:234:24:234:26 | ref arg m25 | map.cpp:236:24:236:26 | m25 | | +| map.cpp:234:24:234:26 | ref arg m25 | map.cpp:237:7:237:9 | m25 | | +| map.cpp:234:24:234:26 | ref arg m25 | map.cpp:249:1:249:1 | m25 | | +| map.cpp:234:28:234:32 | call to begin | map.cpp:234:24:234:34 | call to iterator | TAINT | +| map.cpp:235:7:235:9 | m25 | map.cpp:235:7:235:9 | call to map | | +| map.cpp:236:7:236:9 | ref arg m25 | map.cpp:237:7:237:9 | m25 | | +| map.cpp:236:7:236:9 | ref arg m25 | map.cpp:249:1:249:1 | m25 | | +| map.cpp:236:24:236:26 | ref arg m25 | map.cpp:236:7:236:9 | m25 | | +| map.cpp:236:24:236:26 | ref arg m25 | map.cpp:237:7:237:9 | m25 | | +| map.cpp:236:24:236:26 | ref arg m25 | map.cpp:249:1:249:1 | m25 | | +| map.cpp:236:28:236:32 | call to begin | map.cpp:236:24:236:34 | call to iterator | TAINT | +| map.cpp:237:7:237:9 | m25 | map.cpp:237:7:237:9 | call to map | | +| map.cpp:240:27:240:29 | call to map | map.cpp:241:7:241:9 | m26 | | +| map.cpp:240:27:240:29 | call to map | map.cpp:242:7:242:9 | m26 | | +| map.cpp:240:27:240:29 | call to map | map.cpp:243:7:243:9 | m26 | | +| map.cpp:240:27:240:29 | call to map | map.cpp:244:7:244:9 | m26 | | +| map.cpp:240:27:240:29 | call to map | map.cpp:249:1:249:1 | m26 | | +| map.cpp:240:32:240:34 | call to map | map.cpp:245:7:245:9 | m27 | | +| map.cpp:240:32:240:34 | call to map | map.cpp:245:23:245:25 | m27 | | +| map.cpp:240:32:240:34 | call to map | map.cpp:246:7:246:9 | m27 | | +| map.cpp:240:32:240:34 | call to map | map.cpp:247:7:247:9 | m27 | | +| map.cpp:240:32:240:34 | call to map | map.cpp:247:23:247:25 | m27 | | +| map.cpp:240:32:240:34 | call to map | map.cpp:248:7:248:9 | m27 | | +| map.cpp:240:32:240:34 | call to map | map.cpp:249:1:249:1 | m27 | | +| map.cpp:241:7:241:9 | ref arg m26 | map.cpp:242:7:242:9 | m26 | | +| map.cpp:241:7:241:9 | ref arg m26 | map.cpp:243:7:243:9 | m26 | | +| map.cpp:241:7:241:9 | ref arg m26 | map.cpp:244:7:244:9 | m26 | | +| map.cpp:241:7:241:9 | ref arg m26 | map.cpp:249:1:249:1 | m26 | | +| map.cpp:241:37:241:41 | first | map.cpp:241:7:241:41 | call to iterator | | +| map.cpp:242:7:242:9 | m26 | map.cpp:242:7:242:9 | call to map | | +| map.cpp:243:7:243:9 | ref arg m26 | map.cpp:244:7:244:9 | m26 | | +| map.cpp:243:7:243:9 | ref arg m26 | map.cpp:249:1:249:1 | m26 | | +| map.cpp:243:40:243:44 | first | map.cpp:243:7:243:44 | call to iterator | | +| map.cpp:244:7:244:9 | m26 | map.cpp:244:7:244:9 | call to map | | +| map.cpp:245:7:245:9 | ref arg m27 | map.cpp:246:7:246:9 | m27 | | +| map.cpp:245:7:245:9 | ref arg m27 | map.cpp:247:7:247:9 | m27 | | +| map.cpp:245:7:245:9 | ref arg m27 | map.cpp:247:23:247:25 | m27 | | +| map.cpp:245:7:245:9 | ref arg m27 | map.cpp:248:7:248:9 | m27 | | +| map.cpp:245:7:245:9 | ref arg m27 | map.cpp:249:1:249:1 | m27 | | +| map.cpp:245:23:245:25 | ref arg m27 | map.cpp:245:7:245:9 | m27 | | +| map.cpp:245:23:245:25 | ref arg m27 | map.cpp:246:7:246:9 | m27 | | +| map.cpp:245:23:245:25 | ref arg m27 | map.cpp:247:7:247:9 | m27 | | +| map.cpp:245:23:245:25 | ref arg m27 | map.cpp:247:23:247:25 | m27 | | +| map.cpp:245:23:245:25 | ref arg m27 | map.cpp:248:7:248:9 | m27 | | +| map.cpp:245:23:245:25 | ref arg m27 | map.cpp:249:1:249:1 | m27 | | +| map.cpp:245:27:245:31 | call to begin | map.cpp:245:23:245:33 | call to iterator | TAINT | +| map.cpp:246:7:246:9 | m27 | map.cpp:246:7:246:9 | call to map | | +| map.cpp:247:7:247:9 | ref arg m27 | map.cpp:248:7:248:9 | m27 | | +| map.cpp:247:7:247:9 | ref arg m27 | map.cpp:249:1:249:1 | m27 | | +| map.cpp:247:23:247:25 | ref arg m27 | map.cpp:247:7:247:9 | m27 | | +| map.cpp:247:23:247:25 | ref arg m27 | map.cpp:248:7:248:9 | m27 | | +| map.cpp:247:23:247:25 | ref arg m27 | map.cpp:249:1:249:1 | m27 | | +| map.cpp:247:27:247:31 | call to begin | map.cpp:247:23:247:33 | call to iterator | TAINT | +| map.cpp:248:7:248:9 | m27 | map.cpp:248:7:248:9 | call to map | | +| map.cpp:254:37:254:38 | call to unordered_map | map.cpp:256:7:256:8 | m1 | | +| map.cpp:254:37:254:38 | call to unordered_map | map.cpp:262:7:262:8 | m1 | | +| map.cpp:254:37:254:38 | call to unordered_map | map.cpp:268:7:268:8 | m1 | | +| map.cpp:254:37:254:38 | call to unordered_map | map.cpp:274:7:274:8 | m1 | | +| map.cpp:254:37:254:38 | call to unordered_map | map.cpp:295:12:295:13 | m1 | | +| map.cpp:254:37:254:38 | call to unordered_map | map.cpp:295:30:295:31 | m1 | | +| map.cpp:254:37:254:38 | call to unordered_map | map.cpp:398:1:398:1 | m1 | | +| map.cpp:254:41:254:42 | call to unordered_map | map.cpp:257:7:257:8 | m2 | | +| map.cpp:254:41:254:42 | call to unordered_map | map.cpp:263:7:263:8 | m2 | | +| map.cpp:254:41:254:42 | call to unordered_map | map.cpp:269:7:269:8 | m2 | | +| map.cpp:254:41:254:42 | call to unordered_map | map.cpp:275:7:275:8 | m2 | | +| map.cpp:254:41:254:42 | call to unordered_map | map.cpp:282:40:282:41 | m2 | | +| map.cpp:254:41:254:42 | call to unordered_map | map.cpp:283:42:283:43 | m2 | | +| map.cpp:254:41:254:42 | call to unordered_map | map.cpp:285:7:285:8 | m2 | | +| map.cpp:254:41:254:42 | call to unordered_map | map.cpp:301:12:301:13 | m2 | | +| map.cpp:254:41:254:42 | call to unordered_map | map.cpp:301:30:301:31 | m2 | | +| map.cpp:254:41:254:42 | call to unordered_map | map.cpp:331:7:331:8 | m2 | | +| map.cpp:254:41:254:42 | call to unordered_map | map.cpp:332:7:332:8 | m2 | | +| map.cpp:254:41:254:42 | call to unordered_map | map.cpp:333:7:333:8 | m2 | | +| map.cpp:254:41:254:42 | call to unordered_map | map.cpp:398:1:398:1 | m2 | | +| map.cpp:254:45:254:46 | call to unordered_map | map.cpp:258:7:258:8 | m3 | | +| map.cpp:254:45:254:46 | call to unordered_map | map.cpp:264:7:264:8 | m3 | | +| map.cpp:254:45:254:46 | call to unordered_map | map.cpp:270:7:270:8 | m3 | | +| map.cpp:254:45:254:46 | call to unordered_map | map.cpp:276:7:276:8 | m3 | | +| map.cpp:254:45:254:46 | call to unordered_map | map.cpp:307:12:307:13 | m3 | | +| map.cpp:254:45:254:46 | call to unordered_map | map.cpp:307:30:307:31 | m3 | | +| map.cpp:254:45:254:46 | call to unordered_map | map.cpp:398:1:398:1 | m3 | | +| map.cpp:254:49:254:50 | call to unordered_map | map.cpp:259:7:259:8 | m4 | | +| map.cpp:254:49:254:50 | call to unordered_map | map.cpp:259:17:259:18 | m4 | | +| map.cpp:254:49:254:50 | call to unordered_map | map.cpp:265:7:265:8 | m4 | | +| map.cpp:254:49:254:50 | call to unordered_map | map.cpp:271:7:271:8 | m4 | | +| map.cpp:254:49:254:50 | call to unordered_map | map.cpp:277:7:277:8 | m4 | | +| map.cpp:254:49:254:50 | call to unordered_map | map.cpp:398:1:398:1 | m4 | | +| map.cpp:254:53:254:54 | call to unordered_map | map.cpp:260:7:260:8 | m5 | | +| map.cpp:254:53:254:54 | call to unordered_map | map.cpp:266:7:266:8 | m5 | | +| map.cpp:254:53:254:54 | call to unordered_map | map.cpp:272:7:272:8 | m5 | | +| map.cpp:254:53:254:54 | call to unordered_map | map.cpp:278:7:278:8 | m5 | | +| map.cpp:254:53:254:54 | call to unordered_map | map.cpp:398:1:398:1 | m5 | | +| map.cpp:254:57:254:58 | call to unordered_map | map.cpp:261:7:261:8 | m6 | | +| map.cpp:254:57:254:58 | call to unordered_map | map.cpp:261:27:261:28 | m6 | | +| map.cpp:254:57:254:58 | call to unordered_map | map.cpp:267:7:267:8 | m6 | | +| map.cpp:254:57:254:58 | call to unordered_map | map.cpp:273:7:273:8 | m6 | | +| map.cpp:254:57:254:58 | call to unordered_map | map.cpp:279:7:279:8 | m6 | | +| map.cpp:254:57:254:58 | call to unordered_map | map.cpp:398:1:398:1 | m6 | | +| map.cpp:256:7:256:8 | ref arg m1 | map.cpp:262:7:262:8 | m1 | | +| map.cpp:256:7:256:8 | ref arg m1 | map.cpp:268:7:268:8 | m1 | | +| map.cpp:256:7:256:8 | ref arg m1 | map.cpp:274:7:274:8 | m1 | | +| map.cpp:256:7:256:8 | ref arg m1 | map.cpp:295:12:295:13 | m1 | | +| map.cpp:256:7:256:8 | ref arg m1 | map.cpp:295:30:295:31 | m1 | | +| map.cpp:256:7:256:8 | ref arg m1 | map.cpp:398:1:398:1 | m1 | | +| map.cpp:256:17:256:30 | call to make_pair | map.cpp:256:17:256:44 | call to pair | TAINT | +| map.cpp:256:47:256:51 | first | map.cpp:256:7:256:51 | call to iterator | | +| map.cpp:257:7:257:8 | ref arg m2 | map.cpp:263:7:263:8 | m2 | | +| map.cpp:257:7:257:8 | ref arg m2 | map.cpp:269:7:269:8 | m2 | | +| map.cpp:257:7:257:8 | ref arg m2 | map.cpp:275:7:275:8 | m2 | | +| map.cpp:257:7:257:8 | ref arg m2 | map.cpp:282:40:282:41 | m2 | | +| map.cpp:257:7:257:8 | ref arg m2 | map.cpp:283:42:283:43 | m2 | | +| map.cpp:257:7:257:8 | ref arg m2 | map.cpp:285:7:285:8 | m2 | | +| map.cpp:257:7:257:8 | ref arg m2 | map.cpp:301:12:301:13 | m2 | | +| map.cpp:257:7:257:8 | ref arg m2 | map.cpp:301:30:301:31 | m2 | | +| map.cpp:257:7:257:8 | ref arg m2 | map.cpp:331:7:331:8 | m2 | | +| map.cpp:257:7:257:8 | ref arg m2 | map.cpp:332:7:332:8 | m2 | | +| map.cpp:257:7:257:8 | ref arg m2 | map.cpp:333:7:333:8 | m2 | | +| map.cpp:257:7:257:8 | ref arg m2 | map.cpp:398:1:398:1 | m2 | | +| map.cpp:257:17:257:30 | call to make_pair | map.cpp:257:17:257:47 | call to pair | TAINT | +| map.cpp:257:50:257:54 | first | map.cpp:257:7:257:54 | call to iterator | | +| map.cpp:258:7:258:8 | ref arg m3 | map.cpp:264:7:264:8 | m3 | | +| map.cpp:258:7:258:8 | ref arg m3 | map.cpp:270:7:270:8 | m3 | | +| map.cpp:258:7:258:8 | ref arg m3 | map.cpp:276:7:276:8 | m3 | | +| map.cpp:258:7:258:8 | ref arg m3 | map.cpp:307:12:307:13 | m3 | | +| map.cpp:258:7:258:8 | ref arg m3 | map.cpp:307:30:307:31 | m3 | | +| map.cpp:258:7:258:8 | ref arg m3 | map.cpp:398:1:398:1 | m3 | | +| map.cpp:258:17:258:30 | call to make_pair | map.cpp:258:17:258:47 | call to pair | TAINT | +| map.cpp:258:50:258:54 | first | map.cpp:258:7:258:54 | call to iterator | | +| map.cpp:259:7:259:8 | ref arg m4 | map.cpp:265:7:265:8 | m4 | | +| map.cpp:259:7:259:8 | ref arg m4 | map.cpp:271:7:271:8 | m4 | | +| map.cpp:259:7:259:8 | ref arg m4 | map.cpp:277:7:277:8 | m4 | | +| map.cpp:259:7:259:8 | ref arg m4 | map.cpp:398:1:398:1 | m4 | | +| map.cpp:259:17:259:18 | ref arg m4 | map.cpp:259:7:259:8 | m4 | | +| map.cpp:259:17:259:18 | ref arg m4 | map.cpp:265:7:265:8 | m4 | | +| map.cpp:259:17:259:18 | ref arg m4 | map.cpp:271:7:271:8 | m4 | | +| map.cpp:259:17:259:18 | ref arg m4 | map.cpp:277:7:277:8 | m4 | | +| map.cpp:259:17:259:18 | ref arg m4 | map.cpp:398:1:398:1 | m4 | | +| map.cpp:259:20:259:24 | call to begin | map.cpp:259:17:259:26 | call to iterator | TAINT | +| map.cpp:259:29:259:70 | call to pair | map.cpp:259:29:259:70 | call to pair | TAINT | +| map.cpp:260:7:260:8 | ref arg m5 | map.cpp:266:7:266:8 | m5 | | +| map.cpp:260:7:260:8 | ref arg m5 | map.cpp:272:7:272:8 | m5 | | +| map.cpp:260:7:260:8 | ref arg m5 | map.cpp:278:7:278:8 | m5 | | +| map.cpp:260:7:260:8 | ref arg m5 | map.cpp:398:1:398:1 | m5 | | +| map.cpp:260:44:260:48 | first | map.cpp:260:7:260:48 | call to iterator | | +| map.cpp:261:7:261:8 | ref arg m6 | map.cpp:267:7:267:8 | m6 | | +| map.cpp:261:7:261:8 | ref arg m6 | map.cpp:273:7:273:8 | m6 | | +| map.cpp:261:7:261:8 | ref arg m6 | map.cpp:279:7:279:8 | m6 | | +| map.cpp:261:7:261:8 | ref arg m6 | map.cpp:398:1:398:1 | m6 | | +| map.cpp:261:27:261:28 | ref arg m6 | map.cpp:261:7:261:8 | m6 | | +| map.cpp:261:27:261:28 | ref arg m6 | map.cpp:267:7:267:8 | m6 | | +| map.cpp:261:27:261:28 | ref arg m6 | map.cpp:273:7:273:8 | m6 | | +| map.cpp:261:27:261:28 | ref arg m6 | map.cpp:279:7:279:8 | m6 | | +| map.cpp:261:27:261:28 | ref arg m6 | map.cpp:398:1:398:1 | m6 | | +| map.cpp:261:30:261:34 | call to begin | map.cpp:261:27:261:36 | call to iterator | TAINT | +| map.cpp:262:7:262:8 | m1 | map.cpp:262:7:262:8 | call to unordered_map | | +| map.cpp:263:7:263:8 | m2 | map.cpp:263:7:263:8 | call to unordered_map | | +| map.cpp:264:7:264:8 | m3 | map.cpp:264:7:264:8 | call to unordered_map | | +| map.cpp:265:7:265:8 | m4 | map.cpp:265:7:265:8 | call to unordered_map | | +| map.cpp:266:7:266:8 | m5 | map.cpp:266:7:266:8 | call to unordered_map | | +| map.cpp:267:7:267:8 | m6 | map.cpp:267:7:267:8 | call to unordered_map | | +| map.cpp:268:7:268:8 | ref arg m1 | map.cpp:274:7:274:8 | m1 | | +| map.cpp:268:7:268:8 | ref arg m1 | map.cpp:295:12:295:13 | m1 | | +| map.cpp:268:7:268:8 | ref arg m1 | map.cpp:295:30:295:31 | m1 | | +| map.cpp:268:7:268:8 | ref arg m1 | map.cpp:398:1:398:1 | m1 | | +| map.cpp:269:7:269:8 | ref arg m2 | map.cpp:275:7:275:8 | m2 | | +| map.cpp:269:7:269:8 | ref arg m2 | map.cpp:282:40:282:41 | m2 | | +| map.cpp:269:7:269:8 | ref arg m2 | map.cpp:283:42:283:43 | m2 | | +| map.cpp:269:7:269:8 | ref arg m2 | map.cpp:285:7:285:8 | m2 | | +| map.cpp:269:7:269:8 | ref arg m2 | map.cpp:301:12:301:13 | m2 | | +| map.cpp:269:7:269:8 | ref arg m2 | map.cpp:301:30:301:31 | m2 | | +| map.cpp:269:7:269:8 | ref arg m2 | map.cpp:331:7:331:8 | m2 | | +| map.cpp:269:7:269:8 | ref arg m2 | map.cpp:332:7:332:8 | m2 | | +| map.cpp:269:7:269:8 | ref arg m2 | map.cpp:333:7:333:8 | m2 | | +| map.cpp:269:7:269:8 | ref arg m2 | map.cpp:398:1:398:1 | m2 | | +| map.cpp:270:7:270:8 | ref arg m3 | map.cpp:276:7:276:8 | m3 | | +| map.cpp:270:7:270:8 | ref arg m3 | map.cpp:307:12:307:13 | m3 | | +| map.cpp:270:7:270:8 | ref arg m3 | map.cpp:307:30:307:31 | m3 | | +| map.cpp:270:7:270:8 | ref arg m3 | map.cpp:398:1:398:1 | m3 | | +| map.cpp:271:7:271:8 | ref arg m4 | map.cpp:277:7:277:8 | m4 | | +| map.cpp:271:7:271:8 | ref arg m4 | map.cpp:398:1:398:1 | m4 | | +| map.cpp:272:7:272:8 | ref arg m5 | map.cpp:278:7:278:8 | m5 | | +| map.cpp:272:7:272:8 | ref arg m5 | map.cpp:398:1:398:1 | m5 | | +| map.cpp:273:7:273:8 | ref arg m6 | map.cpp:279:7:279:8 | m6 | | +| map.cpp:273:7:273:8 | ref arg m6 | map.cpp:398:1:398:1 | m6 | | +| map.cpp:274:7:274:8 | ref arg m1 | map.cpp:295:12:295:13 | m1 | | +| map.cpp:274:7:274:8 | ref arg m1 | map.cpp:295:30:295:31 | m1 | | +| map.cpp:274:7:274:8 | ref arg m1 | map.cpp:398:1:398:1 | m1 | | +| map.cpp:275:7:275:8 | ref arg m2 | map.cpp:282:40:282:41 | m2 | | +| map.cpp:275:7:275:8 | ref arg m2 | map.cpp:283:42:283:43 | m2 | | +| map.cpp:275:7:275:8 | ref arg m2 | map.cpp:285:7:285:8 | m2 | | +| map.cpp:275:7:275:8 | ref arg m2 | map.cpp:301:12:301:13 | m2 | | +| map.cpp:275:7:275:8 | ref arg m2 | map.cpp:301:30:301:31 | m2 | | +| map.cpp:275:7:275:8 | ref arg m2 | map.cpp:331:7:331:8 | m2 | | +| map.cpp:275:7:275:8 | ref arg m2 | map.cpp:332:7:332:8 | m2 | | +| map.cpp:275:7:275:8 | ref arg m2 | map.cpp:333:7:333:8 | m2 | | +| map.cpp:275:7:275:8 | ref arg m2 | map.cpp:398:1:398:1 | m2 | | +| map.cpp:276:7:276:8 | ref arg m3 | map.cpp:307:12:307:13 | m3 | | +| map.cpp:276:7:276:8 | ref arg m3 | map.cpp:307:30:307:31 | m3 | | +| map.cpp:276:7:276:8 | ref arg m3 | map.cpp:398:1:398:1 | m3 | | +| map.cpp:277:7:277:8 | ref arg m4 | map.cpp:398:1:398:1 | m4 | | +| map.cpp:278:7:278:8 | ref arg m5 | map.cpp:398:1:398:1 | m5 | | +| map.cpp:279:7:279:8 | ref arg m6 | map.cpp:398:1:398:1 | m6 | | +| map.cpp:282:40:282:41 | m2 | map.cpp:282:40:282:42 | call to unordered_map | | +| map.cpp:282:40:282:42 | call to unordered_map | map.cpp:286:7:286:8 | m7 | | +| map.cpp:282:40:282:42 | call to unordered_map | map.cpp:289:7:289:8 | m7 | | +| map.cpp:282:40:282:42 | call to unordered_map | map.cpp:398:1:398:1 | m7 | | +| map.cpp:283:41:283:43 | call to unordered_map | map.cpp:287:7:287:8 | m8 | | +| map.cpp:283:41:283:43 | call to unordered_map | map.cpp:290:7:290:8 | m8 | | +| map.cpp:283:41:283:43 | call to unordered_map | map.cpp:398:1:398:1 | m8 | | +| map.cpp:283:42:283:43 | m2 | map.cpp:283:41:283:43 | call to unordered_map | | +| map.cpp:284:37:284:38 | call to unordered_map | map.cpp:285:2:285:3 | m9 | | +| map.cpp:284:37:284:38 | call to unordered_map | map.cpp:288:7:288:8 | m9 | | +| map.cpp:284:37:284:38 | call to unordered_map | map.cpp:291:7:291:8 | m9 | | +| map.cpp:284:37:284:38 | call to unordered_map | map.cpp:398:1:398:1 | m9 | | +| map.cpp:285:2:285:3 | ref arg m9 | map.cpp:288:7:288:8 | m9 | | +| map.cpp:285:2:285:3 | ref arg m9 | map.cpp:291:7:291:8 | m9 | | +| map.cpp:285:2:285:3 | ref arg m9 | map.cpp:398:1:398:1 | m9 | | +| map.cpp:285:7:285:8 | m2 | map.cpp:285:2:285:3 | ref arg m9 | TAINT | +| map.cpp:285:7:285:8 | m2 | map.cpp:285:5:285:5 | call to operator= | TAINT | +| map.cpp:286:7:286:8 | m7 | map.cpp:286:7:286:8 | call to unordered_map | | +| map.cpp:287:7:287:8 | m8 | map.cpp:287:7:287:8 | call to unordered_map | | +| map.cpp:288:7:288:8 | m9 | map.cpp:288:7:288:8 | call to unordered_map | | +| map.cpp:289:7:289:8 | ref arg m7 | map.cpp:398:1:398:1 | m7 | | +| map.cpp:290:7:290:8 | ref arg m8 | map.cpp:398:1:398:1 | m8 | | +| map.cpp:291:7:291:8 | ref arg m9 | map.cpp:398:1:398:1 | m9 | | +| map.cpp:295:12:295:13 | ref arg m1 | map.cpp:295:30:295:31 | m1 | | +| map.cpp:295:12:295:13 | ref arg m1 | map.cpp:398:1:398:1 | m1 | | +| map.cpp:295:15:295:19 | call to begin | map.cpp:295:7:295:21 | ... = ... | | +| map.cpp:295:15:295:19 | call to begin | map.cpp:295:24:295:25 | i1 | | +| map.cpp:295:15:295:19 | call to begin | map.cpp:295:40:295:41 | i1 | | +| map.cpp:295:15:295:19 | call to begin | map.cpp:297:9:297:10 | i1 | | +| map.cpp:295:15:295:19 | call to begin | map.cpp:298:8:298:9 | i1 | | +| map.cpp:295:15:295:19 | call to begin | map.cpp:299:8:299:9 | i1 | | +| map.cpp:295:30:295:31 | ref arg m1 | map.cpp:295:30:295:31 | m1 | | +| map.cpp:295:30:295:31 | ref arg m1 | map.cpp:398:1:398:1 | m1 | | +| map.cpp:295:40:295:41 | i1 | map.cpp:295:42:295:42 | call to operator++ | | +| map.cpp:295:40:295:41 | ref arg i1 | map.cpp:295:24:295:25 | i1 | | +| map.cpp:295:40:295:41 | ref arg i1 | map.cpp:295:40:295:41 | i1 | | +| map.cpp:295:40:295:41 | ref arg i1 | map.cpp:297:9:297:10 | i1 | | +| map.cpp:295:40:295:41 | ref arg i1 | map.cpp:298:8:298:9 | i1 | | +| map.cpp:295:40:295:41 | ref arg i1 | map.cpp:299:8:299:9 | i1 | | +| map.cpp:297:8:297:8 | call to operator* | map.cpp:297:8:297:10 | call to pair | TAINT | +| map.cpp:297:9:297:10 | i1 | map.cpp:297:8:297:8 | call to operator* | TAINT | +| map.cpp:298:8:298:9 | i1 | map.cpp:298:10:298:10 | call to operator-> | TAINT | +| map.cpp:299:8:299:9 | i1 | map.cpp:299:10:299:10 | call to operator-> | TAINT | +| map.cpp:301:12:301:13 | ref arg m2 | map.cpp:301:30:301:31 | m2 | | +| map.cpp:301:12:301:13 | ref arg m2 | map.cpp:331:7:331:8 | m2 | | +| map.cpp:301:12:301:13 | ref arg m2 | map.cpp:332:7:332:8 | m2 | | +| map.cpp:301:12:301:13 | ref arg m2 | map.cpp:333:7:333:8 | m2 | | +| map.cpp:301:12:301:13 | ref arg m2 | map.cpp:398:1:398:1 | m2 | | +| map.cpp:301:15:301:19 | call to begin | map.cpp:301:7:301:21 | ... = ... | | +| map.cpp:301:15:301:19 | call to begin | map.cpp:301:24:301:25 | i2 | | +| map.cpp:301:15:301:19 | call to begin | map.cpp:301:40:301:41 | i2 | | +| map.cpp:301:15:301:19 | call to begin | map.cpp:303:9:303:10 | i2 | | +| map.cpp:301:15:301:19 | call to begin | map.cpp:304:8:304:9 | i2 | | +| map.cpp:301:15:301:19 | call to begin | map.cpp:305:8:305:9 | i2 | | +| map.cpp:301:15:301:19 | call to begin | map.cpp:310:8:310:9 | i2 | | +| map.cpp:301:15:301:19 | call to begin | map.cpp:311:8:311:9 | i2 | | +| map.cpp:301:30:301:31 | ref arg m2 | map.cpp:301:30:301:31 | m2 | | +| map.cpp:301:30:301:31 | ref arg m2 | map.cpp:331:7:331:8 | m2 | | +| map.cpp:301:30:301:31 | ref arg m2 | map.cpp:332:7:332:8 | m2 | | +| map.cpp:301:30:301:31 | ref arg m2 | map.cpp:333:7:333:8 | m2 | | +| map.cpp:301:30:301:31 | ref arg m2 | map.cpp:398:1:398:1 | m2 | | +| map.cpp:301:40:301:41 | i2 | map.cpp:301:42:301:42 | call to operator++ | | +| map.cpp:301:40:301:41 | ref arg i2 | map.cpp:301:24:301:25 | i2 | | +| map.cpp:301:40:301:41 | ref arg i2 | map.cpp:301:40:301:41 | i2 | | +| map.cpp:301:40:301:41 | ref arg i2 | map.cpp:303:9:303:10 | i2 | | +| map.cpp:301:40:301:41 | ref arg i2 | map.cpp:304:8:304:9 | i2 | | +| map.cpp:301:40:301:41 | ref arg i2 | map.cpp:305:8:305:9 | i2 | | +| map.cpp:301:40:301:41 | ref arg i2 | map.cpp:310:8:310:9 | i2 | | +| map.cpp:301:40:301:41 | ref arg i2 | map.cpp:311:8:311:9 | i2 | | +| map.cpp:303:8:303:8 | call to operator* | map.cpp:303:8:303:10 | call to pair | TAINT | +| map.cpp:303:9:303:10 | i2 | map.cpp:303:8:303:8 | call to operator* | TAINT | +| map.cpp:304:8:304:9 | i2 | map.cpp:304:10:304:10 | call to operator-> | TAINT | +| map.cpp:305:8:305:9 | i2 | map.cpp:305:10:305:10 | call to operator-> | TAINT | +| map.cpp:307:12:307:13 | ref arg m3 | map.cpp:307:30:307:31 | m3 | | +| map.cpp:307:12:307:13 | ref arg m3 | map.cpp:398:1:398:1 | m3 | | +| map.cpp:307:15:307:19 | call to begin | map.cpp:307:7:307:21 | ... = ... | | +| map.cpp:307:15:307:19 | call to begin | map.cpp:307:24:307:25 | i3 | | +| map.cpp:307:15:307:19 | call to begin | map.cpp:307:40:307:41 | i3 | | +| map.cpp:307:15:307:19 | call to begin | map.cpp:309:9:309:10 | i3 | | +| map.cpp:307:30:307:31 | ref arg m3 | map.cpp:307:30:307:31 | m3 | | +| map.cpp:307:30:307:31 | ref arg m3 | map.cpp:398:1:398:1 | m3 | | +| map.cpp:307:40:307:41 | i3 | map.cpp:307:42:307:42 | call to operator++ | | +| map.cpp:307:40:307:41 | ref arg i3 | map.cpp:307:24:307:25 | i3 | | +| map.cpp:307:40:307:41 | ref arg i3 | map.cpp:307:40:307:41 | i3 | | +| map.cpp:307:40:307:41 | ref arg i3 | map.cpp:309:9:309:10 | i3 | | +| map.cpp:309:8:309:8 | call to operator* | map.cpp:309:8:309:10 | call to pair | TAINT | +| map.cpp:309:9:309:10 | i3 | map.cpp:309:8:309:8 | call to operator* | TAINT | +| map.cpp:310:8:310:9 | i2 | map.cpp:310:10:310:10 | call to operator-> | TAINT | +| map.cpp:311:8:311:9 | i2 | map.cpp:311:10:311:10 | call to operator-> | TAINT | +| map.cpp:315:37:315:39 | call to unordered_map | map.cpp:316:7:316:9 | m10 | | +| map.cpp:315:37:315:39 | call to unordered_map | map.cpp:320:7:320:9 | m10 | | +| map.cpp:315:37:315:39 | call to unordered_map | map.cpp:398:1:398:1 | m10 | | +| map.cpp:315:42:315:44 | call to unordered_map | map.cpp:317:7:317:9 | m11 | | +| map.cpp:315:42:315:44 | call to unordered_map | map.cpp:321:7:321:9 | m11 | | +| map.cpp:315:42:315:44 | call to unordered_map | map.cpp:398:1:398:1 | m11 | | +| map.cpp:315:47:315:49 | call to unordered_map | map.cpp:318:7:318:9 | m12 | | +| map.cpp:315:47:315:49 | call to unordered_map | map.cpp:322:7:322:9 | m12 | | +| map.cpp:315:47:315:49 | call to unordered_map | map.cpp:398:1:398:1 | m12 | | +| map.cpp:315:52:315:54 | call to unordered_map | map.cpp:319:7:319:9 | m13 | | +| map.cpp:315:52:315:54 | call to unordered_map | map.cpp:323:7:323:9 | m13 | | +| map.cpp:315:52:315:54 | call to unordered_map | map.cpp:398:1:398:1 | m13 | | +| map.cpp:316:7:316:9 | ref arg m10 | map.cpp:320:7:320:9 | m10 | | +| map.cpp:316:7:316:9 | ref arg m10 | map.cpp:398:1:398:1 | m10 | | +| map.cpp:316:7:316:24 | ... = ... | map.cpp:316:10:316:10 | call to operator[] [post update] | | +| map.cpp:316:20:316:24 | def | map.cpp:316:7:316:24 | ... = ... | | +| map.cpp:317:7:317:9 | ref arg m11 | map.cpp:321:7:321:9 | m11 | | +| map.cpp:317:7:317:9 | ref arg m11 | map.cpp:398:1:398:1 | m11 | | +| map.cpp:317:7:317:27 | ... = ... | map.cpp:317:10:317:10 | call to operator[] [post update] | | +| map.cpp:317:20:317:25 | call to source | map.cpp:317:7:317:27 | ... = ... | | +| map.cpp:318:7:318:9 | ref arg m12 | map.cpp:322:7:322:9 | m12 | | +| map.cpp:318:7:318:9 | ref arg m12 | map.cpp:398:1:398:1 | m12 | | +| map.cpp:318:7:318:27 | ... = ... | map.cpp:318:11:318:12 | call to at [post update] | | +| map.cpp:318:23:318:27 | def | map.cpp:318:7:318:27 | ... = ... | | +| map.cpp:319:7:319:9 | ref arg m13 | map.cpp:323:7:323:9 | m13 | | +| map.cpp:319:7:319:9 | ref arg m13 | map.cpp:398:1:398:1 | m13 | | +| map.cpp:319:7:319:30 | ... = ... | map.cpp:319:11:319:12 | call to at [post update] | | +| map.cpp:319:23:319:28 | call to source | map.cpp:319:7:319:30 | ... = ... | | +| map.cpp:320:7:320:9 | ref arg m10 | map.cpp:398:1:398:1 | m10 | | +| map.cpp:321:7:321:9 | ref arg m11 | map.cpp:398:1:398:1 | m11 | | +| map.cpp:322:7:322:9 | ref arg m12 | map.cpp:398:1:398:1 | m12 | | +| map.cpp:323:7:323:9 | ref arg m13 | map.cpp:398:1:398:1 | m13 | | +| map.cpp:326:37:326:39 | call to unordered_map | map.cpp:327:2:327:4 | m14 | | +| map.cpp:326:37:326:39 | call to unordered_map | map.cpp:328:2:328:4 | m14 | | +| map.cpp:326:37:326:39 | call to unordered_map | map.cpp:329:2:329:4 | m14 | | +| map.cpp:326:37:326:39 | call to unordered_map | map.cpp:330:2:330:4 | m14 | | +| map.cpp:326:37:326:39 | call to unordered_map | map.cpp:398:1:398:1 | m14 | | +| map.cpp:327:2:327:4 | ref arg m14 | map.cpp:328:2:328:4 | m14 | | +| map.cpp:327:2:327:4 | ref arg m14 | map.cpp:329:2:329:4 | m14 | | +| map.cpp:327:2:327:4 | ref arg m14 | map.cpp:330:2:330:4 | m14 | | +| map.cpp:327:2:327:4 | ref arg m14 | map.cpp:398:1:398:1 | m14 | | +| map.cpp:327:13:327:26 | call to make_pair | map.cpp:327:13:327:36 | call to pair | TAINT | +| map.cpp:328:2:328:4 | ref arg m14 | map.cpp:329:2:329:4 | m14 | | +| map.cpp:328:2:328:4 | ref arg m14 | map.cpp:330:2:330:4 | m14 | | +| map.cpp:328:2:328:4 | ref arg m14 | map.cpp:398:1:398:1 | m14 | | +| map.cpp:328:13:328:26 | call to make_pair | map.cpp:328:13:328:41 | call to pair | TAINT | +| map.cpp:329:2:329:4 | ref arg m14 | map.cpp:330:2:330:4 | m14 | | +| map.cpp:329:2:329:4 | ref arg m14 | map.cpp:398:1:398:1 | m14 | | +| map.cpp:329:13:329:26 | call to make_pair | map.cpp:329:13:329:41 | call to pair | TAINT | +| map.cpp:330:2:330:4 | ref arg m14 | map.cpp:398:1:398:1 | m14 | | +| map.cpp:330:13:330:26 | call to make_pair | map.cpp:330:13:330:36 | call to pair | TAINT | +| map.cpp:331:7:331:8 | ref arg m2 | map.cpp:332:7:332:8 | m2 | | +| map.cpp:331:7:331:8 | ref arg m2 | map.cpp:333:7:333:8 | m2 | | +| map.cpp:331:7:331:8 | ref arg m2 | map.cpp:398:1:398:1 | m2 | | +| map.cpp:331:27:331:31 | first | map.cpp:331:7:331:31 | call to iterator | | +| map.cpp:332:7:332:8 | ref arg m2 | map.cpp:333:7:333:8 | m2 | | +| map.cpp:332:7:332:8 | ref arg m2 | map.cpp:398:1:398:1 | m2 | | +| map.cpp:332:27:332:32 | second | map.cpp:332:7:332:32 | call to iterator | | +| map.cpp:333:7:333:8 | ref arg m2 | map.cpp:398:1:398:1 | m2 | | +| map.cpp:333:27:333:32 | second | map.cpp:333:7:333:32 | call to iterator | | +| map.cpp:336:37:336:39 | call to unordered_map | map.cpp:337:2:337:4 | m15 | | +| map.cpp:336:37:336:39 | call to unordered_map | map.cpp:339:7:339:9 | m15 | | +| map.cpp:336:37:336:39 | call to unordered_map | map.cpp:343:2:343:4 | m15 | | +| map.cpp:336:37:336:39 | call to unordered_map | map.cpp:345:7:345:9 | m15 | | +| map.cpp:336:37:336:39 | call to unordered_map | map.cpp:360:2:360:4 | m15 | | +| map.cpp:336:37:336:39 | call to unordered_map | map.cpp:398:1:398:1 | m15 | | +| map.cpp:336:42:336:44 | call to unordered_map | map.cpp:340:7:340:9 | m16 | | +| map.cpp:336:42:336:44 | call to unordered_map | map.cpp:343:11:343:13 | m16 | | +| map.cpp:336:42:336:44 | call to unordered_map | map.cpp:346:7:346:9 | m16 | | +| map.cpp:336:42:336:44 | call to unordered_map | map.cpp:360:12:360:14 | m16 | | +| map.cpp:336:42:336:44 | call to unordered_map | map.cpp:398:1:398:1 | m16 | | +| map.cpp:336:47:336:49 | call to unordered_map | map.cpp:341:7:341:9 | m17 | | +| map.cpp:336:47:336:49 | call to unordered_map | map.cpp:344:2:344:4 | m17 | | +| map.cpp:336:47:336:49 | call to unordered_map | map.cpp:347:7:347:9 | m17 | | +| map.cpp:336:47:336:49 | call to unordered_map | map.cpp:361:2:361:4 | m17 | | +| map.cpp:336:47:336:49 | call to unordered_map | map.cpp:398:1:398:1 | m17 | | +| map.cpp:336:52:336:54 | call to unordered_map | map.cpp:338:2:338:4 | m18 | | +| map.cpp:336:52:336:54 | call to unordered_map | map.cpp:342:7:342:9 | m18 | | +| map.cpp:336:52:336:54 | call to unordered_map | map.cpp:344:11:344:13 | m18 | | +| map.cpp:336:52:336:54 | call to unordered_map | map.cpp:348:7:348:9 | m18 | | +| map.cpp:336:52:336:54 | call to unordered_map | map.cpp:361:12:361:14 | m18 | | +| map.cpp:336:52:336:54 | call to unordered_map | map.cpp:398:1:398:1 | m18 | | +| map.cpp:337:2:337:4 | ref arg m15 | map.cpp:339:7:339:9 | m15 | | +| map.cpp:337:2:337:4 | ref arg m15 | map.cpp:343:2:343:4 | m15 | | +| map.cpp:337:2:337:4 | ref arg m15 | map.cpp:345:7:345:9 | m15 | | +| map.cpp:337:2:337:4 | ref arg m15 | map.cpp:360:2:360:4 | m15 | | +| map.cpp:337:2:337:4 | ref arg m15 | map.cpp:398:1:398:1 | m15 | | +| map.cpp:337:13:337:57 | call to pair | map.cpp:337:13:337:57 | call to pair | TAINT | +| map.cpp:338:2:338:4 | ref arg m18 | map.cpp:342:7:342:9 | m18 | | +| map.cpp:338:2:338:4 | ref arg m18 | map.cpp:344:11:344:13 | m18 | | +| map.cpp:338:2:338:4 | ref arg m18 | map.cpp:348:7:348:9 | m18 | | +| map.cpp:338:2:338:4 | ref arg m18 | map.cpp:361:12:361:14 | m18 | | +| map.cpp:338:2:338:4 | ref arg m18 | map.cpp:398:1:398:1 | m18 | | +| map.cpp:338:13:338:57 | call to pair | map.cpp:338:13:338:57 | call to pair | TAINT | +| map.cpp:339:7:339:9 | m15 | map.cpp:339:7:339:9 | call to unordered_map | | +| map.cpp:340:7:340:9 | m16 | map.cpp:340:7:340:9 | call to unordered_map | | +| map.cpp:341:7:341:9 | m17 | map.cpp:341:7:341:9 | call to unordered_map | | +| map.cpp:342:7:342:9 | m18 | map.cpp:342:7:342:9 | call to unordered_map | | +| map.cpp:343:2:343:4 | ref arg m15 | map.cpp:345:7:345:9 | m15 | | +| map.cpp:343:2:343:4 | ref arg m15 | map.cpp:360:2:360:4 | m15 | | +| map.cpp:343:2:343:4 | ref arg m15 | map.cpp:398:1:398:1 | m15 | | +| map.cpp:343:11:343:13 | ref arg m16 | map.cpp:346:7:346:9 | m16 | | +| map.cpp:343:11:343:13 | ref arg m16 | map.cpp:360:12:360:14 | m16 | | +| map.cpp:343:11:343:13 | ref arg m16 | map.cpp:398:1:398:1 | m16 | | +| map.cpp:344:2:344:4 | ref arg m17 | map.cpp:347:7:347:9 | m17 | | +| map.cpp:344:2:344:4 | ref arg m17 | map.cpp:361:2:361:4 | m17 | | +| map.cpp:344:2:344:4 | ref arg m17 | map.cpp:398:1:398:1 | m17 | | +| map.cpp:344:11:344:13 | ref arg m18 | map.cpp:348:7:348:9 | m18 | | +| map.cpp:344:11:344:13 | ref arg m18 | map.cpp:361:12:361:14 | m18 | | +| map.cpp:344:11:344:13 | ref arg m18 | map.cpp:398:1:398:1 | m18 | | +| map.cpp:345:7:345:9 | m15 | map.cpp:345:7:345:9 | call to unordered_map | | +| map.cpp:346:7:346:9 | m16 | map.cpp:346:7:346:9 | call to unordered_map | | +| map.cpp:347:7:347:9 | m17 | map.cpp:347:7:347:9 | call to unordered_map | | +| map.cpp:348:7:348:9 | m18 | map.cpp:348:7:348:9 | call to unordered_map | | +| map.cpp:351:37:351:39 | call to unordered_map | map.cpp:352:2:352:4 | m19 | | +| map.cpp:351:37:351:39 | call to unordered_map | map.cpp:356:7:356:9 | m19 | | +| map.cpp:351:37:351:39 | call to unordered_map | map.cpp:362:7:362:9 | m19 | | +| map.cpp:351:37:351:39 | call to unordered_map | map.cpp:398:1:398:1 | m19 | | +| map.cpp:351:42:351:44 | call to unordered_map | map.cpp:353:2:353:4 | m20 | | +| map.cpp:351:42:351:44 | call to unordered_map | map.cpp:357:7:357:9 | m20 | | +| map.cpp:351:42:351:44 | call to unordered_map | map.cpp:363:7:363:9 | m20 | | +| map.cpp:351:42:351:44 | call to unordered_map | map.cpp:398:1:398:1 | m20 | | +| map.cpp:351:47:351:49 | call to unordered_map | map.cpp:354:2:354:4 | m21 | | +| map.cpp:351:47:351:49 | call to unordered_map | map.cpp:358:7:358:9 | m21 | | +| map.cpp:351:47:351:49 | call to unordered_map | map.cpp:364:7:364:9 | m21 | | +| map.cpp:351:47:351:49 | call to unordered_map | map.cpp:398:1:398:1 | m21 | | +| map.cpp:351:52:351:54 | call to unordered_map | map.cpp:355:2:355:4 | m22 | | +| map.cpp:351:52:351:54 | call to unordered_map | map.cpp:359:7:359:9 | m22 | | +| map.cpp:351:52:351:54 | call to unordered_map | map.cpp:365:7:365:9 | m22 | | +| map.cpp:351:52:351:54 | call to unordered_map | map.cpp:398:1:398:1 | m22 | | +| map.cpp:352:2:352:4 | ref arg m19 | map.cpp:356:7:356:9 | m19 | | +| map.cpp:352:2:352:4 | ref arg m19 | map.cpp:362:7:362:9 | m19 | | +| map.cpp:352:2:352:4 | ref arg m19 | map.cpp:398:1:398:1 | m19 | | +| map.cpp:352:13:352:57 | call to pair | map.cpp:352:13:352:57 | call to pair | TAINT | +| map.cpp:353:2:353:4 | ref arg m20 | map.cpp:357:7:357:9 | m20 | | +| map.cpp:353:2:353:4 | ref arg m20 | map.cpp:363:7:363:9 | m20 | | +| map.cpp:353:2:353:4 | ref arg m20 | map.cpp:398:1:398:1 | m20 | | +| map.cpp:353:13:353:51 | call to pair | map.cpp:353:13:353:51 | call to pair | TAINT | +| map.cpp:354:2:354:4 | ref arg m21 | map.cpp:358:7:358:9 | m21 | | +| map.cpp:354:2:354:4 | ref arg m21 | map.cpp:364:7:364:9 | m21 | | +| map.cpp:354:2:354:4 | ref arg m21 | map.cpp:398:1:398:1 | m21 | | +| map.cpp:354:13:354:51 | call to pair | map.cpp:354:13:354:51 | call to pair | TAINT | +| map.cpp:355:2:355:4 | ref arg m22 | map.cpp:359:7:359:9 | m22 | | +| map.cpp:355:2:355:4 | ref arg m22 | map.cpp:365:7:365:9 | m22 | | +| map.cpp:355:2:355:4 | ref arg m22 | map.cpp:398:1:398:1 | m22 | | +| map.cpp:355:13:355:57 | call to pair | map.cpp:355:13:355:57 | call to pair | TAINT | +| map.cpp:356:7:356:9 | m19 | map.cpp:356:7:356:9 | call to unordered_map | | +| map.cpp:357:7:357:9 | m20 | map.cpp:357:7:357:9 | call to unordered_map | | +| map.cpp:358:7:358:9 | m21 | map.cpp:358:7:358:9 | call to unordered_map | | +| map.cpp:359:7:359:9 | m22 | map.cpp:359:7:359:9 | call to unordered_map | | +| map.cpp:360:2:360:4 | ref arg m15 | map.cpp:398:1:398:1 | m15 | | +| map.cpp:360:12:360:14 | ref arg m16 | map.cpp:398:1:398:1 | m16 | | +| map.cpp:361:2:361:4 | ref arg m17 | map.cpp:398:1:398:1 | m17 | | +| map.cpp:361:12:361:14 | ref arg m18 | map.cpp:398:1:398:1 | m18 | | +| map.cpp:362:7:362:9 | m19 | map.cpp:362:7:362:9 | call to unordered_map | | +| map.cpp:363:7:363:9 | m20 | map.cpp:363:7:363:9 | call to unordered_map | | +| map.cpp:364:7:364:9 | m21 | map.cpp:364:7:364:9 | call to unordered_map | | +| map.cpp:365:7:365:9 | m22 | map.cpp:365:7:365:9 | call to unordered_map | | +| map.cpp:368:37:368:39 | call to unordered_map | map.cpp:369:2:369:4 | m23 | | +| map.cpp:368:37:368:39 | call to unordered_map | map.cpp:370:2:370:4 | m23 | | +| map.cpp:368:37:368:39 | call to unordered_map | map.cpp:371:7:371:9 | m23 | | +| map.cpp:368:37:368:39 | call to unordered_map | map.cpp:372:7:372:9 | m23 | | +| map.cpp:368:37:368:39 | call to unordered_map | map.cpp:372:17:372:19 | m23 | | +| map.cpp:368:37:368:39 | call to unordered_map | map.cpp:373:7:373:9 | m23 | | +| map.cpp:368:37:368:39 | call to unordered_map | map.cpp:374:2:374:4 | m23 | | +| map.cpp:368:37:368:39 | call to unordered_map | map.cpp:375:7:375:9 | m23 | | +| map.cpp:368:37:368:39 | call to unordered_map | map.cpp:398:1:398:1 | m23 | | +| map.cpp:369:2:369:4 | ref arg m23 | map.cpp:370:2:370:4 | m23 | | +| map.cpp:369:2:369:4 | ref arg m23 | map.cpp:371:7:371:9 | m23 | | +| map.cpp:369:2:369:4 | ref arg m23 | map.cpp:372:7:372:9 | m23 | | +| map.cpp:369:2:369:4 | ref arg m23 | map.cpp:372:17:372:19 | m23 | | +| map.cpp:369:2:369:4 | ref arg m23 | map.cpp:373:7:373:9 | m23 | | +| map.cpp:369:2:369:4 | ref arg m23 | map.cpp:374:2:374:4 | m23 | | +| map.cpp:369:2:369:4 | ref arg m23 | map.cpp:375:7:375:9 | m23 | | +| map.cpp:369:2:369:4 | ref arg m23 | map.cpp:398:1:398:1 | m23 | | +| map.cpp:369:13:369:57 | call to pair | map.cpp:369:13:369:57 | call to pair | TAINT | +| map.cpp:370:2:370:4 | ref arg m23 | map.cpp:371:7:371:9 | m23 | | +| map.cpp:370:2:370:4 | ref arg m23 | map.cpp:372:7:372:9 | m23 | | +| map.cpp:370:2:370:4 | ref arg m23 | map.cpp:372:17:372:19 | m23 | | +| map.cpp:370:2:370:4 | ref arg m23 | map.cpp:373:7:373:9 | m23 | | +| map.cpp:370:2:370:4 | ref arg m23 | map.cpp:374:2:374:4 | m23 | | +| map.cpp:370:2:370:4 | ref arg m23 | map.cpp:375:7:375:9 | m23 | | +| map.cpp:370:2:370:4 | ref arg m23 | map.cpp:398:1:398:1 | m23 | | +| map.cpp:370:13:370:57 | call to pair | map.cpp:370:13:370:57 | call to pair | TAINT | +| map.cpp:371:7:371:9 | m23 | map.cpp:371:7:371:9 | call to unordered_map | | +| map.cpp:372:7:372:9 | ref arg m23 | map.cpp:373:7:373:9 | m23 | | +| map.cpp:372:7:372:9 | ref arg m23 | map.cpp:374:2:374:4 | m23 | | +| map.cpp:372:7:372:9 | ref arg m23 | map.cpp:375:7:375:9 | m23 | | +| map.cpp:372:7:372:9 | ref arg m23 | map.cpp:398:1:398:1 | m23 | | +| map.cpp:372:17:372:19 | ref arg m23 | map.cpp:372:7:372:9 | m23 | | +| map.cpp:372:17:372:19 | ref arg m23 | map.cpp:373:7:373:9 | m23 | | +| map.cpp:372:17:372:19 | ref arg m23 | map.cpp:374:2:374:4 | m23 | | +| map.cpp:372:17:372:19 | ref arg m23 | map.cpp:375:7:375:9 | m23 | | +| map.cpp:372:17:372:19 | ref arg m23 | map.cpp:398:1:398:1 | m23 | | +| map.cpp:373:7:373:9 | m23 | map.cpp:373:7:373:9 | call to unordered_map | | +| map.cpp:374:2:374:4 | ref arg m23 | map.cpp:375:7:375:9 | m23 | | +| map.cpp:374:2:374:4 | ref arg m23 | map.cpp:398:1:398:1 | m23 | | +| map.cpp:375:7:375:9 | m23 | map.cpp:375:7:375:9 | call to unordered_map | | +| map.cpp:378:37:378:39 | call to unordered_map | map.cpp:379:7:379:9 | m24 | | +| map.cpp:378:37:378:39 | call to unordered_map | map.cpp:380:7:380:9 | m24 | | +| map.cpp:378:37:378:39 | call to unordered_map | map.cpp:381:7:381:9 | m24 | | +| map.cpp:378:37:378:39 | call to unordered_map | map.cpp:382:7:382:9 | m24 | | +| map.cpp:378:37:378:39 | call to unordered_map | map.cpp:398:1:398:1 | m24 | | +| map.cpp:378:42:378:44 | call to unordered_map | map.cpp:383:7:383:9 | m25 | | +| map.cpp:378:42:378:44 | call to unordered_map | map.cpp:383:24:383:26 | m25 | | +| map.cpp:378:42:378:44 | call to unordered_map | map.cpp:384:7:384:9 | m25 | | +| map.cpp:378:42:378:44 | call to unordered_map | map.cpp:385:7:385:9 | m25 | | +| map.cpp:378:42:378:44 | call to unordered_map | map.cpp:385:24:385:26 | m25 | | +| map.cpp:378:42:378:44 | call to unordered_map | map.cpp:386:7:386:9 | m25 | | +| map.cpp:378:42:378:44 | call to unordered_map | map.cpp:398:1:398:1 | m25 | | +| map.cpp:379:7:379:9 | ref arg m24 | map.cpp:380:7:380:9 | m24 | | +| map.cpp:379:7:379:9 | ref arg m24 | map.cpp:381:7:381:9 | m24 | | +| map.cpp:379:7:379:9 | ref arg m24 | map.cpp:382:7:382:9 | m24 | | +| map.cpp:379:7:379:9 | ref arg m24 | map.cpp:398:1:398:1 | m24 | | +| map.cpp:379:33:379:37 | first | map.cpp:379:7:379:37 | call to iterator | | +| map.cpp:380:7:380:9 | m24 | map.cpp:380:7:380:9 | call to unordered_map | | +| map.cpp:381:7:381:9 | ref arg m24 | map.cpp:382:7:382:9 | m24 | | +| map.cpp:381:7:381:9 | ref arg m24 | map.cpp:398:1:398:1 | m24 | | +| map.cpp:381:36:381:40 | first | map.cpp:381:7:381:40 | call to iterator | | +| map.cpp:382:7:382:9 | m24 | map.cpp:382:7:382:9 | call to unordered_map | | +| map.cpp:383:7:383:9 | ref arg m25 | map.cpp:384:7:384:9 | m25 | | +| map.cpp:383:7:383:9 | ref arg m25 | map.cpp:385:7:385:9 | m25 | | +| map.cpp:383:7:383:9 | ref arg m25 | map.cpp:385:24:385:26 | m25 | | +| map.cpp:383:7:383:9 | ref arg m25 | map.cpp:386:7:386:9 | m25 | | +| map.cpp:383:7:383:9 | ref arg m25 | map.cpp:398:1:398:1 | m25 | | +| map.cpp:383:24:383:26 | ref arg m25 | map.cpp:383:7:383:9 | m25 | | +| map.cpp:383:24:383:26 | ref arg m25 | map.cpp:384:7:384:9 | m25 | | +| map.cpp:383:24:383:26 | ref arg m25 | map.cpp:385:7:385:9 | m25 | | +| map.cpp:383:24:383:26 | ref arg m25 | map.cpp:385:24:385:26 | m25 | | +| map.cpp:383:24:383:26 | ref arg m25 | map.cpp:386:7:386:9 | m25 | | +| map.cpp:383:24:383:26 | ref arg m25 | map.cpp:398:1:398:1 | m25 | | +| map.cpp:383:28:383:32 | call to begin | map.cpp:383:24:383:34 | call to iterator | TAINT | +| map.cpp:384:7:384:9 | m25 | map.cpp:384:7:384:9 | call to unordered_map | | +| map.cpp:385:7:385:9 | ref arg m25 | map.cpp:386:7:386:9 | m25 | | +| map.cpp:385:7:385:9 | ref arg m25 | map.cpp:398:1:398:1 | m25 | | +| map.cpp:385:24:385:26 | ref arg m25 | map.cpp:385:7:385:9 | m25 | | +| map.cpp:385:24:385:26 | ref arg m25 | map.cpp:386:7:386:9 | m25 | | +| map.cpp:385:24:385:26 | ref arg m25 | map.cpp:398:1:398:1 | m25 | | +| map.cpp:385:28:385:32 | call to begin | map.cpp:385:24:385:34 | call to iterator | TAINT | +| map.cpp:386:7:386:9 | m25 | map.cpp:386:7:386:9 | call to unordered_map | | +| map.cpp:389:37:389:39 | call to unordered_map | map.cpp:390:7:390:9 | m26 | | +| map.cpp:389:37:389:39 | call to unordered_map | map.cpp:391:7:391:9 | m26 | | +| map.cpp:389:37:389:39 | call to unordered_map | map.cpp:392:7:392:9 | m26 | | +| map.cpp:389:37:389:39 | call to unordered_map | map.cpp:393:7:393:9 | m26 | | +| map.cpp:389:37:389:39 | call to unordered_map | map.cpp:398:1:398:1 | m26 | | +| map.cpp:389:42:389:44 | call to unordered_map | map.cpp:394:7:394:9 | m27 | | +| map.cpp:389:42:389:44 | call to unordered_map | map.cpp:394:23:394:25 | m27 | | +| map.cpp:389:42:389:44 | call to unordered_map | map.cpp:395:7:395:9 | m27 | | +| map.cpp:389:42:389:44 | call to unordered_map | map.cpp:396:7:396:9 | m27 | | +| map.cpp:389:42:389:44 | call to unordered_map | map.cpp:396:23:396:25 | m27 | | +| map.cpp:389:42:389:44 | call to unordered_map | map.cpp:397:7:397:9 | m27 | | +| map.cpp:389:42:389:44 | call to unordered_map | map.cpp:398:1:398:1 | m27 | | +| map.cpp:390:7:390:9 | ref arg m26 | map.cpp:391:7:391:9 | m26 | | +| map.cpp:390:7:390:9 | ref arg m26 | map.cpp:392:7:392:9 | m26 | | +| map.cpp:390:7:390:9 | ref arg m26 | map.cpp:393:7:393:9 | m26 | | +| map.cpp:390:7:390:9 | ref arg m26 | map.cpp:398:1:398:1 | m26 | | +| map.cpp:390:37:390:41 | first | map.cpp:390:7:390:41 | call to iterator | | +| map.cpp:391:7:391:9 | m26 | map.cpp:391:7:391:9 | call to unordered_map | | +| map.cpp:392:7:392:9 | ref arg m26 | map.cpp:393:7:393:9 | m26 | | +| map.cpp:392:7:392:9 | ref arg m26 | map.cpp:398:1:398:1 | m26 | | +| map.cpp:392:40:392:44 | first | map.cpp:392:7:392:44 | call to iterator | | +| map.cpp:393:7:393:9 | m26 | map.cpp:393:7:393:9 | call to unordered_map | | +| map.cpp:394:7:394:9 | ref arg m27 | map.cpp:395:7:395:9 | m27 | | +| map.cpp:394:7:394:9 | ref arg m27 | map.cpp:396:7:396:9 | m27 | | +| map.cpp:394:7:394:9 | ref arg m27 | map.cpp:396:23:396:25 | m27 | | +| map.cpp:394:7:394:9 | ref arg m27 | map.cpp:397:7:397:9 | m27 | | +| map.cpp:394:7:394:9 | ref arg m27 | map.cpp:398:1:398:1 | m27 | | +| map.cpp:394:23:394:25 | ref arg m27 | map.cpp:394:7:394:9 | m27 | | +| map.cpp:394:23:394:25 | ref arg m27 | map.cpp:395:7:395:9 | m27 | | +| map.cpp:394:23:394:25 | ref arg m27 | map.cpp:396:7:396:9 | m27 | | +| map.cpp:394:23:394:25 | ref arg m27 | map.cpp:396:23:396:25 | m27 | | +| map.cpp:394:23:394:25 | ref arg m27 | map.cpp:397:7:397:9 | m27 | | +| map.cpp:394:23:394:25 | ref arg m27 | map.cpp:398:1:398:1 | m27 | | +| map.cpp:394:27:394:31 | call to begin | map.cpp:394:23:394:33 | call to iterator | TAINT | +| map.cpp:395:7:395:9 | m27 | map.cpp:395:7:395:9 | call to unordered_map | | +| map.cpp:396:7:396:9 | ref arg m27 | map.cpp:397:7:397:9 | m27 | | +| map.cpp:396:7:396:9 | ref arg m27 | map.cpp:398:1:398:1 | m27 | | +| map.cpp:396:23:396:25 | ref arg m27 | map.cpp:396:7:396:9 | m27 | | +| map.cpp:396:23:396:25 | ref arg m27 | map.cpp:397:7:397:9 | m27 | | +| map.cpp:396:23:396:25 | ref arg m27 | map.cpp:398:1:398:1 | m27 | | +| map.cpp:396:27:396:31 | call to begin | map.cpp:396:23:396:33 | call to iterator | TAINT | +| map.cpp:397:7:397:9 | m27 | map.cpp:397:7:397:9 | call to unordered_map | | | movableclass.cpp:8:2:8:15 | this | movableclass.cpp:8:27:8:31 | constructor init of field v [pre-this] | | | movableclass.cpp:8:21:8:22 | _v | movableclass.cpp:8:29:8:30 | _v | | | movableclass.cpp:8:29:8:30 | _v | movableclass.cpp:8:27:8:31 | constructor init of field v | TAINT | @@ -653,22 +1716,22 @@ | standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:53:12:53:18 | source1 | | | standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:54:14:54:20 | source1 | | | standalone_iterators.cpp:53:12:53:18 | ref arg source1 | standalone_iterators.cpp:54:14:54:20 | source1 | | -| stl.h:221:30:221:40 | call to allocator | stl.h:221:21:221:41 | noexcept(...) | TAINT | -| stl.h:221:30:221:40 | call to allocator | stl.h:221:21:221:41 | noexcept(...) | TAINT | -| stl.h:221:30:221:40 | call to allocator | stl.h:221:21:221:41 | noexcept(...) | TAINT | -| stl.h:221:30:221:40 | call to allocator | stl.h:221:21:221:41 | noexcept(...) | TAINT | -| stl.h:221:30:221:40 | call to allocator | stl.h:221:21:221:41 | noexcept(...) | TAINT | -| stl.h:221:53:221:63 | 0 | stl.h:221:46:221:64 | (no string representation) | TAINT | -| stl.h:314:9:314:9 | Unknown literal | stl.h:314:9:314:9 | constructor init of field first | TAINT | -| stl.h:314:9:314:9 | Unknown literal | stl.h:314:9:314:9 | constructor init of field first | TAINT | -| stl.h:314:9:314:9 | Unknown literal | stl.h:314:9:314:9 | constructor init of field second | TAINT | -| stl.h:314:9:314:9 | Unknown literal | stl.h:314:9:314:9 | constructor init of field second | TAINT | -| stl.h:314:9:314:9 | constructor init of field first [post-this] | stl.h:314:9:314:9 | constructor init of field second [pre-this] | | -| stl.h:314:9:314:9 | constructor init of field first [post-this] | stl.h:314:9:314:9 | constructor init of field second [pre-this] | | -| stl.h:314:9:314:9 | constructor init of field first [pre-this] | stl.h:314:9:314:9 | constructor init of field second [pre-this] | | -| stl.h:314:9:314:9 | constructor init of field first [pre-this] | stl.h:314:9:314:9 | constructor init of field second [pre-this] | | -| stl.h:314:9:314:9 | this | stl.h:314:9:314:9 | constructor init of field first [pre-this] | | -| stl.h:314:9:314:9 | this | stl.h:314:9:314:9 | constructor init of field first [pre-this] | | +| stl.h:222:30:222:40 | call to allocator | stl.h:222:21:222:41 | noexcept(...) | TAINT | +| stl.h:222:30:222:40 | call to allocator | stl.h:222:21:222:41 | noexcept(...) | TAINT | +| stl.h:222:30:222:40 | call to allocator | stl.h:222:21:222:41 | noexcept(...) | TAINT | +| stl.h:222:30:222:40 | call to allocator | stl.h:222:21:222:41 | noexcept(...) | TAINT | +| stl.h:222:30:222:40 | call to allocator | stl.h:222:21:222:41 | noexcept(...) | TAINT | +| stl.h:222:53:222:63 | 0 | stl.h:222:46:222:64 | (no string representation) | TAINT | +| stl.h:315:9:315:9 | Unknown literal | stl.h:315:9:315:9 | constructor init of field first | TAINT | +| stl.h:315:9:315:9 | Unknown literal | stl.h:315:9:315:9 | constructor init of field first | TAINT | +| stl.h:315:9:315:9 | Unknown literal | stl.h:315:9:315:9 | constructor init of field second | TAINT | +| stl.h:315:9:315:9 | Unknown literal | stl.h:315:9:315:9 | constructor init of field second | TAINT | +| stl.h:315:9:315:9 | constructor init of field first [post-this] | stl.h:315:9:315:9 | constructor init of field second [pre-this] | | +| stl.h:315:9:315:9 | constructor init of field first [post-this] | stl.h:315:9:315:9 | constructor init of field second [pre-this] | | +| stl.h:315:9:315:9 | constructor init of field first [pre-this] | stl.h:315:9:315:9 | constructor init of field second [pre-this] | | +| stl.h:315:9:315:9 | constructor init of field first [pre-this] | stl.h:315:9:315:9 | constructor init of field second [pre-this] | | +| stl.h:315:9:315:9 | this | stl.h:315:9:315:9 | constructor init of field first [pre-this] | | +| stl.h:315:9:315:9 | this | stl.h:315:9:315:9 | constructor init of field first [pre-this] | | | string.cpp:24:12:24:17 | call to source | string.cpp:28:7:28:7 | a | | | string.cpp:25:16:25:20 | 123 | string.cpp:25:16:25:21 | call to basic_string | TAINT | | string.cpp:25:16:25:21 | call to basic_string | string.cpp:29:7:29:7 | b | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp index 0da7369cda2..ae8ad331518 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp @@ -8,6 +8,10 @@ char *source(); void sink(char *); void sink(const char *); void sink(std::pair); +void sink(std::map); +void sink(std::map::iterator); +void sink(std::unordered_map); +void sink(std::unordered_map::iterator); void test_pair() { @@ -44,9 +48,9 @@ void test_pair() sink(f); // tainted [NOT DETECTED] std::pair g(f); - sink(f.first); - sink(f.second); // tainted [NOT DETECTED] - sink(f); // tainted [NOT DETECTED] + sink(g.first); + sink(g.second); // tainted [NOT DETECTED] + sink(g); // tainted [NOT DETECTED] std::pair h; h = f; @@ -91,3 +95,304 @@ void test_pair() sink(m.first.second); // tainted [NOT DETECTED] sink(m.second); } + +void test_map() +{ + // insert + std::map m1, m2, m3, m4, m5, m6; + + sink(m1.insert(std::make_pair("abc", "def")).first); + sink(m2.insert(std::make_pair("abc", source())).first); // tainted [NOT DETECTED] + sink(m3.insert(std::make_pair(source(), "def")).first); // tainted [NOT DETECTED] + sink(m4.insert(m4.begin(), std::pair("abc", source()))); // tainted [NOT DETECTED] + sink(m5.insert_or_assign("abc", source()).first); // tainted [NOT DETECTED] + sink(m6.insert_or_assign(m6.begin(), "abc", source())); // tainted [NOT DETECTED] + sink(m1); + sink(m2); // tainted [NOT DETECTED] + sink(m3); // tainted [NOT DETECTED] + sink(m4); // tainted [NOT DETECTED] + sink(m5); // tainted [NOT DETECTED] + sink(m6); // tainted [NOT DETECTED] + sink(m1.find("abc")); + sink(m2.find("abc")); // tainted [NOT DETECTED] + sink(m3.find("abc")); + sink(m4.find("abc")); // tainted [NOT DETECTED] + sink(m5.find("abc")); // tainted [NOT DETECTED] + sink(m6.find("abc")); // tainted [NOT DETECTED] + sink(m1.find("def")); + sink(m2.find("def")); + sink(m3.find("def")); + sink(m4.find("def")); + sink(m5.find("def")); + sink(m6.find("def")); + + // copy constructors and assignment + std::map m7(m2); + std::map m8 = m2; + std::map m9; + m9 = m2; + sink(m7); // tainted [NOT DETECTED] + sink(m8); // tainted [NOT DETECTED] + sink(m9); // tainted [NOT DETECTED] + sink(m7.find("abc")); // tainted [NOT DETECTED] + sink(m8.find("abc")); // tainted [NOT DETECTED] + sink(m9.find("abc")); // tainted [NOT DETECTED] + + // iterators + std::map::iterator i1, i2, i3; + for (i1 = m1.begin(); i1 != m1.end(); i1++) + { + sink(*i1); + sink(i1->first); + sink(i1->second); + } + for (i2 = m2.begin(); i2 != m2.end(); i2++) + { + sink(*i2); // tainted [NOT DETECTED] + sink(i2->first); + sink(i2->second); // tainted [NOT DETECTED] + } + for (i3 = m3.begin(); i3 != m3.end(); i3++) + { + sink(*i3); // tainted [NOT DETECTED] + sink(i2->first); // tainted [NOT DETECTED] + sink(i2->second); + } + + // array-like access + std::map m10, m11, m12, m13; + sink(m10["abc"] = "def"); + sink(m11["abc"] = source()); // tainted + sink(m12.at("abc") = "def"); + sink(m13.at("abc") = source()); // tainted + sink(m10["abc"]); + sink(m11["abc"]); // tainted [NOT DETECTED] + sink(m12["abc"]); + sink(m13["abc"]); // tainted [NOT DETECTED] + + // ranges + std::map m14; + m14.insert(std::make_pair("a", "a")); + m14.insert(std::make_pair("b", source())); + m14.insert(std::make_pair("c", source())); + m14.insert(std::make_pair("d", "d")); + sink(m2.lower_bound("b")); // tainted [NOT DETECTED] + sink(m2.upper_bound("b")); // tainted [NOT DETECTED] + sink(m2.equal_range("b").first); // tainted [NOT DETECTED] + sink(m2.equal_range("b").second); // tainted [NOT DETECTED] + sink(m2.upper_bound("c")); + sink(m2.equal_range("c").second); + + // swap + std::map m15, m16, m17, m18; + m15.insert(std::pair(source(), source())); + m18.insert(std::pair(source(), source())); + sink(m15); // tainted [NOT DETECTED] + sink(m16); + sink(m17); + sink(m18); // tainted [NOT DETECTED] + m15.swap(m16); + m17.swap(m18); + sink(m15); + sink(m16); // tainted [NOT DETECTED] + sink(m17); // tainted [NOT DETECTED] + sink(m18); + + // merge + std::map m19, m20, m21, m22; + m19.insert(std::pair(source(), source())); + m20.insert(std::pair("abc", "def")); + m21.insert(std::pair("abc", "def")); + m22.insert(std::pair(source(), source())); + sink(m19); // tainted [NOT DETECTED] + sink(m20); + sink(m21); + sink(m22); // tainted [NOT DETECTED] + m15.merge(m16); + m17.merge(m18); + sink(m19); // tainted [NOT DETECTED] + sink(m20); // tainted [NOT DETECTED] + sink(m21); // tainted [NOT DETECTED] + sink(m22); // tainted [NOT DETECTED] + + // erase, clear + std::map m23; + m23.insert(std::pair(source(), source())); + m23.insert(std::pair(source(), source())); + sink(m23); // tainted [NOT DETECTED] + sink(m23.erase(m23.begin())); // tainted [NOT DETECTED] + sink(m23); // tainted [NOT DETECTED] + m23.clear(); + sink(m23); + + // emplace, emplace_hint + std::map m24, m25; + sink(m24.emplace("abc", "def").first); + sink(m24); + sink(m24.emplace("abc", source()).first); // tainted [NOT DETECTED] + sink(m24); // tainted [NOT DETECTED] + sink(m25.emplace_hint(m25.begin(), "abc", "def")); + sink(m25); + sink(m25.emplace_hint(m25.begin(), "abc", source())); // tainted [NOT DETECTED] + sink(m25); // tainted [NOT DETECTED] + + // try_emplace + std::map m26, m27; + sink(m26.try_emplace("abc", "def").first); + sink(m26); + sink(m26.try_emplace("abc", source()).first); // tainted [NOT DETECTED] + sink(m26); // tainted [NOT DETECTED] + sink(m27.try_emplace(m27.begin(), "abc", "def")); + sink(m27); + sink(m27.try_emplace(m27.begin(), "abc", source())); // tainted [NOT DETECTED] + sink(m27); // tainted [NOT DETECTED] +} + +void test_unordered_map() +{ + // insert + std::unordered_map m1, m2, m3, m4, m5, m6; + + sink(m1.insert(std::make_pair("abc", "def")).first); + sink(m2.insert(std::make_pair("abc", source())).first); // tainted [NOT DETECTED] + sink(m3.insert(std::make_pair(source(), "def")).first); // tainted [NOT DETECTED] + sink(m4.insert(m4.begin(), std::pair("abc", source()))); // tainted [NOT DETECTED] + sink(m5.insert_or_assign("abc", source()).first); // tainted [NOT DETECTED] + sink(m6.insert_or_assign(m6.begin(), "abc", source())); // tainted [NOT DETECTED] + sink(m1); + sink(m2); // tainted [NOT DETECTED] + sink(m3); // tainted [NOT DETECTED] + sink(m4); // tainted [NOT DETECTED] + sink(m5); // tainted [NOT DETECTED] + sink(m6); // tainted [NOT DETECTED] + sink(m1.find("abc")); + sink(m2.find("abc")); // tainted [NOT DETECTED] + sink(m3.find("abc")); + sink(m4.find("abc")); // tainted [NOT DETECTED] + sink(m5.find("abc")); // tainted [NOT DETECTED] + sink(m6.find("abc")); // tainted [NOT DETECTED] + sink(m1.find("def")); + sink(m2.find("def")); + sink(m3.find("def")); + sink(m4.find("def")); + sink(m5.find("def")); + sink(m6.find("def")); + + // copy constructors and assignment + std::unordered_map m7(m2); + std::unordered_map m8 = m2; + std::unordered_map m9; + m9 = m2; + sink(m7); // tainted [NOT DETECTED] + sink(m8); // tainted [NOT DETECTED] + sink(m9); // tainted [NOT DETECTED] + sink(m7.find("abc")); // tainted [NOT DETECTED] + sink(m8.find("abc")); // tainted [NOT DETECTED] + sink(m9.find("abc")); // tainted [NOT DETECTED] + + // iterators + std::unordered_map::iterator i1, i2, i3; + for (i1 = m1.begin(); i1 != m1.end(); i1++) + { + sink(*i1); + sink(i1->first); + sink(i1->second); + } + for (i2 = m2.begin(); i2 != m2.end(); i2++) + { + sink(*i2); // tainted [NOT DETECTED] + sink(i2->first); + sink(i2->second); // tainted [NOT DETECTED] + } + for (i3 = m3.begin(); i3 != m3.end(); i3++) + { + sink(*i3); // tainted [NOT DETECTED] + sink(i2->first); // tainted [NOT DETECTED] + sink(i2->second); + } + + // array-like access + std::unordered_map m10, m11, m12, m13; + sink(m10["abc"] = "def"); + sink(m11["abc"] = source()); // tainted + sink(m12.at("abc") = "def"); + sink(m13.at("abc") = source()); // tainted + sink(m10["abc"]); + sink(m11["abc"]); // tainted [NOT DETECTED] + sink(m12["abc"]); + sink(m13["abc"]); // tainted [NOT DETECTED] + + // ranges + std::unordered_map m14; + m14.insert(std::make_pair("a", "a")); + m14.insert(std::make_pair("b", source())); + m14.insert(std::make_pair("c", source())); + m14.insert(std::make_pair("d", "d")); + sink(m2.equal_range("b").first); // tainted [NOT DETECTED] + sink(m2.equal_range("b").second); // tainted [NOT DETECTED] + sink(m2.equal_range("c").second); + + // swap + std::unordered_map m15, m16, m17, m18; + m15.insert(std::pair(source(), source())); + m18.insert(std::pair(source(), source())); + sink(m15); // tainted [NOT DETECTED] + sink(m16); + sink(m17); + sink(m18); // tainted [NOT DETECTED] + m15.swap(m16); + m17.swap(m18); + sink(m15); + sink(m16); // tainted [NOT DETECTED] + sink(m17); // tainted [NOT DETECTED] + sink(m18); + + // merge + std::unordered_map m19, m20, m21, m22; + m19.insert(std::pair(source(), source())); + m20.insert(std::pair("abc", "def")); + m21.insert(std::pair("abc", "def")); + m22.insert(std::pair(source(), source())); + sink(m19); // tainted [NOT DETECTED] + sink(m20); + sink(m21); + sink(m22); // tainted [NOT DETECTED] + m15.merge(m16); + m17.merge(m18); + sink(m19); // tainted [NOT DETECTED] + sink(m20); // tainted [NOT DETECTED] + sink(m21); // tainted [NOT DETECTED] + sink(m22); // tainted [NOT DETECTED] + + // erase, clear + std::unordered_map m23; + m23.insert(std::pair(source(), source())); + m23.insert(std::pair(source(), source())); + sink(m23); // tainted [NOT DETECTED] + sink(m23.erase(m23.begin())); // tainted [NOT DETECTED] + sink(m23); // tainted [NOT DETECTED] + m23.clear(); + sink(m23); + + // emplace, emplace_hint + std::unordered_map m24, m25; + sink(m24.emplace("abc", "def").first); + sink(m24); + sink(m24.emplace("abc", source()).first); // tainted [NOT DETECTED] + sink(m24); // tainted [NOT DETECTED] + sink(m25.emplace_hint(m25.begin(), "abc", "def")); + sink(m25); + sink(m25.emplace_hint(m25.begin(), "abc", source())); // tainted [NOT DETECTED] + sink(m25); // tainted [NOT DETECTED] + + // try_emplace + std::unordered_map m26, m27; + sink(m26.try_emplace("abc", "def").first); + sink(m26); + sink(m26.try_emplace("abc", source()).first); // tainted [NOT DETECTED] + sink(m26); // tainted [NOT DETECTED] + sink(m27.try_emplace(m27.begin(), "abc", "def")); + sink(m27); + sink(m27.try_emplace(m27.begin(), "abc", source())); // tainted [NOT DETECTED] + sink(m27); // tainted [NOT DETECTED] +} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h index c6b2150510f..3a112cd0c88 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h @@ -36,6 +36,7 @@ namespace std { bool operator==(iterator other) const; bool operator!=(iterator other) const; reference_type operator*() const; + pointer_type operator->() const; iterator operator+(int); iterator operator-(int); iterator &operator+=(int); @@ -326,3 +327,137 @@ namespace std { template pair make_pair(T1, T2); } + +// --- map --- + +namespace std { + template struct less; + + template, class Allocator = allocator>> + class map { + public: + using key_type = Key; + using mapped_type = T; + using value_type = pair; + using iterator = std::iterator; + using const_iterator = std::iterator; + + map() /*: map(Compare()) { }*/; + map(const map& x); + map(map&& x); + ~map(); + + map& operator=(const map& x); + map& operator=(map&& x) /*noexcept(allocator_traits::is_always_equal::value && is_nothrow_move_assignable_v)*/; + + iterator begin() noexcept; + const_iterator begin() const noexcept; + iterator end() noexcept; + const_iterator end() const noexcept; + + T& operator[](const key_type& x); + T& operator[](key_type&& x); + T& at(const key_type& x); + const T& at(const key_type& x) const; + + template pair emplace(Args&&... args); + template iterator emplace_hint(const_iterator position, Args&&... args); + + pair insert(const value_type& x); + pair insert(value_type&& x); + iterator insert(const_iterator position, const value_type& x); + iterator insert(const_iterator position, value_type&& x); + + template pair try_emplace(const key_type& k, Args&&... args); + template pair try_emplace(key_type&& k, Args&&... args); + template iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); + template iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); + template pair insert_or_assign(const key_type& k, M&& obj); + template pair insert_or_assign(key_type&& k, M&& obj); + template iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); + template iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); + + iterator erase(iterator position); + iterator erase(const_iterator position); + iterator erase(const_iterator first, const_iterator last); + void swap(map&) /*noexcept(/*==allocator_traits::is_always_equal::value && is_nothrow_swappable_v)*/; + void clear() noexcept; + + template void merge(map& source); + template void merge(map&& source); + + iterator find(const key_type& x); + const_iterator find(const key_type& x) const; + + iterator lower_bound(const key_type& x); + const_iterator lower_bound(const key_type& x) const; + iterator upper_bound(const key_type& x); + const_iterator upper_bound(const key_type& x) const; + + pair equal_range(const key_type& x); + pair equal_range(const key_type& x) const; + }; + + template struct hash; + template struct equal_to; + + template, class Pred = equal_to, class Allocator = allocator>> + class unordered_map { + public: + using key_type = Key; + using mapped_type = T; + using value_type = pair; + using iterator = std::iterator; + using const_iterator = std::iterator; + + unordered_map(); + unordered_map(const unordered_map&); + unordered_map(unordered_map&&); + ~unordered_map(); + + unordered_map& operator=(const unordered_map&); + unordered_map& operator=(unordered_map&&) /*noexcept(allocator_traits::is_always_equal::value && is_nothrow_move_assignable_v && is_nothrow_move_assignable_v)*/; + + iterator begin() noexcept; + const_iterator begin() const noexcept; + iterator end() noexcept; + const_iterator end() const noexcept; + + mapped_type& operator[](const key_type& k); + mapped_type& operator[](key_type&& k); + mapped_type& at(const key_type& k); + const mapped_type& at(const key_type& k) const; + + template pair emplace(Args&&... args); + template iterator emplace_hint(const_iterator position, Args&&... args); + + pair insert(const value_type& obj); + pair insert(value_type&& obj); + iterator insert(const_iterator hint, const value_type& obj); + iterator insert(const_iterator hint, value_type&& obj); + + template pair try_emplace(const key_type& k, Args&&... args); + template pair try_emplace(key_type&& k, Args&&... args); + template iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); + template iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); + template pair insert_or_assign(const key_type& k, M&& obj); + template pair insert_or_assign(key_type&& k, M&& obj); + template iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); + template iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); + + iterator erase(iterator position); + iterator erase(const_iterator position); + iterator erase(const_iterator first, const_iterator last); + void swap(unordered_map&) /*noexcept(allocator_traits::is_always_equal::value && is_nothrow_swappable_v && is_nothrow_swappable_v)*/; + void clear() noexcept; + + template void merge(unordered_map& source); + template void merge(unordered_map&& source); + + iterator find(const key_type& k); + const_iterator find(const key_type& k) const; + + pair equal_range(const key_type& k); + pair equal_range(const key_type& k) const; + }; +}; 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 7032d498666..f8db8d30418 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -33,8 +33,12 @@ | format.cpp:115:8:115:13 | buffer | format.cpp:114:37:114:50 | call to source | | format.cpp:157:7:157:22 | access to array | format.cpp:147:12:147:25 | call to source | | format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source | -| map.cpp:22:9:22:13 | first | map.cpp:21:12:21:17 | call to source | -| map.cpp:28:9:28:14 | second | map.cpp:26:13:26:18 | call to source | +| map.cpp:26:9:26:13 | first | map.cpp:25:12:25:17 | call to source | +| map.cpp:32:9:32:14 | second | map.cpp:30:13:30:18 | call to source | +| map.cpp:165:7:165:27 | ... = ... | map.cpp:165:20:165:25 | call to source | +| map.cpp:167:7:167:30 | ... = ... | map.cpp:167:23:167:28 | call to source | +| map.cpp:317:7:317:27 | ... = ... | map.cpp:317:20:317:25 | call to source | +| map.cpp:319:7:319:30 | ... = ... | map.cpp:319:23:319:28 | call to source | | movableclass.cpp:44:8:44:9 | s1 | movableclass.cpp:39:21:39:26 | call to source | | movableclass.cpp:45:8:45:9 | s2 | movableclass.cpp:40:23:40:28 | call to source | | movableclass.cpp:46:8:46:9 | s3 | movableclass.cpp:42:8:42:13 | 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 ce708a75747..24ebc1469a2 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 @@ -42,8 +42,12 @@ | format.cpp:115:8:115:13 | Argument 0 indirection | format.cpp:114:37:114:50 | call to source | | format.cpp:157:7:157:22 | access to array | format.cpp:147:12:147:25 | call to source | | format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source | -| map.cpp:22:9:22:13 | first | map.cpp:21:12:21:17 | call to source | -| map.cpp:28:9:28:14 | second | map.cpp:26:13:26:18 | call to source | +| map.cpp:26:9:26:13 | first | map.cpp:25:12:25:17 | call to source | +| map.cpp:32:9:32:14 | second | map.cpp:30:13:30:18 | call to source | +| map.cpp:165:7:165:27 | ... = ... | map.cpp:165:20:165:25 | call to source | +| map.cpp:167:7:167:30 | ... = ... | map.cpp:167:23:167:28 | call to source | +| map.cpp:317:7:317:27 | ... = ... | map.cpp:317:20:317:25 | call to source | +| map.cpp:319:7:319:30 | ... = ... | map.cpp:319:23:319:28 | call to source | | movableclass.cpp:44:8:44:9 | s1 | movableclass.cpp:39:21:39:26 | call to source | | movableclass.cpp:45:8:45:9 | s2 | movableclass.cpp:40:23:40:28 | call to source | | movableclass.cpp:46:8:46:9 | s3 | movableclass.cpp:42:8:42:13 | call to source | From 0dca7f81bc1f5804e45bc4230f1f5a67d86e89df Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Sep 2020 15:15:40 +0100 Subject: [PATCH 046/411] C++: Model std::swap. --- cpp/ql/src/semmle/code/cpp/models/Models.qll | 1 + .../cpp/models/implementations/StdPair.qll | 60 ++++++++++ .../dataflow/taint-tests/localTaint.expected | 104 ++++++++++++++++++ .../dataflow/taint-tests/map.cpp | 70 ++++++------ .../dataflow/taint-tests/taint.expected | 11 ++ .../dataflow/taint-tests/test_diff.expected | 25 +++++ .../dataflow/taint-tests/test_ir.expected | 34 ++++++ 7 files changed, 270 insertions(+), 35 deletions(-) create mode 100644 cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll diff --git a/cpp/ql/src/semmle/code/cpp/models/Models.qll b/cpp/ql/src/semmle/code/cpp/models/Models.qll index 2f1896fc2a6..e950096ac47 100644 --- a/cpp/ql/src/semmle/code/cpp/models/Models.qll +++ b/cpp/ql/src/semmle/code/cpp/models/Models.qll @@ -15,6 +15,7 @@ private import implementations.Strcpy private import implementations.Strdup private import implementations.Strftime private import implementations.StdContainer +private import implementations.StdPair private import implementations.StdString private import implementations.Swap private import implementations.GetDelim diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll new file mode 100644 index 00000000000..f092b8bac2e --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll @@ -0,0 +1,60 @@ +/** + * Provides models for the C++ `std::pair` class. + */ + +import semmle.code.cpp.models.interfaces.Taint + +/** + * Additional model for `std::pair` constructors. + */ +class StdPairConstructor extends Constructor, TaintFunction { + StdPairConstructor() { this.getDeclaringType().hasQualifiedName("std", "pair") } + + /** + * Gets the index of a parameter to this function that is a reference to the + * value type of the container. + */ + int getAValueTypeParameterIndex() { + getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() = + getDeclaringType().getTemplateArgument(_).(Type).getUnspecifiedType() // i.e. the `T1` or `T2` of this `std::pair` + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // taint flow from any parameter of the value type to the returned object + input.isParameterDeref(getAValueTypeParameterIndex()) and + ( + output.isReturnValue() // TODO: this is only needed for AST data flow, which treats constructors as returning the new object + or + output.isQualifierObject() + ) + } +} + +/** + * An instantiation of `std::make_pair`. + */ +class StdMakePair extends TaintFunction { + StdMakePair() { this.hasQualifiedName("std", "make_pair") } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // taint flow from any parameter to the returned object + input.isParameterDeref(_) and + output.isReturnValue() + } +} + +/** + * The standard pair `swap` function. + */ +class StdPairSwap extends TaintFunction { + StdPairSwap() { this.hasQualifiedName("std", "pair", "swap") } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // container1.swap(container2) + input.isQualifierObject() and + output.isParameterDeref(0) + or + 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 18e8a873303..4e7a5cee79b 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -430,23 +430,29 @@ | map.cpp:31:7:31:7 | c [post update] | map.cpp:32:7:32:7 | c | | | map.cpp:31:7:31:7 | c [post update] | map.cpp:33:7:33:7 | c | | | map.cpp:32:7:32:7 | c [post update] | map.cpp:33:7:33:7 | c | | +| map.cpp:35:30:35:34 | 123 | map.cpp:35:30:35:42 | call to pair | TAINT | | map.cpp:35:30:35:42 | call to pair | map.cpp:36:7:36:7 | d | | | map.cpp:35:30:35:42 | call to pair | map.cpp:37:7:37:7 | d | | | map.cpp:35:30:35:42 | call to pair | map.cpp:38:7:38:7 | d | | +| map.cpp:35:37:35:41 | 456 | map.cpp:35:30:35:42 | call to pair | TAINT | | map.cpp:36:7:36:7 | d [post update] | map.cpp:37:7:37:7 | d | | | map.cpp:36:7:36:7 | d [post update] | map.cpp:38:7:38:7 | d | | | map.cpp:37:7:37:7 | d [post update] | map.cpp:38:7:38:7 | d | | +| map.cpp:40:30:40:35 | call to source | map.cpp:40:30:40:45 | call to pair | TAINT | | map.cpp:40:30:40:45 | call to pair | map.cpp:41:7:41:7 | e | | | map.cpp:40:30:40:45 | call to pair | map.cpp:42:7:42:7 | e | | | map.cpp:40:30:40:45 | call to pair | map.cpp:43:7:43:7 | e | | +| map.cpp:40:40:40:44 | 456 | map.cpp:40:30:40:45 | call to pair | TAINT | | map.cpp:41:7:41:7 | e [post update] | map.cpp:42:7:42:7 | e | | | map.cpp:41:7:41:7 | e [post update] | map.cpp:43:7:43:7 | e | | | map.cpp:42:7:42:7 | e [post update] | map.cpp:43:7:43:7 | e | | +| map.cpp:45:30:45:34 | 123 | map.cpp:45:30:45:45 | call to pair | TAINT | | map.cpp:45:30:45:45 | call to pair | map.cpp:46:7:46:7 | f | | | map.cpp:45:30:45:45 | call to pair | map.cpp:47:7:47:7 | f | | | map.cpp:45:30:45:45 | call to pair | map.cpp:48:7:48:7 | f | | | map.cpp:45:30:45:45 | call to pair | map.cpp:50:30:50:30 | f | | | map.cpp:45:30:45:45 | call to pair | map.cpp:56:6:56:6 | f | | +| map.cpp:45:37:45:42 | call to source | map.cpp:45:30:45:45 | call to pair | TAINT | | map.cpp:46:7:46:7 | f [post update] | map.cpp:47:7:47:7 | f | | | map.cpp:46:7:46:7 | f [post update] | map.cpp:48:7:48:7 | f | | | map.cpp:46:7:46:7 | f [post update] | map.cpp:50:30:50:30 | f | | @@ -467,31 +473,43 @@ | map.cpp:57:7:57:7 | h [post update] | map.cpp:58:7:58:7 | h | | | map.cpp:57:7:57:7 | h [post update] | map.cpp:59:7:59:7 | h | | | map.cpp:58:7:58:7 | h [post update] | map.cpp:59:7:59:7 | h | | +| map.cpp:61:30:61:34 | 123 | map.cpp:61:30:61:42 | call to pair | TAINT | | map.cpp:61:30:61:42 | call to pair | map.cpp:65:3:65:3 | i | | | map.cpp:61:30:61:42 | call to pair | map.cpp:67:7:67:7 | i | | | map.cpp:61:30:61:42 | call to pair | map.cpp:68:7:68:7 | i | | | map.cpp:61:30:61:42 | call to pair | map.cpp:69:7:69:7 | i | | +| map.cpp:61:37:61:41 | 456 | map.cpp:61:30:61:42 | call to pair | TAINT | +| map.cpp:62:30:62:34 | 123 | map.cpp:62:30:62:45 | call to pair | TAINT | | map.cpp:62:30:62:45 | call to pair | map.cpp:65:10:65:10 | j | | | map.cpp:62:30:62:45 | call to pair | map.cpp:70:7:70:7 | j | | | map.cpp:62:30:62:45 | call to pair | map.cpp:71:7:71:7 | j | | | map.cpp:62:30:62:45 | call to pair | map.cpp:72:7:72:7 | j | | +| map.cpp:62:37:62:42 | call to source | map.cpp:62:30:62:45 | call to pair | TAINT | +| map.cpp:63:30:63:34 | 123 | map.cpp:63:30:63:45 | call to pair | TAINT | | map.cpp:63:30:63:45 | call to pair | map.cpp:66:2:66:2 | k | | | map.cpp:63:30:63:45 | call to pair | map.cpp:73:7:73:7 | k | | | map.cpp:63:30:63:45 | call to pair | map.cpp:74:7:74:7 | k | | | map.cpp:63:30:63:45 | call to pair | map.cpp:75:7:75:7 | k | | +| map.cpp:63:37:63:42 | call to source | map.cpp:63:30:63:45 | call to pair | TAINT | +| map.cpp:64:30:64:34 | 123 | map.cpp:64:30:64:42 | call to pair | TAINT | | map.cpp:64:30:64:42 | call to pair | map.cpp:66:9:66:9 | l | | | map.cpp:64:30:64:42 | call to pair | map.cpp:76:7:76:7 | l | | | map.cpp:64:30:64:42 | call to pair | map.cpp:77:7:77:7 | l | | | map.cpp:64:30:64:42 | call to pair | map.cpp:78:7:78:7 | l | | +| map.cpp:64:37:64:41 | 456 | map.cpp:64:30:64:42 | call to pair | TAINT | +| map.cpp:65:3:65:3 | i | map.cpp:65:10:65:10 | ref arg j | TAINT | | map.cpp:65:3:65:3 | ref arg i | map.cpp:67:7:67:7 | i | | | map.cpp:65:3:65:3 | ref arg i | map.cpp:68:7:68:7 | i | | | map.cpp:65:3:65:3 | ref arg i | map.cpp:69:7:69:7 | i | | +| map.cpp:65:10:65:10 | j | map.cpp:65:3:65:3 | ref arg i | TAINT | | map.cpp:65:10:65:10 | ref arg j | map.cpp:70:7:70:7 | j | | | map.cpp:65:10:65:10 | ref arg j | map.cpp:71:7:71:7 | j | | | map.cpp:65:10:65:10 | ref arg j | map.cpp:72:7:72:7 | j | | +| map.cpp:66:2:66:2 | k | map.cpp:66:9:66:9 | ref arg l | TAINT | | map.cpp:66:2:66:2 | ref arg k | map.cpp:73:7:73:7 | k | | | map.cpp:66:2:66:2 | ref arg k | map.cpp:74:7:74:7 | k | | | map.cpp:66:2:66:2 | ref arg k | map.cpp:75:7:75:7 | k | | +| map.cpp:66:9:66:9 | l | map.cpp:66:2:66:2 | ref arg k | TAINT | | map.cpp:66:9:66:9 | ref arg l | map.cpp:76:7:76:7 | l | | | map.cpp:66:9:66:9 | ref arg l | map.cpp:77:7:77:7 | l | | | map.cpp:66:9:66:9 | ref arg l | map.cpp:78:7:78:7 | l | | @@ -508,8 +526,26 @@ | map.cpp:76:7:76:7 | l [post update] | map.cpp:78:7:78:7 | l | | | map.cpp:77:7:77:7 | l [post update] | map.cpp:78:7:78:7 | l | | | map.cpp:80:7:80:15 | call to make_pair | map.cpp:80:7:80:29 | call to pair | TAINT | +| map.cpp:80:17:80:21 | 123 | map.cpp:80:7:80:15 | call to make_pair | TAINT | +| map.cpp:80:24:80:28 | 456 | map.cpp:80:7:80:15 | call to make_pair | TAINT | +| map.cpp:81:17:81:21 | 123 | map.cpp:81:7:81:15 | call to make_pair | TAINT | +| map.cpp:81:24:81:28 | 456 | map.cpp:81:7:81:15 | call to make_pair | TAINT | +| map.cpp:82:17:82:21 | 123 | map.cpp:82:7:82:15 | call to make_pair | TAINT | +| map.cpp:82:24:82:28 | 456 | map.cpp:82:7:82:15 | call to make_pair | TAINT | | map.cpp:83:7:83:15 | call to make_pair | map.cpp:83:7:83:32 | call to pair | TAINT | +| map.cpp:83:17:83:22 | call to source | map.cpp:83:7:83:15 | call to make_pair | TAINT | +| map.cpp:83:27:83:31 | 456 | map.cpp:83:7:83:15 | call to make_pair | TAINT | +| map.cpp:84:17:84:22 | call to source | map.cpp:84:7:84:15 | call to make_pair | TAINT | +| map.cpp:84:27:84:31 | 456 | map.cpp:84:7:84:15 | call to make_pair | TAINT | +| map.cpp:85:17:85:22 | call to source | map.cpp:85:7:85:15 | call to make_pair | TAINT | +| map.cpp:85:27:85:31 | 456 | map.cpp:85:7:85:15 | call to make_pair | TAINT | | map.cpp:86:7:86:15 | call to make_pair | map.cpp:86:7:86:32 | call to pair | TAINT | +| map.cpp:86:17:86:21 | 123 | map.cpp:86:7:86:15 | call to make_pair | TAINT | +| map.cpp:86:24:86:29 | call to source | map.cpp:86:7:86:15 | call to make_pair | TAINT | +| map.cpp:87:17:87:21 | 123 | map.cpp:87:7:87:15 | call to make_pair | TAINT | +| map.cpp:87:24:87:29 | call to source | map.cpp:87:7:87:15 | call to make_pair | TAINT | +| map.cpp:88:17:88:21 | 123 | map.cpp:88:7:88:15 | call to make_pair | TAINT | +| map.cpp:88:24:88:29 | call to source | map.cpp:88:7:88:15 | call to make_pair | TAINT | | map.cpp:91:6:91:14 | call to make_pair | map.cpp:91:6:91:49 | call to pair | TAINT | | map.cpp:91:6:91:49 | call to pair | map.cpp:91:2:91:49 | ... = ... | | | map.cpp:91:6:91:49 | call to pair | map.cpp:92:7:92:7 | m | | @@ -517,6 +553,10 @@ | map.cpp:91:6:91:49 | call to pair | map.cpp:94:7:94:7 | m | | | map.cpp:91:6:91:49 | call to pair | map.cpp:95:7:95:7 | m | | | map.cpp:91:6:91:49 | call to pair | map.cpp:96:7:96:7 | m | | +| map.cpp:91:16:91:24 | call to make_pair | map.cpp:91:6:91:14 | call to make_pair | TAINT | +| map.cpp:91:26:91:30 | 123 | map.cpp:91:16:91:24 | call to make_pair | TAINT | +| map.cpp:91:33:91:38 | call to source | map.cpp:91:16:91:24 | call to make_pair | TAINT | +| map.cpp:91:44:91:48 | 789 | map.cpp:91:6:91:14 | call to make_pair | TAINT | | map.cpp:92:7:92:7 | m | map.cpp:92:7:92:7 | call to pair | TAINT | | map.cpp:94:7:94:7 | m [post update] | map.cpp:95:7:95:7 | m | | | map.cpp:94:7:94:7 | m [post update] | map.cpp:96:7:96:7 | m | | @@ -575,6 +615,8 @@ | map.cpp:104:7:104:8 | ref arg m1 | map.cpp:143:30:143:31 | m1 | | | map.cpp:104:7:104:8 | ref arg m1 | map.cpp:249:1:249:1 | m1 | | | map.cpp:104:17:104:30 | call to make_pair | map.cpp:104:17:104:44 | call to pair | TAINT | +| map.cpp:104:32:104:36 | abc | map.cpp:104:17:104:30 | call to make_pair | TAINT | +| map.cpp:104:39:104:43 | def | map.cpp:104:17:104:30 | call to make_pair | TAINT | | map.cpp:104:47:104:51 | first | map.cpp:104:7:104:51 | call to iterator | | | map.cpp:105:7:105:8 | ref arg m2 | map.cpp:111:7:111:8 | m2 | | | map.cpp:105:7:105:8 | ref arg m2 | map.cpp:117:7:117:8 | m2 | | @@ -592,6 +634,8 @@ | map.cpp:105:7:105:8 | ref arg m2 | map.cpp:184:7:184:8 | m2 | | | map.cpp:105:7:105:8 | ref arg m2 | map.cpp:249:1:249:1 | m2 | | | map.cpp:105:17:105:30 | call to make_pair | map.cpp:105:17:105:47 | call to pair | TAINT | +| map.cpp:105:32:105:36 | abc | map.cpp:105:17:105:30 | call to make_pair | TAINT | +| map.cpp:105:39:105:44 | call to source | map.cpp:105:17:105:30 | call to make_pair | TAINT | | map.cpp:105:50:105:54 | first | map.cpp:105:7:105:54 | call to iterator | | | map.cpp:106:7:106:8 | ref arg m3 | map.cpp:112:7:112:8 | m3 | | | map.cpp:106:7:106:8 | ref arg m3 | map.cpp:118:7:118:8 | m3 | | @@ -600,6 +644,8 @@ | map.cpp:106:7:106:8 | ref arg m3 | map.cpp:155:30:155:31 | m3 | | | map.cpp:106:7:106:8 | ref arg m3 | map.cpp:249:1:249:1 | m3 | | | map.cpp:106:17:106:30 | call to make_pair | map.cpp:106:17:106:47 | call to pair | TAINT | +| map.cpp:106:32:106:37 | call to source | map.cpp:106:17:106:30 | call to make_pair | TAINT | +| map.cpp:106:42:106:46 | def | map.cpp:106:17:106:30 | call to make_pair | TAINT | | map.cpp:106:50:106:54 | first | map.cpp:106:7:106:54 | call to iterator | | | map.cpp:107:7:107:8 | ref arg m4 | map.cpp:113:7:113:8 | m4 | | | map.cpp:107:7:107:8 | ref arg m4 | map.cpp:119:7:119:8 | m4 | | @@ -612,6 +658,8 @@ | map.cpp:107:17:107:18 | ref arg m4 | map.cpp:249:1:249:1 | m4 | | | map.cpp:107:20:107:24 | call to begin | map.cpp:107:17:107:26 | call to iterator | TAINT | | map.cpp:107:29:107:70 | call to pair | map.cpp:107:29:107:70 | call to pair | TAINT | +| map.cpp:107:55:107:59 | abc | map.cpp:107:29:107:70 | call to pair | TAINT | +| map.cpp:107:62:107:67 | call to source | map.cpp:107:29:107:70 | call to pair | TAINT | | map.cpp:108:7:108:8 | ref arg m5 | map.cpp:114:7:114:8 | m5 | | | map.cpp:108:7:108:8 | ref arg m5 | map.cpp:120:7:120:8 | m5 | | | map.cpp:108:7:108:8 | ref arg m5 | map.cpp:126:7:126:8 | m5 | | @@ -818,15 +866,23 @@ | map.cpp:175:2:175:4 | ref arg m14 | map.cpp:178:2:178:4 | m14 | | | map.cpp:175:2:175:4 | ref arg m14 | map.cpp:249:1:249:1 | m14 | | | map.cpp:175:13:175:26 | call to make_pair | map.cpp:175:13:175:36 | call to pair | TAINT | +| map.cpp:175:28:175:30 | a | map.cpp:175:13:175:26 | call to make_pair | TAINT | +| map.cpp:175:33:175:35 | a | map.cpp:175:13:175:26 | call to make_pair | TAINT | | map.cpp:176:2:176:4 | ref arg m14 | map.cpp:177:2:177:4 | m14 | | | map.cpp:176:2:176:4 | ref arg m14 | map.cpp:178:2:178:4 | m14 | | | map.cpp:176:2:176:4 | ref arg m14 | map.cpp:249:1:249:1 | m14 | | | map.cpp:176:13:176:26 | call to make_pair | map.cpp:176:13:176:41 | call to pair | TAINT | +| map.cpp:176:28:176:30 | b | map.cpp:176:13:176:26 | call to make_pair | TAINT | +| map.cpp:176:33:176:38 | call to source | map.cpp:176:13:176:26 | call to make_pair | TAINT | | map.cpp:177:2:177:4 | ref arg m14 | map.cpp:178:2:178:4 | m14 | | | map.cpp:177:2:177:4 | ref arg m14 | map.cpp:249:1:249:1 | m14 | | | map.cpp:177:13:177:26 | call to make_pair | map.cpp:177:13:177:41 | call to pair | TAINT | +| map.cpp:177:28:177:30 | c | map.cpp:177:13:177:26 | call to make_pair | TAINT | +| map.cpp:177:33:177:38 | call to source | map.cpp:177:13:177:26 | call to make_pair | TAINT | | map.cpp:178:2:178:4 | ref arg m14 | map.cpp:249:1:249:1 | m14 | | | map.cpp:178:13:178:26 | call to make_pair | map.cpp:178:13:178:36 | call to pair | TAINT | +| map.cpp:178:28:178:30 | d | map.cpp:178:13:178:26 | call to make_pair | TAINT | +| map.cpp:178:33:178:35 | d | map.cpp:178:13:178:26 | call to make_pair | TAINT | | map.cpp:179:7:179:8 | ref arg m2 | map.cpp:180:7:180:8 | m2 | | | map.cpp:179:7:179:8 | ref arg m2 | map.cpp:181:7:181:8 | m2 | | | map.cpp:179:7:179:8 | ref arg m2 | map.cpp:182:7:182:8 | m2 | | @@ -879,12 +935,16 @@ | map.cpp:188:2:188:4 | ref arg m15 | map.cpp:211:2:211:4 | m15 | | | map.cpp:188:2:188:4 | ref arg m15 | map.cpp:249:1:249:1 | m15 | | | map.cpp:188:13:188:57 | call to pair | map.cpp:188:13:188:57 | call to pair | TAINT | +| map.cpp:188:39:188:44 | call to source | map.cpp:188:13:188:57 | call to pair | TAINT | +| map.cpp:188:49:188:54 | call to source | map.cpp:188:13:188:57 | call to pair | TAINT | | map.cpp:189:2:189:4 | ref arg m18 | map.cpp:193:7:193:9 | m18 | | | map.cpp:189:2:189:4 | ref arg m18 | map.cpp:195:11:195:13 | m18 | | | map.cpp:189:2:189:4 | ref arg m18 | map.cpp:199:7:199:9 | m18 | | | map.cpp:189:2:189:4 | ref arg m18 | map.cpp:212:12:212:14 | m18 | | | map.cpp:189:2:189:4 | ref arg m18 | map.cpp:249:1:249:1 | m18 | | | map.cpp:189:13:189:57 | call to pair | map.cpp:189:13:189:57 | call to pair | TAINT | +| map.cpp:189:39:189:44 | call to source | map.cpp:189:13:189:57 | call to pair | TAINT | +| map.cpp:189:49:189:54 | call to source | map.cpp:189:13:189:57 | call to pair | TAINT | | map.cpp:190:7:190:9 | m15 | map.cpp:190:7:190:9 | call to map | | | map.cpp:191:7:191:9 | m16 | map.cpp:191:7:191:9 | call to map | | | map.cpp:192:7:192:9 | m17 | map.cpp:192:7:192:9 | call to map | | @@ -925,18 +985,26 @@ | map.cpp:203:2:203:4 | ref arg m19 | map.cpp:213:7:213:9 | m19 | | | map.cpp:203:2:203:4 | ref arg m19 | map.cpp:249:1:249:1 | m19 | | | map.cpp:203:13:203:57 | call to pair | map.cpp:203:13:203:57 | call to pair | TAINT | +| map.cpp:203:39:203:44 | call to source | map.cpp:203:13:203:57 | call to pair | TAINT | +| map.cpp:203:49:203:54 | call to source | map.cpp:203:13:203:57 | call to pair | TAINT | | map.cpp:204:2:204:4 | ref arg m20 | map.cpp:208:7:208:9 | m20 | | | map.cpp:204:2:204:4 | ref arg m20 | map.cpp:214:7:214:9 | m20 | | | map.cpp:204:2:204:4 | ref arg m20 | map.cpp:249:1:249:1 | m20 | | | map.cpp:204:13:204:51 | call to pair | map.cpp:204:13:204:51 | call to pair | TAINT | +| map.cpp:204:39:204:43 | abc | map.cpp:204:13:204:51 | call to pair | TAINT | +| map.cpp:204:46:204:50 | def | map.cpp:204:13:204:51 | call to pair | TAINT | | map.cpp:205:2:205:4 | ref arg m21 | map.cpp:209:7:209:9 | m21 | | | map.cpp:205:2:205:4 | ref arg m21 | map.cpp:215:7:215:9 | m21 | | | map.cpp:205:2:205:4 | ref arg m21 | map.cpp:249:1:249:1 | m21 | | | map.cpp:205:13:205:51 | call to pair | map.cpp:205:13:205:51 | call to pair | TAINT | +| map.cpp:205:39:205:43 | abc | map.cpp:205:13:205:51 | call to pair | TAINT | +| map.cpp:205:46:205:50 | def | map.cpp:205:13:205:51 | call to pair | TAINT | | map.cpp:206:2:206:4 | ref arg m22 | map.cpp:210:7:210:9 | m22 | | | map.cpp:206:2:206:4 | ref arg m22 | map.cpp:216:7:216:9 | m22 | | | map.cpp:206:2:206:4 | ref arg m22 | map.cpp:249:1:249:1 | m22 | | | map.cpp:206:13:206:57 | call to pair | map.cpp:206:13:206:57 | call to pair | TAINT | +| map.cpp:206:39:206:44 | call to source | map.cpp:206:13:206:57 | call to pair | TAINT | +| map.cpp:206:49:206:54 | call to source | map.cpp:206:13:206:57 | call to pair | TAINT | | map.cpp:207:7:207:9 | m19 | map.cpp:207:7:207:9 | call to map | | | map.cpp:208:7:208:9 | m20 | map.cpp:208:7:208:9 | call to map | | | map.cpp:209:7:209:9 | m21 | map.cpp:209:7:209:9 | call to map | | @@ -967,6 +1035,8 @@ | map.cpp:220:2:220:4 | ref arg m23 | map.cpp:226:7:226:9 | m23 | | | map.cpp:220:2:220:4 | ref arg m23 | map.cpp:249:1:249:1 | m23 | | | map.cpp:220:13:220:57 | call to pair | map.cpp:220:13:220:57 | call to pair | TAINT | +| map.cpp:220:39:220:44 | call to source | map.cpp:220:13:220:57 | call to pair | TAINT | +| map.cpp:220:49:220:54 | call to source | map.cpp:220:13:220:57 | call to pair | TAINT | | map.cpp:221:2:221:4 | ref arg m23 | map.cpp:222:7:222:9 | m23 | | | map.cpp:221:2:221:4 | ref arg m23 | map.cpp:223:7:223:9 | m23 | | | map.cpp:221:2:221:4 | ref arg m23 | map.cpp:223:17:223:19 | m23 | | @@ -975,6 +1045,8 @@ | map.cpp:221:2:221:4 | ref arg m23 | map.cpp:226:7:226:9 | m23 | | | map.cpp:221:2:221:4 | ref arg m23 | map.cpp:249:1:249:1 | m23 | | | map.cpp:221:13:221:57 | call to pair | map.cpp:221:13:221:57 | call to pair | TAINT | +| map.cpp:221:39:221:44 | call to source | map.cpp:221:13:221:57 | call to pair | TAINT | +| map.cpp:221:49:221:54 | call to source | map.cpp:221:13:221:57 | call to pair | TAINT | | map.cpp:222:7:222:9 | m23 | map.cpp:222:7:222:9 | call to map | | | map.cpp:223:7:223:9 | ref arg m23 | map.cpp:224:7:224:9 | m23 | | | map.cpp:223:7:223:9 | ref arg m23 | map.cpp:225:2:225:4 | m23 | | @@ -1124,6 +1196,8 @@ | map.cpp:256:7:256:8 | ref arg m1 | map.cpp:295:30:295:31 | m1 | | | map.cpp:256:7:256:8 | ref arg m1 | map.cpp:398:1:398:1 | m1 | | | map.cpp:256:17:256:30 | call to make_pair | map.cpp:256:17:256:44 | call to pair | TAINT | +| map.cpp:256:32:256:36 | abc | map.cpp:256:17:256:30 | call to make_pair | TAINT | +| map.cpp:256:39:256:43 | def | map.cpp:256:17:256:30 | call to make_pair | TAINT | | map.cpp:256:47:256:51 | first | map.cpp:256:7:256:51 | call to iterator | | | map.cpp:257:7:257:8 | ref arg m2 | map.cpp:263:7:263:8 | m2 | | | map.cpp:257:7:257:8 | ref arg m2 | map.cpp:269:7:269:8 | m2 | | @@ -1138,6 +1212,8 @@ | map.cpp:257:7:257:8 | ref arg m2 | map.cpp:333:7:333:8 | m2 | | | map.cpp:257:7:257:8 | ref arg m2 | map.cpp:398:1:398:1 | m2 | | | map.cpp:257:17:257:30 | call to make_pair | map.cpp:257:17:257:47 | call to pair | TAINT | +| map.cpp:257:32:257:36 | abc | map.cpp:257:17:257:30 | call to make_pair | TAINT | +| map.cpp:257:39:257:44 | call to source | map.cpp:257:17:257:30 | call to make_pair | TAINT | | map.cpp:257:50:257:54 | first | map.cpp:257:7:257:54 | call to iterator | | | map.cpp:258:7:258:8 | ref arg m3 | map.cpp:264:7:264:8 | m3 | | | map.cpp:258:7:258:8 | ref arg m3 | map.cpp:270:7:270:8 | m3 | | @@ -1146,6 +1222,8 @@ | map.cpp:258:7:258:8 | ref arg m3 | map.cpp:307:30:307:31 | m3 | | | map.cpp:258:7:258:8 | ref arg m3 | map.cpp:398:1:398:1 | m3 | | | map.cpp:258:17:258:30 | call to make_pair | map.cpp:258:17:258:47 | call to pair | TAINT | +| map.cpp:258:32:258:37 | call to source | map.cpp:258:17:258:30 | call to make_pair | TAINT | +| map.cpp:258:42:258:46 | def | map.cpp:258:17:258:30 | call to make_pair | TAINT | | map.cpp:258:50:258:54 | first | map.cpp:258:7:258:54 | call to iterator | | | map.cpp:259:7:259:8 | ref arg m4 | map.cpp:265:7:265:8 | m4 | | | map.cpp:259:7:259:8 | ref arg m4 | map.cpp:271:7:271:8 | m4 | | @@ -1158,6 +1236,8 @@ | map.cpp:259:17:259:18 | ref arg m4 | map.cpp:398:1:398:1 | m4 | | | map.cpp:259:20:259:24 | call to begin | map.cpp:259:17:259:26 | call to iterator | TAINT | | map.cpp:259:29:259:70 | call to pair | map.cpp:259:29:259:70 | call to pair | TAINT | +| map.cpp:259:55:259:59 | abc | map.cpp:259:29:259:70 | call to pair | TAINT | +| map.cpp:259:62:259:67 | call to source | map.cpp:259:29:259:70 | call to pair | TAINT | | map.cpp:260:7:260:8 | ref arg m5 | map.cpp:266:7:266:8 | m5 | | | map.cpp:260:7:260:8 | ref arg m5 | map.cpp:272:7:272:8 | m5 | | | map.cpp:260:7:260:8 | ref arg m5 | map.cpp:278:7:278:8 | m5 | | @@ -1352,15 +1432,23 @@ | map.cpp:327:2:327:4 | ref arg m14 | map.cpp:330:2:330:4 | m14 | | | map.cpp:327:2:327:4 | ref arg m14 | map.cpp:398:1:398:1 | m14 | | | map.cpp:327:13:327:26 | call to make_pair | map.cpp:327:13:327:36 | call to pair | TAINT | +| map.cpp:327:28:327:30 | a | map.cpp:327:13:327:26 | call to make_pair | TAINT | +| map.cpp:327:33:327:35 | a | map.cpp:327:13:327:26 | call to make_pair | TAINT | | map.cpp:328:2:328:4 | ref arg m14 | map.cpp:329:2:329:4 | m14 | | | map.cpp:328:2:328:4 | ref arg m14 | map.cpp:330:2:330:4 | m14 | | | map.cpp:328:2:328:4 | ref arg m14 | map.cpp:398:1:398:1 | m14 | | | map.cpp:328:13:328:26 | call to make_pair | map.cpp:328:13:328:41 | call to pair | TAINT | +| map.cpp:328:28:328:30 | b | map.cpp:328:13:328:26 | call to make_pair | TAINT | +| map.cpp:328:33:328:38 | call to source | map.cpp:328:13:328:26 | call to make_pair | TAINT | | map.cpp:329:2:329:4 | ref arg m14 | map.cpp:330:2:330:4 | m14 | | | map.cpp:329:2:329:4 | ref arg m14 | map.cpp:398:1:398:1 | m14 | | | map.cpp:329:13:329:26 | call to make_pair | map.cpp:329:13:329:41 | call to pair | TAINT | +| map.cpp:329:28:329:30 | c | map.cpp:329:13:329:26 | call to make_pair | TAINT | +| map.cpp:329:33:329:38 | call to source | map.cpp:329:13:329:26 | call to make_pair | TAINT | | map.cpp:330:2:330:4 | ref arg m14 | map.cpp:398:1:398:1 | m14 | | | map.cpp:330:13:330:26 | call to make_pair | map.cpp:330:13:330:36 | call to pair | TAINT | +| map.cpp:330:28:330:30 | d | map.cpp:330:13:330:26 | call to make_pair | TAINT | +| map.cpp:330:33:330:35 | d | map.cpp:330:13:330:26 | call to make_pair | TAINT | | map.cpp:331:7:331:8 | ref arg m2 | map.cpp:332:7:332:8 | m2 | | | map.cpp:331:7:331:8 | ref arg m2 | map.cpp:333:7:333:8 | m2 | | | map.cpp:331:7:331:8 | ref arg m2 | map.cpp:398:1:398:1 | m2 | | @@ -1398,12 +1486,16 @@ | map.cpp:337:2:337:4 | ref arg m15 | map.cpp:360:2:360:4 | m15 | | | map.cpp:337:2:337:4 | ref arg m15 | map.cpp:398:1:398:1 | m15 | | | map.cpp:337:13:337:57 | call to pair | map.cpp:337:13:337:57 | call to pair | TAINT | +| map.cpp:337:39:337:44 | call to source | map.cpp:337:13:337:57 | call to pair | TAINT | +| map.cpp:337:49:337:54 | call to source | map.cpp:337:13:337:57 | call to pair | TAINT | | map.cpp:338:2:338:4 | ref arg m18 | map.cpp:342:7:342:9 | m18 | | | map.cpp:338:2:338:4 | ref arg m18 | map.cpp:344:11:344:13 | m18 | | | map.cpp:338:2:338:4 | ref arg m18 | map.cpp:348:7:348:9 | m18 | | | map.cpp:338:2:338:4 | ref arg m18 | map.cpp:361:12:361:14 | m18 | | | map.cpp:338:2:338:4 | ref arg m18 | map.cpp:398:1:398:1 | m18 | | | map.cpp:338:13:338:57 | call to pair | map.cpp:338:13:338:57 | call to pair | TAINT | +| map.cpp:338:39:338:44 | call to source | map.cpp:338:13:338:57 | call to pair | TAINT | +| map.cpp:338:49:338:54 | call to source | map.cpp:338:13:338:57 | call to pair | TAINT | | map.cpp:339:7:339:9 | m15 | map.cpp:339:7:339:9 | call to unordered_map | | | map.cpp:340:7:340:9 | m16 | map.cpp:340:7:340:9 | call to unordered_map | | | map.cpp:341:7:341:9 | m17 | map.cpp:341:7:341:9 | call to unordered_map | | @@ -1444,18 +1536,26 @@ | map.cpp:352:2:352:4 | ref arg m19 | map.cpp:362:7:362:9 | m19 | | | map.cpp:352:2:352:4 | ref arg m19 | map.cpp:398:1:398:1 | m19 | | | map.cpp:352:13:352:57 | call to pair | map.cpp:352:13:352:57 | call to pair | TAINT | +| map.cpp:352:39:352:44 | call to source | map.cpp:352:13:352:57 | call to pair | TAINT | +| map.cpp:352:49:352:54 | call to source | map.cpp:352:13:352:57 | call to pair | TAINT | | map.cpp:353:2:353:4 | ref arg m20 | map.cpp:357:7:357:9 | m20 | | | map.cpp:353:2:353:4 | ref arg m20 | map.cpp:363:7:363:9 | m20 | | | map.cpp:353:2:353:4 | ref arg m20 | map.cpp:398:1:398:1 | m20 | | | map.cpp:353:13:353:51 | call to pair | map.cpp:353:13:353:51 | call to pair | TAINT | +| map.cpp:353:39:353:43 | abc | map.cpp:353:13:353:51 | call to pair | TAINT | +| map.cpp:353:46:353:50 | def | map.cpp:353:13:353:51 | call to pair | TAINT | | map.cpp:354:2:354:4 | ref arg m21 | map.cpp:358:7:358:9 | m21 | | | map.cpp:354:2:354:4 | ref arg m21 | map.cpp:364:7:364:9 | m21 | | | map.cpp:354:2:354:4 | ref arg m21 | map.cpp:398:1:398:1 | m21 | | | map.cpp:354:13:354:51 | call to pair | map.cpp:354:13:354:51 | call to pair | TAINT | +| map.cpp:354:39:354:43 | abc | map.cpp:354:13:354:51 | call to pair | TAINT | +| map.cpp:354:46:354:50 | def | map.cpp:354:13:354:51 | call to pair | TAINT | | map.cpp:355:2:355:4 | ref arg m22 | map.cpp:359:7:359:9 | m22 | | | map.cpp:355:2:355:4 | ref arg m22 | map.cpp:365:7:365:9 | m22 | | | map.cpp:355:2:355:4 | ref arg m22 | map.cpp:398:1:398:1 | m22 | | | map.cpp:355:13:355:57 | call to pair | map.cpp:355:13:355:57 | call to pair | TAINT | +| map.cpp:355:39:355:44 | call to source | map.cpp:355:13:355:57 | call to pair | TAINT | +| map.cpp:355:49:355:54 | call to source | map.cpp:355:13:355:57 | call to pair | TAINT | | map.cpp:356:7:356:9 | m19 | map.cpp:356:7:356:9 | call to unordered_map | | | map.cpp:357:7:357:9 | m20 | map.cpp:357:7:357:9 | call to unordered_map | | | map.cpp:358:7:358:9 | m21 | map.cpp:358:7:358:9 | call to unordered_map | | @@ -1486,6 +1586,8 @@ | map.cpp:369:2:369:4 | ref arg m23 | map.cpp:375:7:375:9 | m23 | | | map.cpp:369:2:369:4 | ref arg m23 | map.cpp:398:1:398:1 | m23 | | | map.cpp:369:13:369:57 | call to pair | map.cpp:369:13:369:57 | call to pair | TAINT | +| map.cpp:369:39:369:44 | call to source | map.cpp:369:13:369:57 | call to pair | TAINT | +| map.cpp:369:49:369:54 | call to source | map.cpp:369:13:369:57 | call to pair | TAINT | | map.cpp:370:2:370:4 | ref arg m23 | map.cpp:371:7:371:9 | m23 | | | map.cpp:370:2:370:4 | ref arg m23 | map.cpp:372:7:372:9 | m23 | | | map.cpp:370:2:370:4 | ref arg m23 | map.cpp:372:17:372:19 | m23 | | @@ -1494,6 +1596,8 @@ | map.cpp:370:2:370:4 | ref arg m23 | map.cpp:375:7:375:9 | m23 | | | map.cpp:370:2:370:4 | ref arg m23 | map.cpp:398:1:398:1 | m23 | | | map.cpp:370:13:370:57 | call to pair | map.cpp:370:13:370:57 | call to pair | TAINT | +| map.cpp:370:39:370:44 | call to source | map.cpp:370:13:370:57 | call to pair | TAINT | +| map.cpp:370:49:370:54 | call to source | map.cpp:370:13:370:57 | call to pair | TAINT | | map.cpp:371:7:371:9 | m23 | map.cpp:371:7:371:9 | call to unordered_map | | | map.cpp:372:7:372:9 | ref arg m23 | map.cpp:373:7:373:9 | m23 | | | map.cpp:372:7:372:9 | ref arg m23 | map.cpp:374:2:374:4 | m23 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp index ae8ad331518..03c5697c396 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp @@ -38,25 +38,25 @@ void test_pair() sink(d); std::pair e(source(), "456"); - sink(e.first); // tainted [NOT DETECTED] - sink(e.second); - sink(e); // tainted [NOT DETECTED] + sink(e.first); // tainted + sink(e.second); // [FALSE POSITIVE] + sink(e); // tainted std::pair f("123", source()); - sink(f.first); - sink(f.second); // tainted [NOT DETECTED] - sink(f); // tainted [NOT DETECTED] + sink(f.first); // [FALSE POSITIVE] + sink(f.second); // tainted + sink(f); // tainted std::pair g(f); - sink(g.first); - sink(g.second); // tainted [NOT DETECTED] - sink(g); // tainted [NOT DETECTED] - + sink(g.first); // [FALSE POSITIVE] + sink(g.second); // tainted + sink(g); // tainted + std::pair h; h = f; - sink(h.first); - sink(h.second); // tainted [NOT DETECTED] - sink(h); // tainted [NOT DETECTED] + sink(h.first); // [FALSE POSITIVE] + sink(h.second); // tainted + sink(h); // tainted std::pair i("123", "456"); std::pair j("123", source()); @@ -64,35 +64,35 @@ void test_pair() std::pair l("123", "456"); i.swap(j); k.swap(l); - sink(i.first); - sink(i.second); // tainted [NOT DETECTED] - sink(i); // tainted [NOT DETECTED] - sink(j.first); - sink(j.second); - sink(j); - sink(k.first); - sink(k.second); - sink(k); - sink(l.first); - sink(l.second); // tainted [NOT DETECTED] - sink(l); // tainted [NOT DETECTED] + sink(i.first); // [FALSE POSITIVE] + sink(i.second); // tainted + sink(i); // tainted + sink(j.first); // [FALSE POSITIVE] + sink(j.second); // [FALSE POSITIVE] + sink(j); // [FALSE POSITIVE] + sink(k.first); // [FALSE POSITIVE] + sink(k.second); // [FALSE POSITIVE] + sink(k); // [FALSE POSITIVE] + sink(l.first); // [FALSE POSITIVE] + sink(l.second); // tainted + sink(l); // tainted sink(make_pair("123", "456")); sink(make_pair("123", "456").first); sink(make_pair("123", "456").second); - sink(make_pair(source(), "456")); // tainted [NOT DETECTED] - sink(make_pair(source(), "456").first); // tainted [NOT DETECTED] - sink(make_pair(source(), "456").second); - sink(make_pair("123", source())); // tainted [NOT DETECTED] - sink(make_pair("123", source()).first); - sink(make_pair("123", source()).second); // tainted [NOT DETECTED] + sink(make_pair(source(), "456")); // tainted + sink(make_pair(source(), "456").first); // tainted + sink(make_pair(source(), "456").second); // [FALSE POSITIVE] + sink(make_pair("123", source())); // tainted + sink(make_pair("123", source()).first); // [FALSE POSITIVE] + sink(make_pair("123", source()).second); // tainted std::pair, char *> m; m = make_pair(make_pair("123", source()), "789"); - sink(m); // tainted [NOT DETECTED] - sink(m.first); // tainted [NOT DETECTED] - sink(m.first.first); - sink(m.first.second); // tainted [NOT DETECTED] + sink(m); // tainted + sink(m.first); // tainted + sink(m.first.first); // [FALSE POSITIVE] + sink(m.first.second); // tainted sink(m.second); } 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 f8db8d30418..f046ca21988 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -35,6 +35,17 @@ | format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source | | map.cpp:26:9:26:13 | first | map.cpp:25:12:25:17 | call to source | | map.cpp:32:9:32:14 | second | map.cpp:30:13:30:18 | call to source | +| map.cpp:43:7:43:7 | e | map.cpp:40:30:40:35 | call to source | +| map.cpp:48:7:48:7 | f | map.cpp:45:37:45:42 | call to source | +| map.cpp:53:7:53:7 | g | map.cpp:45:37:45:42 | call to source | +| map.cpp:59:7:59:7 | h | map.cpp:45:37:45:42 | call to source | +| map.cpp:69:7:69:7 | i | map.cpp:62:37:62:42 | call to source | +| map.cpp:72:7:72:7 | j | map.cpp:62:37:62:42 | call to source | +| map.cpp:75:7:75:7 | k | map.cpp:63:37:63:42 | call to source | +| map.cpp:78:7:78:7 | l | map.cpp:63:37:63:42 | call to source | +| map.cpp:83:7:83:32 | call to pair | map.cpp:83:17:83:22 | call to source | +| map.cpp:86:7:86:32 | call to pair | map.cpp:86:24:86:29 | call to source | +| map.cpp:92:7:92:7 | call to pair | map.cpp:91:33:91:38 | call to source | | map.cpp:165:7:165:27 | ... = ... | map.cpp:165:20:165:25 | call to source | | map.cpp:167:7:167:30 | ... = ... | map.cpp:167:23:167:28 | call to source | | map.cpp:317:7:317:27 | ... = ... | map.cpp:317:20:317:25 | 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 2291a42f1ac..3722b7337ad 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 @@ -17,6 +17,31 @@ | copyableclass.cpp:67:11:67:21 | copyableclass.cpp:67:13:67:18 | IR only | | copyableclass_declonly.cpp:42:8:42:9 | copyableclass_declonly.cpp:34:30:34:35 | AST only | | copyableclass_declonly.cpp:67:11:67:11 | copyableclass_declonly.cpp:67:13:67:18 | AST only | +| map.cpp:41:9:41:13 | map.cpp:40:30:40:35 | IR only | +| map.cpp:42:9:42:14 | map.cpp:40:30:40:35 | IR only | +| map.cpp:46:9:46:13 | map.cpp:45:37:45:42 | IR only | +| map.cpp:47:9:47:14 | map.cpp:45:37:45:42 | IR only | +| map.cpp:51:9:51:13 | map.cpp:45:37:45:42 | IR only | +| map.cpp:52:9:52:14 | map.cpp:45:37:45:42 | IR only | +| map.cpp:57:9:57:13 | map.cpp:45:37:45:42 | IR only | +| map.cpp:58:9:58:14 | map.cpp:45:37:45:42 | IR only | +| map.cpp:67:9:67:13 | map.cpp:62:37:62:42 | IR only | +| map.cpp:68:9:68:14 | map.cpp:62:37:62:42 | IR only | +| map.cpp:70:9:70:13 | map.cpp:62:37:62:42 | IR only | +| map.cpp:71:9:71:14 | map.cpp:62:37:62:42 | IR only | +| map.cpp:73:9:73:13 | map.cpp:63:37:63:42 | IR only | +| map.cpp:74:9:74:14 | map.cpp:63:37:63:42 | IR only | +| map.cpp:76:9:76:13 | map.cpp:63:37:63:42 | IR only | +| map.cpp:77:9:77:14 | map.cpp:63:37:63:42 | IR only | +| map.cpp:84:34:84:38 | map.cpp:84:17:84:22 | IR only | +| map.cpp:85:34:85:39 | map.cpp:85:17:85:22 | IR only | +| map.cpp:87:34:87:38 | map.cpp:87:24:87:29 | IR only | +| map.cpp:88:34:88:39 | map.cpp:88:24:88:29 | IR only | +| map.cpp:92:7:92:7 | map.cpp:91:33:91:38 | AST only | +| map.cpp:93:9:93:13 | map.cpp:91:33:91:38 | IR only | +| map.cpp:94:15:94:19 | map.cpp:91:33:91:38 | IR only | +| map.cpp:95:15:95:20 | map.cpp:91:33:91:38 | IR only | +| map.cpp:96:9:96:14 | map.cpp:91:33:91:38 | IR only | | movableclass.cpp:65:11:65:11 | movableclass.cpp:65:13:65:18 | AST only | | movableclass.cpp:65:11:65:21 | movableclass.cpp:65:13:65:18 | IR only | | smart_pointer.cpp:12:10:12:10 | smart_pointer.cpp:11:52:11:57 | 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 24ebc1469a2..ccdc330c7e2 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 @@ -44,6 +44,40 @@ | format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source | | map.cpp:26:9:26:13 | first | map.cpp:25:12:25:17 | call to source | | map.cpp:32:9:32:14 | second | map.cpp:30:13:30:18 | call to source | +| map.cpp:41:9:41:13 | first | map.cpp:40:30:40:35 | call to source | +| map.cpp:42:9:42:14 | second | map.cpp:40:30:40:35 | call to source | +| map.cpp:43:7:43:7 | e | map.cpp:40:30:40:35 | call to source | +| map.cpp:46:9:46:13 | first | map.cpp:45:37:45:42 | call to source | +| map.cpp:47:9:47:14 | second | map.cpp:45:37:45:42 | call to source | +| map.cpp:48:7:48:7 | f | map.cpp:45:37:45:42 | call to source | +| map.cpp:51:9:51:13 | first | map.cpp:45:37:45:42 | call to source | +| map.cpp:52:9:52:14 | second | map.cpp:45:37:45:42 | call to source | +| map.cpp:53:7:53:7 | g | map.cpp:45:37:45:42 | call to source | +| map.cpp:57:9:57:13 | first | map.cpp:45:37:45:42 | call to source | +| map.cpp:58:9:58:14 | second | map.cpp:45:37:45:42 | call to source | +| map.cpp:59:7:59:7 | h | map.cpp:45:37:45:42 | call to source | +| map.cpp:67:9:67:13 | first | map.cpp:62:37:62:42 | call to source | +| map.cpp:68:9:68:14 | second | map.cpp:62:37:62:42 | call to source | +| map.cpp:69:7:69:7 | i | map.cpp:62:37:62:42 | call to source | +| map.cpp:70:9:70:13 | first | map.cpp:62:37:62:42 | call to source | +| map.cpp:71:9:71:14 | second | map.cpp:62:37:62:42 | call to source | +| map.cpp:72:7:72:7 | j | map.cpp:62:37:62:42 | call to source | +| map.cpp:73:9:73:13 | first | map.cpp:63:37:63:42 | call to source | +| map.cpp:74:9:74:14 | second | map.cpp:63:37:63:42 | call to source | +| map.cpp:75:7:75:7 | k | map.cpp:63:37:63:42 | call to source | +| map.cpp:76:9:76:13 | first | map.cpp:63:37:63:42 | call to source | +| map.cpp:77:9:77:14 | second | map.cpp:63:37:63:42 | call to source | +| map.cpp:78:7:78:7 | l | map.cpp:63:37:63:42 | call to source | +| map.cpp:83:7:83:32 | call to pair | map.cpp:83:17:83:22 | call to source | +| map.cpp:84:34:84:38 | first | map.cpp:84:17:84:22 | call to source | +| map.cpp:85:34:85:39 | second | map.cpp:85:17:85:22 | call to source | +| map.cpp:86:7:86:32 | call to pair | map.cpp:86:24:86:29 | call to source | +| map.cpp:87:34:87:38 | first | map.cpp:87:24:87:29 | call to source | +| map.cpp:88:34:88:39 | second | map.cpp:88:24:88:29 | call to source | +| map.cpp:93:9:93:13 | first | map.cpp:91:33:91:38 | call to source | +| map.cpp:94:15:94:19 | first | map.cpp:91:33:91:38 | call to source | +| map.cpp:95:15:95:20 | second | map.cpp:91:33:91:38 | call to source | +| map.cpp:96:9:96:14 | second | map.cpp:91:33:91:38 | call to source | | map.cpp:165:7:165:27 | ... = ... | map.cpp:165:20:165:25 | call to source | | map.cpp:167:7:167:30 | ... = ... | map.cpp:167:23:167:28 | call to source | | map.cpp:317:7:317:27 | ... = ... | map.cpp:317:20:317:25 | call to source | From 094b06ec2accc225ba57df0a1686e972d700d252 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 24 Sep 2020 10:37:38 -0700 Subject: [PATCH 047/411] C++: remove unneeded predicate --- .../src/semmle/code/cpp/models/implementations/Iterator.qll | 6 ------ cpp/ql/src/semmle/code/cpp/models/interfaces/Iterator.qll | 1 - 2 files changed, 7 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll index c1b8e24e7db..ded937d5312 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll @@ -93,8 +93,6 @@ class IteratorPointerDereferenceOperator extends Operator, TaintFunction, Iterat input = iteratorInput and output.isReturnValue() } - - override FunctionInput getIteratorInput() { result = iteratorInput } } /** @@ -179,8 +177,6 @@ class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunc this.getDeclaringType() instanceof Iterator } - override FunctionInput getIteratorInput() { result.isQualifierObject() } - override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isQualifierObject() and output.isReturnValue() @@ -276,8 +272,6 @@ class IteratorArrayMemberOperator extends MemberFunction, TaintFunction, Iterato input.isQualifierObject() and output.isReturnValue() } - - override FunctionInput getIteratorInput() { result.isQualifierObject() } } /** diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/Iterator.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/Iterator.qll index ea9ce04e530..1086e088979 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/Iterator.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/Iterator.qll @@ -15,5 +15,4 @@ import semmle.code.cpp.models.Models * can be used to write to the iterator's underlying collection. */ abstract class IteratorReferenceFunction extends Function { - abstract FunctionInput getIteratorInput(); } From 25e0c680c6a04c91194e34dc036693189c788ed6 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Sep 2020 13:18:17 +0100 Subject: [PATCH 048/411] C++: Model insert. --- cpp/ql/src/semmle/code/cpp/models/Models.qll | 1 + .../cpp/models/implementations/StdMap.qll | 25 +++++++ .../dataflow/taint-tests/localTaint.expected | 64 +++++++++++++++++ .../dataflow/taint-tests/map.cpp | 72 +++++++++---------- .../dataflow/taint-tests/taint.expected | 70 ++++++++++++++++++ .../dataflow/taint-tests/test_diff.expected | 72 +++++++++++++++++++ .../dataflow/taint-tests/test_ir.expected | 6 ++ 7 files changed, 274 insertions(+), 36 deletions(-) create mode 100644 cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll diff --git a/cpp/ql/src/semmle/code/cpp/models/Models.qll b/cpp/ql/src/semmle/code/cpp/models/Models.qll index e950096ac47..7df1edc34ac 100644 --- a/cpp/ql/src/semmle/code/cpp/models/Models.qll +++ b/cpp/ql/src/semmle/code/cpp/models/Models.qll @@ -16,6 +16,7 @@ private import implementations.Strdup private import implementations.Strftime private import implementations.StdContainer private import implementations.StdPair +private import implementations.StdMap private import implementations.StdString private import implementations.Swap private import implementations.GetDelim diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll new file mode 100644 index 00000000000..f6ac66091f5 --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll @@ -0,0 +1,25 @@ +/** + * Provides models for C++ containers `std::map` and `std::unordered_map`. + */ + +import semmle.code.cpp.models.interfaces.Taint +import semmle.code.cpp.models.implementations.Iterator + +/** + * The standard map `insert` function. + */ +class StdMapInsert extends TaintFunction { + StdMapInsert() { + this.hasQualifiedName("std", ["map", "unordered_map"], "insert") + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from last parameter to qualifier and return value + // (where the return value is a pair, this should really flow just to the first part of it) + input.isParameterDeref(getNumberOfParameters() - 1) and + ( + output.isQualifierObject() or + output.isReturnValue() + ) + } +} 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 4e7a5cee79b..52944e7cdbe 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -615,6 +615,8 @@ | map.cpp:104:7:104:8 | ref arg m1 | map.cpp:143:30:143:31 | m1 | | | map.cpp:104:7:104:8 | ref arg m1 | map.cpp:249:1:249:1 | m1 | | | map.cpp:104:17:104:30 | call to make_pair | map.cpp:104:17:104:44 | call to pair | TAINT | +| map.cpp:104:17:104:44 | call to pair | map.cpp:104:7:104:8 | ref arg m1 | TAINT | +| map.cpp:104:17:104:44 | call to pair | map.cpp:104:10:104:15 | call to insert | TAINT | | map.cpp:104:32:104:36 | abc | map.cpp:104:17:104:30 | call to make_pair | TAINT | | map.cpp:104:39:104:43 | def | map.cpp:104:17:104:30 | call to make_pair | TAINT | | map.cpp:104:47:104:51 | first | map.cpp:104:7:104:51 | call to iterator | | @@ -634,6 +636,8 @@ | map.cpp:105:7:105:8 | ref arg m2 | map.cpp:184:7:184:8 | m2 | | | map.cpp:105:7:105:8 | ref arg m2 | map.cpp:249:1:249:1 | m2 | | | map.cpp:105:17:105:30 | call to make_pair | map.cpp:105:17:105:47 | call to pair | TAINT | +| map.cpp:105:17:105:47 | call to pair | map.cpp:105:7:105:8 | ref arg m2 | TAINT | +| map.cpp:105:17:105:47 | call to pair | map.cpp:105:10:105:15 | call to insert | TAINT | | map.cpp:105:32:105:36 | abc | map.cpp:105:17:105:30 | call to make_pair | TAINT | | map.cpp:105:39:105:44 | call to source | map.cpp:105:17:105:30 | call to make_pair | TAINT | | map.cpp:105:50:105:54 | first | map.cpp:105:7:105:54 | call to iterator | | @@ -644,6 +648,8 @@ | map.cpp:106:7:106:8 | ref arg m3 | map.cpp:155:30:155:31 | m3 | | | map.cpp:106:7:106:8 | ref arg m3 | map.cpp:249:1:249:1 | m3 | | | map.cpp:106:17:106:30 | call to make_pair | map.cpp:106:17:106:47 | call to pair | TAINT | +| map.cpp:106:17:106:47 | call to pair | map.cpp:106:7:106:8 | ref arg m3 | TAINT | +| map.cpp:106:17:106:47 | call to pair | map.cpp:106:10:106:15 | call to insert | TAINT | | map.cpp:106:32:106:37 | call to source | map.cpp:106:17:106:30 | call to make_pair | TAINT | | map.cpp:106:42:106:46 | def | map.cpp:106:17:106:30 | call to make_pair | TAINT | | map.cpp:106:50:106:54 | first | map.cpp:106:7:106:54 | call to iterator | | @@ -657,6 +663,8 @@ | map.cpp:107:17:107:18 | ref arg m4 | map.cpp:125:7:125:8 | m4 | | | map.cpp:107:17:107:18 | ref arg m4 | map.cpp:249:1:249:1 | m4 | | | map.cpp:107:20:107:24 | call to begin | map.cpp:107:17:107:26 | call to iterator | TAINT | +| map.cpp:107:29:107:70 | call to pair | map.cpp:107:7:107:8 | ref arg m4 | TAINT | +| map.cpp:107:29:107:70 | call to pair | map.cpp:107:10:107:15 | call to insert | TAINT | | map.cpp:107:29:107:70 | call to pair | map.cpp:107:29:107:70 | call to pair | TAINT | | map.cpp:107:55:107:59 | abc | map.cpp:107:29:107:70 | call to pair | TAINT | | map.cpp:107:62:107:67 | call to source | map.cpp:107:29:107:70 | call to pair | TAINT | @@ -866,21 +874,29 @@ | map.cpp:175:2:175:4 | ref arg m14 | map.cpp:178:2:178:4 | m14 | | | map.cpp:175:2:175:4 | ref arg m14 | map.cpp:249:1:249:1 | m14 | | | map.cpp:175:13:175:26 | call to make_pair | map.cpp:175:13:175:36 | call to pair | TAINT | +| map.cpp:175:13:175:36 | call to pair | map.cpp:175:2:175:4 | ref arg m14 | TAINT | +| map.cpp:175:13:175:36 | call to pair | map.cpp:175:6:175:11 | call to insert | TAINT | | map.cpp:175:28:175:30 | a | map.cpp:175:13:175:26 | call to make_pair | TAINT | | map.cpp:175:33:175:35 | a | map.cpp:175:13:175:26 | call to make_pair | TAINT | | map.cpp:176:2:176:4 | ref arg m14 | map.cpp:177:2:177:4 | m14 | | | map.cpp:176:2:176:4 | ref arg m14 | map.cpp:178:2:178:4 | m14 | | | map.cpp:176:2:176:4 | ref arg m14 | map.cpp:249:1:249:1 | m14 | | | map.cpp:176:13:176:26 | call to make_pair | map.cpp:176:13:176:41 | call to pair | TAINT | +| map.cpp:176:13:176:41 | call to pair | map.cpp:176:2:176:4 | ref arg m14 | TAINT | +| map.cpp:176:13:176:41 | call to pair | map.cpp:176:6:176:11 | call to insert | TAINT | | map.cpp:176:28:176:30 | b | map.cpp:176:13:176:26 | call to make_pair | TAINT | | map.cpp:176:33:176:38 | call to source | map.cpp:176:13:176:26 | call to make_pair | TAINT | | map.cpp:177:2:177:4 | ref arg m14 | map.cpp:178:2:178:4 | m14 | | | map.cpp:177:2:177:4 | ref arg m14 | map.cpp:249:1:249:1 | m14 | | | map.cpp:177:13:177:26 | call to make_pair | map.cpp:177:13:177:41 | call to pair | TAINT | +| map.cpp:177:13:177:41 | call to pair | map.cpp:177:2:177:4 | ref arg m14 | TAINT | +| map.cpp:177:13:177:41 | call to pair | map.cpp:177:6:177:11 | call to insert | TAINT | | map.cpp:177:28:177:30 | c | map.cpp:177:13:177:26 | call to make_pair | TAINT | | map.cpp:177:33:177:38 | call to source | map.cpp:177:13:177:26 | call to make_pair | TAINT | | map.cpp:178:2:178:4 | ref arg m14 | map.cpp:249:1:249:1 | m14 | | | map.cpp:178:13:178:26 | call to make_pair | map.cpp:178:13:178:36 | call to pair | TAINT | +| map.cpp:178:13:178:36 | call to pair | map.cpp:178:2:178:4 | ref arg m14 | TAINT | +| map.cpp:178:13:178:36 | call to pair | map.cpp:178:6:178:11 | call to insert | TAINT | | map.cpp:178:28:178:30 | d | map.cpp:178:13:178:26 | call to make_pair | TAINT | | map.cpp:178:33:178:35 | d | map.cpp:178:13:178:26 | call to make_pair | TAINT | | map.cpp:179:7:179:8 | ref arg m2 | map.cpp:180:7:180:8 | m2 | | @@ -934,6 +950,8 @@ | map.cpp:188:2:188:4 | ref arg m15 | map.cpp:196:7:196:9 | m15 | | | map.cpp:188:2:188:4 | ref arg m15 | map.cpp:211:2:211:4 | m15 | | | map.cpp:188:2:188:4 | ref arg m15 | map.cpp:249:1:249:1 | m15 | | +| map.cpp:188:13:188:57 | call to pair | map.cpp:188:2:188:4 | ref arg m15 | TAINT | +| map.cpp:188:13:188:57 | call to pair | map.cpp:188:6:188:11 | call to insert | TAINT | | map.cpp:188:13:188:57 | call to pair | map.cpp:188:13:188:57 | call to pair | TAINT | | map.cpp:188:39:188:44 | call to source | map.cpp:188:13:188:57 | call to pair | TAINT | | map.cpp:188:49:188:54 | call to source | map.cpp:188:13:188:57 | call to pair | TAINT | @@ -942,6 +960,8 @@ | map.cpp:189:2:189:4 | ref arg m18 | map.cpp:199:7:199:9 | m18 | | | map.cpp:189:2:189:4 | ref arg m18 | map.cpp:212:12:212:14 | m18 | | | map.cpp:189:2:189:4 | ref arg m18 | map.cpp:249:1:249:1 | m18 | | +| map.cpp:189:13:189:57 | call to pair | map.cpp:189:2:189:4 | ref arg m18 | TAINT | +| map.cpp:189:13:189:57 | call to pair | map.cpp:189:6:189:11 | call to insert | TAINT | | map.cpp:189:13:189:57 | call to pair | map.cpp:189:13:189:57 | call to pair | TAINT | | map.cpp:189:39:189:44 | call to source | map.cpp:189:13:189:57 | call to pair | TAINT | | map.cpp:189:49:189:54 | call to source | map.cpp:189:13:189:57 | call to pair | TAINT | @@ -984,24 +1004,32 @@ | map.cpp:203:2:203:4 | ref arg m19 | map.cpp:207:7:207:9 | m19 | | | map.cpp:203:2:203:4 | ref arg m19 | map.cpp:213:7:213:9 | m19 | | | map.cpp:203:2:203:4 | ref arg m19 | map.cpp:249:1:249:1 | m19 | | +| map.cpp:203:13:203:57 | call to pair | map.cpp:203:2:203:4 | ref arg m19 | TAINT | +| map.cpp:203:13:203:57 | call to pair | map.cpp:203:6:203:11 | call to insert | TAINT | | map.cpp:203:13:203:57 | call to pair | map.cpp:203:13:203:57 | call to pair | TAINT | | map.cpp:203:39:203:44 | call to source | map.cpp:203:13:203:57 | call to pair | TAINT | | map.cpp:203:49:203:54 | call to source | map.cpp:203:13:203:57 | call to pair | TAINT | | map.cpp:204:2:204:4 | ref arg m20 | map.cpp:208:7:208:9 | m20 | | | map.cpp:204:2:204:4 | ref arg m20 | map.cpp:214:7:214:9 | m20 | | | map.cpp:204:2:204:4 | ref arg m20 | map.cpp:249:1:249:1 | m20 | | +| map.cpp:204:13:204:51 | call to pair | map.cpp:204:2:204:4 | ref arg m20 | TAINT | +| map.cpp:204:13:204:51 | call to pair | map.cpp:204:6:204:11 | call to insert | TAINT | | map.cpp:204:13:204:51 | call to pair | map.cpp:204:13:204:51 | call to pair | TAINT | | map.cpp:204:39:204:43 | abc | map.cpp:204:13:204:51 | call to pair | TAINT | | map.cpp:204:46:204:50 | def | map.cpp:204:13:204:51 | call to pair | TAINT | | map.cpp:205:2:205:4 | ref arg m21 | map.cpp:209:7:209:9 | m21 | | | map.cpp:205:2:205:4 | ref arg m21 | map.cpp:215:7:215:9 | m21 | | | map.cpp:205:2:205:4 | ref arg m21 | map.cpp:249:1:249:1 | m21 | | +| map.cpp:205:13:205:51 | call to pair | map.cpp:205:2:205:4 | ref arg m21 | TAINT | +| map.cpp:205:13:205:51 | call to pair | map.cpp:205:6:205:11 | call to insert | TAINT | | map.cpp:205:13:205:51 | call to pair | map.cpp:205:13:205:51 | call to pair | TAINT | | map.cpp:205:39:205:43 | abc | map.cpp:205:13:205:51 | call to pair | TAINT | | map.cpp:205:46:205:50 | def | map.cpp:205:13:205:51 | call to pair | TAINT | | map.cpp:206:2:206:4 | ref arg m22 | map.cpp:210:7:210:9 | m22 | | | map.cpp:206:2:206:4 | ref arg m22 | map.cpp:216:7:216:9 | m22 | | | map.cpp:206:2:206:4 | ref arg m22 | map.cpp:249:1:249:1 | m22 | | +| map.cpp:206:13:206:57 | call to pair | map.cpp:206:2:206:4 | ref arg m22 | TAINT | +| map.cpp:206:13:206:57 | call to pair | map.cpp:206:6:206:11 | call to insert | TAINT | | map.cpp:206:13:206:57 | call to pair | map.cpp:206:13:206:57 | call to pair | TAINT | | map.cpp:206:39:206:44 | call to source | map.cpp:206:13:206:57 | call to pair | TAINT | | map.cpp:206:49:206:54 | call to source | map.cpp:206:13:206:57 | call to pair | TAINT | @@ -1034,6 +1062,8 @@ | map.cpp:220:2:220:4 | ref arg m23 | map.cpp:225:2:225:4 | m23 | | | map.cpp:220:2:220:4 | ref arg m23 | map.cpp:226:7:226:9 | m23 | | | map.cpp:220:2:220:4 | ref arg m23 | map.cpp:249:1:249:1 | m23 | | +| map.cpp:220:13:220:57 | call to pair | map.cpp:220:2:220:4 | ref arg m23 | TAINT | +| map.cpp:220:13:220:57 | call to pair | map.cpp:220:6:220:11 | call to insert | TAINT | | map.cpp:220:13:220:57 | call to pair | map.cpp:220:13:220:57 | call to pair | TAINT | | map.cpp:220:39:220:44 | call to source | map.cpp:220:13:220:57 | call to pair | TAINT | | map.cpp:220:49:220:54 | call to source | map.cpp:220:13:220:57 | call to pair | TAINT | @@ -1044,6 +1074,8 @@ | map.cpp:221:2:221:4 | ref arg m23 | map.cpp:225:2:225:4 | m23 | | | map.cpp:221:2:221:4 | ref arg m23 | map.cpp:226:7:226:9 | m23 | | | map.cpp:221:2:221:4 | ref arg m23 | map.cpp:249:1:249:1 | m23 | | +| map.cpp:221:13:221:57 | call to pair | map.cpp:221:2:221:4 | ref arg m23 | TAINT | +| map.cpp:221:13:221:57 | call to pair | map.cpp:221:6:221:11 | call to insert | TAINT | | map.cpp:221:13:221:57 | call to pair | map.cpp:221:13:221:57 | call to pair | TAINT | | map.cpp:221:39:221:44 | call to source | map.cpp:221:13:221:57 | call to pair | TAINT | | map.cpp:221:49:221:54 | call to source | map.cpp:221:13:221:57 | call to pair | TAINT | @@ -1196,6 +1228,8 @@ | map.cpp:256:7:256:8 | ref arg m1 | map.cpp:295:30:295:31 | m1 | | | map.cpp:256:7:256:8 | ref arg m1 | map.cpp:398:1:398:1 | m1 | | | map.cpp:256:17:256:30 | call to make_pair | map.cpp:256:17:256:44 | call to pair | TAINT | +| map.cpp:256:17:256:44 | call to pair | map.cpp:256:7:256:8 | ref arg m1 | TAINT | +| map.cpp:256:17:256:44 | call to pair | map.cpp:256:10:256:15 | call to insert | TAINT | | map.cpp:256:32:256:36 | abc | map.cpp:256:17:256:30 | call to make_pair | TAINT | | map.cpp:256:39:256:43 | def | map.cpp:256:17:256:30 | call to make_pair | TAINT | | map.cpp:256:47:256:51 | first | map.cpp:256:7:256:51 | call to iterator | | @@ -1212,6 +1246,8 @@ | map.cpp:257:7:257:8 | ref arg m2 | map.cpp:333:7:333:8 | m2 | | | map.cpp:257:7:257:8 | ref arg m2 | map.cpp:398:1:398:1 | m2 | | | map.cpp:257:17:257:30 | call to make_pair | map.cpp:257:17:257:47 | call to pair | TAINT | +| map.cpp:257:17:257:47 | call to pair | map.cpp:257:7:257:8 | ref arg m2 | TAINT | +| map.cpp:257:17:257:47 | call to pair | map.cpp:257:10:257:15 | call to insert | TAINT | | map.cpp:257:32:257:36 | abc | map.cpp:257:17:257:30 | call to make_pair | TAINT | | map.cpp:257:39:257:44 | call to source | map.cpp:257:17:257:30 | call to make_pair | TAINT | | map.cpp:257:50:257:54 | first | map.cpp:257:7:257:54 | call to iterator | | @@ -1222,6 +1258,8 @@ | map.cpp:258:7:258:8 | ref arg m3 | map.cpp:307:30:307:31 | m3 | | | map.cpp:258:7:258:8 | ref arg m3 | map.cpp:398:1:398:1 | m3 | | | map.cpp:258:17:258:30 | call to make_pair | map.cpp:258:17:258:47 | call to pair | TAINT | +| map.cpp:258:17:258:47 | call to pair | map.cpp:258:7:258:8 | ref arg m3 | TAINT | +| map.cpp:258:17:258:47 | call to pair | map.cpp:258:10:258:15 | call to insert | TAINT | | map.cpp:258:32:258:37 | call to source | map.cpp:258:17:258:30 | call to make_pair | TAINT | | map.cpp:258:42:258:46 | def | map.cpp:258:17:258:30 | call to make_pair | TAINT | | map.cpp:258:50:258:54 | first | map.cpp:258:7:258:54 | call to iterator | | @@ -1235,6 +1273,8 @@ | map.cpp:259:17:259:18 | ref arg m4 | map.cpp:277:7:277:8 | m4 | | | map.cpp:259:17:259:18 | ref arg m4 | map.cpp:398:1:398:1 | m4 | | | map.cpp:259:20:259:24 | call to begin | map.cpp:259:17:259:26 | call to iterator | TAINT | +| map.cpp:259:29:259:70 | call to pair | map.cpp:259:7:259:8 | ref arg m4 | TAINT | +| map.cpp:259:29:259:70 | call to pair | map.cpp:259:10:259:15 | call to insert | TAINT | | map.cpp:259:29:259:70 | call to pair | map.cpp:259:29:259:70 | call to pair | TAINT | | map.cpp:259:55:259:59 | abc | map.cpp:259:29:259:70 | call to pair | TAINT | | map.cpp:259:62:259:67 | call to source | map.cpp:259:29:259:70 | call to pair | TAINT | @@ -1432,21 +1472,29 @@ | map.cpp:327:2:327:4 | ref arg m14 | map.cpp:330:2:330:4 | m14 | | | map.cpp:327:2:327:4 | ref arg m14 | map.cpp:398:1:398:1 | m14 | | | map.cpp:327:13:327:26 | call to make_pair | map.cpp:327:13:327:36 | call to pair | TAINT | +| map.cpp:327:13:327:36 | call to pair | map.cpp:327:2:327:4 | ref arg m14 | TAINT | +| map.cpp:327:13:327:36 | call to pair | map.cpp:327:6:327:11 | call to insert | TAINT | | map.cpp:327:28:327:30 | a | map.cpp:327:13:327:26 | call to make_pair | TAINT | | map.cpp:327:33:327:35 | a | map.cpp:327:13:327:26 | call to make_pair | TAINT | | map.cpp:328:2:328:4 | ref arg m14 | map.cpp:329:2:329:4 | m14 | | | map.cpp:328:2:328:4 | ref arg m14 | map.cpp:330:2:330:4 | m14 | | | map.cpp:328:2:328:4 | ref arg m14 | map.cpp:398:1:398:1 | m14 | | | map.cpp:328:13:328:26 | call to make_pair | map.cpp:328:13:328:41 | call to pair | TAINT | +| map.cpp:328:13:328:41 | call to pair | map.cpp:328:2:328:4 | ref arg m14 | TAINT | +| map.cpp:328:13:328:41 | call to pair | map.cpp:328:6:328:11 | call to insert | TAINT | | map.cpp:328:28:328:30 | b | map.cpp:328:13:328:26 | call to make_pair | TAINT | | map.cpp:328:33:328:38 | call to source | map.cpp:328:13:328:26 | call to make_pair | TAINT | | map.cpp:329:2:329:4 | ref arg m14 | map.cpp:330:2:330:4 | m14 | | | map.cpp:329:2:329:4 | ref arg m14 | map.cpp:398:1:398:1 | m14 | | | map.cpp:329:13:329:26 | call to make_pair | map.cpp:329:13:329:41 | call to pair | TAINT | +| map.cpp:329:13:329:41 | call to pair | map.cpp:329:2:329:4 | ref arg m14 | TAINT | +| map.cpp:329:13:329:41 | call to pair | map.cpp:329:6:329:11 | call to insert | TAINT | | map.cpp:329:28:329:30 | c | map.cpp:329:13:329:26 | call to make_pair | TAINT | | map.cpp:329:33:329:38 | call to source | map.cpp:329:13:329:26 | call to make_pair | TAINT | | map.cpp:330:2:330:4 | ref arg m14 | map.cpp:398:1:398:1 | m14 | | | map.cpp:330:13:330:26 | call to make_pair | map.cpp:330:13:330:36 | call to pair | TAINT | +| map.cpp:330:13:330:36 | call to pair | map.cpp:330:2:330:4 | ref arg m14 | TAINT | +| map.cpp:330:13:330:36 | call to pair | map.cpp:330:6:330:11 | call to insert | TAINT | | map.cpp:330:28:330:30 | d | map.cpp:330:13:330:26 | call to make_pair | TAINT | | map.cpp:330:33:330:35 | d | map.cpp:330:13:330:26 | call to make_pair | TAINT | | map.cpp:331:7:331:8 | ref arg m2 | map.cpp:332:7:332:8 | m2 | | @@ -1485,6 +1533,8 @@ | map.cpp:337:2:337:4 | ref arg m15 | map.cpp:345:7:345:9 | m15 | | | map.cpp:337:2:337:4 | ref arg m15 | map.cpp:360:2:360:4 | m15 | | | map.cpp:337:2:337:4 | ref arg m15 | map.cpp:398:1:398:1 | m15 | | +| map.cpp:337:13:337:57 | call to pair | map.cpp:337:2:337:4 | ref arg m15 | TAINT | +| map.cpp:337:13:337:57 | call to pair | map.cpp:337:6:337:11 | call to insert | TAINT | | map.cpp:337:13:337:57 | call to pair | map.cpp:337:13:337:57 | call to pair | TAINT | | map.cpp:337:39:337:44 | call to source | map.cpp:337:13:337:57 | call to pair | TAINT | | map.cpp:337:49:337:54 | call to source | map.cpp:337:13:337:57 | call to pair | TAINT | @@ -1493,6 +1543,8 @@ | map.cpp:338:2:338:4 | ref arg m18 | map.cpp:348:7:348:9 | m18 | | | map.cpp:338:2:338:4 | ref arg m18 | map.cpp:361:12:361:14 | m18 | | | map.cpp:338:2:338:4 | ref arg m18 | map.cpp:398:1:398:1 | m18 | | +| map.cpp:338:13:338:57 | call to pair | map.cpp:338:2:338:4 | ref arg m18 | TAINT | +| map.cpp:338:13:338:57 | call to pair | map.cpp:338:6:338:11 | call to insert | TAINT | | map.cpp:338:13:338:57 | call to pair | map.cpp:338:13:338:57 | call to pair | TAINT | | map.cpp:338:39:338:44 | call to source | map.cpp:338:13:338:57 | call to pair | TAINT | | map.cpp:338:49:338:54 | call to source | map.cpp:338:13:338:57 | call to pair | TAINT | @@ -1535,24 +1587,32 @@ | map.cpp:352:2:352:4 | ref arg m19 | map.cpp:356:7:356:9 | m19 | | | map.cpp:352:2:352:4 | ref arg m19 | map.cpp:362:7:362:9 | m19 | | | map.cpp:352:2:352:4 | ref arg m19 | map.cpp:398:1:398:1 | m19 | | +| map.cpp:352:13:352:57 | call to pair | map.cpp:352:2:352:4 | ref arg m19 | TAINT | +| map.cpp:352:13:352:57 | call to pair | map.cpp:352:6:352:11 | call to insert | TAINT | | map.cpp:352:13:352:57 | call to pair | map.cpp:352:13:352:57 | call to pair | TAINT | | map.cpp:352:39:352:44 | call to source | map.cpp:352:13:352:57 | call to pair | TAINT | | map.cpp:352:49:352:54 | call to source | map.cpp:352:13:352:57 | call to pair | TAINT | | map.cpp:353:2:353:4 | ref arg m20 | map.cpp:357:7:357:9 | m20 | | | map.cpp:353:2:353:4 | ref arg m20 | map.cpp:363:7:363:9 | m20 | | | map.cpp:353:2:353:4 | ref arg m20 | map.cpp:398:1:398:1 | m20 | | +| map.cpp:353:13:353:51 | call to pair | map.cpp:353:2:353:4 | ref arg m20 | TAINT | +| map.cpp:353:13:353:51 | call to pair | map.cpp:353:6:353:11 | call to insert | TAINT | | map.cpp:353:13:353:51 | call to pair | map.cpp:353:13:353:51 | call to pair | TAINT | | map.cpp:353:39:353:43 | abc | map.cpp:353:13:353:51 | call to pair | TAINT | | map.cpp:353:46:353:50 | def | map.cpp:353:13:353:51 | call to pair | TAINT | | map.cpp:354:2:354:4 | ref arg m21 | map.cpp:358:7:358:9 | m21 | | | map.cpp:354:2:354:4 | ref arg m21 | map.cpp:364:7:364:9 | m21 | | | map.cpp:354:2:354:4 | ref arg m21 | map.cpp:398:1:398:1 | m21 | | +| map.cpp:354:13:354:51 | call to pair | map.cpp:354:2:354:4 | ref arg m21 | TAINT | +| map.cpp:354:13:354:51 | call to pair | map.cpp:354:6:354:11 | call to insert | TAINT | | map.cpp:354:13:354:51 | call to pair | map.cpp:354:13:354:51 | call to pair | TAINT | | map.cpp:354:39:354:43 | abc | map.cpp:354:13:354:51 | call to pair | TAINT | | map.cpp:354:46:354:50 | def | map.cpp:354:13:354:51 | call to pair | TAINT | | map.cpp:355:2:355:4 | ref arg m22 | map.cpp:359:7:359:9 | m22 | | | map.cpp:355:2:355:4 | ref arg m22 | map.cpp:365:7:365:9 | m22 | | | map.cpp:355:2:355:4 | ref arg m22 | map.cpp:398:1:398:1 | m22 | | +| map.cpp:355:13:355:57 | call to pair | map.cpp:355:2:355:4 | ref arg m22 | TAINT | +| map.cpp:355:13:355:57 | call to pair | map.cpp:355:6:355:11 | call to insert | TAINT | | map.cpp:355:13:355:57 | call to pair | map.cpp:355:13:355:57 | call to pair | TAINT | | map.cpp:355:39:355:44 | call to source | map.cpp:355:13:355:57 | call to pair | TAINT | | map.cpp:355:49:355:54 | call to source | map.cpp:355:13:355:57 | call to pair | TAINT | @@ -1585,6 +1645,8 @@ | map.cpp:369:2:369:4 | ref arg m23 | map.cpp:374:2:374:4 | m23 | | | map.cpp:369:2:369:4 | ref arg m23 | map.cpp:375:7:375:9 | m23 | | | map.cpp:369:2:369:4 | ref arg m23 | map.cpp:398:1:398:1 | m23 | | +| map.cpp:369:13:369:57 | call to pair | map.cpp:369:2:369:4 | ref arg m23 | TAINT | +| map.cpp:369:13:369:57 | call to pair | map.cpp:369:6:369:11 | call to insert | TAINT | | map.cpp:369:13:369:57 | call to pair | map.cpp:369:13:369:57 | call to pair | TAINT | | map.cpp:369:39:369:44 | call to source | map.cpp:369:13:369:57 | call to pair | TAINT | | map.cpp:369:49:369:54 | call to source | map.cpp:369:13:369:57 | call to pair | TAINT | @@ -1595,6 +1657,8 @@ | map.cpp:370:2:370:4 | ref arg m23 | map.cpp:374:2:374:4 | m23 | | | map.cpp:370:2:370:4 | ref arg m23 | map.cpp:375:7:375:9 | m23 | | | map.cpp:370:2:370:4 | ref arg m23 | map.cpp:398:1:398:1 | m23 | | +| map.cpp:370:13:370:57 | call to pair | map.cpp:370:2:370:4 | ref arg m23 | TAINT | +| map.cpp:370:13:370:57 | call to pair | map.cpp:370:6:370:11 | call to insert | TAINT | | map.cpp:370:13:370:57 | call to pair | map.cpp:370:13:370:57 | call to pair | TAINT | | map.cpp:370:39:370:44 | call to source | map.cpp:370:13:370:57 | call to pair | TAINT | | map.cpp:370:49:370:54 | call to source | map.cpp:370:13:370:57 | call to pair | TAINT | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp index 03c5697c396..530e63b5770 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp @@ -104,13 +104,13 @@ void test_map() sink(m1.insert(std::make_pair("abc", "def")).first); sink(m2.insert(std::make_pair("abc", source())).first); // tainted [NOT DETECTED] sink(m3.insert(std::make_pair(source(), "def")).first); // tainted [NOT DETECTED] - sink(m4.insert(m4.begin(), std::pair("abc", source()))); // tainted [NOT DETECTED] + sink(m4.insert(m4.begin(), std::pair("abc", source()))); // tainted sink(m5.insert_or_assign("abc", source()).first); // tainted [NOT DETECTED] sink(m6.insert_or_assign(m6.begin(), "abc", source())); // tainted [NOT DETECTED] sink(m1); - sink(m2); // tainted [NOT DETECTED] - sink(m3); // tainted [NOT DETECTED] - sink(m4); // tainted [NOT DETECTED] + sink(m2); // tainted + sink(m3); // tainted + sink(m4); // tainted sink(m5); // tainted [NOT DETECTED] sink(m6); // tainted [NOT DETECTED] sink(m1.find("abc")); @@ -131,9 +131,9 @@ void test_map() std::map m8 = m2; std::map m9; m9 = m2; - sink(m7); // tainted [NOT DETECTED] - sink(m8); // tainted [NOT DETECTED] - sink(m9); // tainted [NOT DETECTED] + sink(m7); // tainted + sink(m8); // tainted + sink(m9); // tainted sink(m7.find("abc")); // tainted [NOT DETECTED] sink(m8.find("abc")); // tainted [NOT DETECTED] sink(m9.find("abc")); // tainted [NOT DETECTED] @@ -187,16 +187,16 @@ void test_map() std::map m15, m16, m17, m18; m15.insert(std::pair(source(), source())); m18.insert(std::pair(source(), source())); - sink(m15); // tainted [NOT DETECTED] + sink(m15); // tainted sink(m16); sink(m17); - sink(m18); // tainted [NOT DETECTED] + sink(m18); // tainted m15.swap(m16); m17.swap(m18); - sink(m15); + sink(m15); // [FALSE POSITIVE] sink(m16); // tainted [NOT DETECTED] sink(m17); // tainted [NOT DETECTED] - sink(m18); + sink(m18); // [FALSE POSITIVE] // merge std::map m19, m20, m21, m22; @@ -204,26 +204,26 @@ void test_map() m20.insert(std::pair("abc", "def")); m21.insert(std::pair("abc", "def")); m22.insert(std::pair(source(), source())); - sink(m19); // tainted [NOT DETECTED] + sink(m19); // tainted sink(m20); sink(m21); - sink(m22); // tainted [NOT DETECTED] + sink(m22); // tainted m15.merge(m16); m17.merge(m18); - sink(m19); // tainted [NOT DETECTED] + sink(m19); // tainted sink(m20); // tainted [NOT DETECTED] sink(m21); // tainted [NOT DETECTED] - sink(m22); // tainted [NOT DETECTED] + sink(m22); // tainted // erase, clear std::map m23; m23.insert(std::pair(source(), source())); m23.insert(std::pair(source(), source())); - sink(m23); // tainted [NOT DETECTED] + sink(m23); // tainted sink(m23.erase(m23.begin())); // tainted [NOT DETECTED] - sink(m23); // tainted [NOT DETECTED] + sink(m23); // tainted m23.clear(); - sink(m23); + sink(m23); // [FALSE POSITIVE] // emplace, emplace_hint std::map m24, m25; @@ -256,13 +256,13 @@ void test_unordered_map() sink(m1.insert(std::make_pair("abc", "def")).first); sink(m2.insert(std::make_pair("abc", source())).first); // tainted [NOT DETECTED] sink(m3.insert(std::make_pair(source(), "def")).first); // tainted [NOT DETECTED] - sink(m4.insert(m4.begin(), std::pair("abc", source()))); // tainted [NOT DETECTED] + sink(m4.insert(m4.begin(), std::pair("abc", source()))); // tainted sink(m5.insert_or_assign("abc", source()).first); // tainted [NOT DETECTED] sink(m6.insert_or_assign(m6.begin(), "abc", source())); // tainted [NOT DETECTED] sink(m1); - sink(m2); // tainted [NOT DETECTED] - sink(m3); // tainted [NOT DETECTED] - sink(m4); // tainted [NOT DETECTED] + sink(m2); // tainted + sink(m3); // tainted + sink(m4); // tainted sink(m5); // tainted [NOT DETECTED] sink(m6); // tainted [NOT DETECTED] sink(m1.find("abc")); @@ -283,9 +283,9 @@ void test_unordered_map() std::unordered_map m8 = m2; std::unordered_map m9; m9 = m2; - sink(m7); // tainted [NOT DETECTED] - sink(m8); // tainted [NOT DETECTED] - sink(m9); // tainted [NOT DETECTED] + sink(m7); // tainted + sink(m8); // tainted + sink(m9); // tainted sink(m7.find("abc")); // tainted [NOT DETECTED] sink(m8.find("abc")); // tainted [NOT DETECTED] sink(m9.find("abc")); // tainted [NOT DETECTED] @@ -336,16 +336,16 @@ void test_unordered_map() std::unordered_map m15, m16, m17, m18; m15.insert(std::pair(source(), source())); m18.insert(std::pair(source(), source())); - sink(m15); // tainted [NOT DETECTED] + sink(m15); // tainted sink(m16); sink(m17); - sink(m18); // tainted [NOT DETECTED] + sink(m18); // tainted m15.swap(m16); m17.swap(m18); - sink(m15); + sink(m15); // [FALSE POSITIVE] sink(m16); // tainted [NOT DETECTED] sink(m17); // tainted [NOT DETECTED] - sink(m18); + sink(m18); // [FALSE POSITIVE] // merge std::unordered_map m19, m20, m21, m22; @@ -353,26 +353,26 @@ void test_unordered_map() m20.insert(std::pair("abc", "def")); m21.insert(std::pair("abc", "def")); m22.insert(std::pair(source(), source())); - sink(m19); // tainted [NOT DETECTED] + sink(m19); // tainted sink(m20); sink(m21); - sink(m22); // tainted [NOT DETECTED] + sink(m22); // tainted m15.merge(m16); m17.merge(m18); - sink(m19); // tainted [NOT DETECTED] + sink(m19); // tainted sink(m20); // tainted [NOT DETECTED] sink(m21); // tainted [NOT DETECTED] - sink(m22); // tainted [NOT DETECTED] + sink(m22); // tainted // erase, clear std::unordered_map m23; m23.insert(std::pair(source(), source())); m23.insert(std::pair(source(), source())); - sink(m23); // tainted [NOT DETECTED] + sink(m23); // tainted sink(m23.erase(m23.begin())); // tainted [NOT DETECTED] - sink(m23); // tainted [NOT DETECTED] + sink(m23); // tainted m23.clear(); - sink(m23); + sink(m23); // [FALSE POSITIVE] // emplace, emplace_hint std::unordered_map m24, m25; 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 f046ca21988..9c849b429db 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -46,10 +46,80 @@ | map.cpp:83:7:83:32 | call to pair | map.cpp:83:17:83:22 | call to source | | map.cpp:86:7:86:32 | call to pair | map.cpp:86:24:86:29 | call to source | | map.cpp:92:7:92:7 | call to pair | map.cpp:91:33:91:38 | call to source | +| map.cpp:107:10:107:15 | call to insert | map.cpp:107:62:107:67 | call to source | +| map.cpp:111:7:111:8 | call to map | map.cpp:105:39:105:44 | call to source | +| map.cpp:112:7:112:8 | call to map | map.cpp:106:32:106:37 | call to source | +| map.cpp:113:7:113:8 | call to map | map.cpp:107:62:107:67 | call to source | +| map.cpp:134:7:134:8 | call to map | map.cpp:105:39:105:44 | call to source | +| map.cpp:135:7:135:8 | call to map | map.cpp:105:39:105:44 | call to source | +| map.cpp:136:7:136:8 | call to map | map.cpp:105:39:105:44 | call to source | | map.cpp:165:7:165:27 | ... = ... | map.cpp:165:20:165:25 | call to source | | map.cpp:167:7:167:30 | ... = ... | map.cpp:167:23:167:28 | call to source | +| map.cpp:190:7:190:9 | call to map | map.cpp:188:39:188:44 | call to source | +| map.cpp:190:7:190:9 | call to map | map.cpp:188:49:188:54 | call to source | +| map.cpp:193:7:193:9 | call to map | map.cpp:189:39:189:44 | call to source | +| map.cpp:193:7:193:9 | call to map | map.cpp:189:49:189:54 | call to source | +| map.cpp:196:7:196:9 | call to map | map.cpp:188:39:188:44 | call to source | +| map.cpp:196:7:196:9 | call to map | map.cpp:188:49:188:54 | call to source | +| map.cpp:199:7:199:9 | call to map | map.cpp:189:39:189:44 | call to source | +| map.cpp:199:7:199:9 | call to map | map.cpp:189:49:189:54 | call to source | +| map.cpp:207:7:207:9 | call to map | map.cpp:203:39:203:44 | call to source | +| map.cpp:207:7:207:9 | call to map | map.cpp:203:49:203:54 | call to source | +| map.cpp:210:7:210:9 | call to map | map.cpp:206:39:206:44 | call to source | +| map.cpp:210:7:210:9 | call to map | map.cpp:206:49:206:54 | call to source | +| map.cpp:213:7:213:9 | call to map | map.cpp:203:39:203:44 | call to source | +| map.cpp:213:7:213:9 | call to map | map.cpp:203:49:203:54 | call to source | +| map.cpp:216:7:216:9 | call to map | map.cpp:206:39:206:44 | call to source | +| map.cpp:216:7:216:9 | call to map | map.cpp:206:49:206:54 | call to source | +| map.cpp:222:7:222:9 | call to map | map.cpp:220:39:220:44 | call to source | +| map.cpp:222:7:222:9 | call to map | map.cpp:220:49:220:54 | call to source | +| map.cpp:222:7:222:9 | call to map | map.cpp:221:39:221:44 | call to source | +| map.cpp:222:7:222:9 | call to map | map.cpp:221:49:221:54 | call to source | +| map.cpp:224:7:224:9 | call to map | map.cpp:220:39:220:44 | call to source | +| map.cpp:224:7:224:9 | call to map | map.cpp:220:49:220:54 | call to source | +| map.cpp:224:7:224:9 | call to map | map.cpp:221:39:221:44 | call to source | +| map.cpp:224:7:224:9 | call to map | map.cpp:221:49:221:54 | call to source | +| map.cpp:226:7:226:9 | call to map | map.cpp:220:39:220:44 | call to source | +| map.cpp:226:7:226:9 | call to map | map.cpp:220:49:220:54 | call to source | +| map.cpp:226:7:226:9 | call to map | map.cpp:221:39:221:44 | call to source | +| map.cpp:226:7:226:9 | call to map | map.cpp:221:49:221:54 | call to source | +| map.cpp:259:10:259:15 | call to insert | map.cpp:259:62:259:67 | call to source | +| map.cpp:263:7:263:8 | call to unordered_map | map.cpp:257:39:257:44 | call to source | +| map.cpp:264:7:264:8 | call to unordered_map | map.cpp:258:32:258:37 | call to source | +| map.cpp:265:7:265:8 | call to unordered_map | map.cpp:259:62:259:67 | call to source | +| map.cpp:286:7:286:8 | call to unordered_map | map.cpp:257:39:257:44 | call to source | +| map.cpp:287:7:287:8 | call to unordered_map | map.cpp:257:39:257:44 | call to source | +| map.cpp:288:7:288:8 | call to unordered_map | map.cpp:257:39:257:44 | call to source | | map.cpp:317:7:317:27 | ... = ... | map.cpp:317:20:317:25 | call to source | | map.cpp:319:7:319:30 | ... = ... | map.cpp:319:23:319:28 | call to source | +| map.cpp:339:7:339:9 | call to unordered_map | map.cpp:337:39:337:44 | call to source | +| map.cpp:339:7:339:9 | call to unordered_map | map.cpp:337:49:337:54 | call to source | +| map.cpp:342:7:342:9 | call to unordered_map | map.cpp:338:39:338:44 | call to source | +| map.cpp:342:7:342:9 | call to unordered_map | map.cpp:338:49:338:54 | call to source | +| map.cpp:345:7:345:9 | call to unordered_map | map.cpp:337:39:337:44 | call to source | +| map.cpp:345:7:345:9 | call to unordered_map | map.cpp:337:49:337:54 | call to source | +| map.cpp:348:7:348:9 | call to unordered_map | map.cpp:338:39:338:44 | call to source | +| map.cpp:348:7:348:9 | call to unordered_map | map.cpp:338:49:338:54 | call to source | +| map.cpp:356:7:356:9 | call to unordered_map | map.cpp:352:39:352:44 | call to source | +| map.cpp:356:7:356:9 | call to unordered_map | map.cpp:352:49:352:54 | call to source | +| map.cpp:359:7:359:9 | call to unordered_map | map.cpp:355:39:355:44 | call to source | +| map.cpp:359:7:359:9 | call to unordered_map | map.cpp:355:49:355:54 | call to source | +| map.cpp:362:7:362:9 | call to unordered_map | map.cpp:352:39:352:44 | call to source | +| map.cpp:362:7:362:9 | call to unordered_map | map.cpp:352:49:352:54 | call to source | +| map.cpp:365:7:365:9 | call to unordered_map | map.cpp:355:39:355:44 | call to source | +| map.cpp:365:7:365:9 | call to unordered_map | map.cpp:355:49:355:54 | call to source | +| map.cpp:371:7:371:9 | call to unordered_map | map.cpp:369:39:369:44 | call to source | +| map.cpp:371:7:371:9 | call to unordered_map | map.cpp:369:49:369:54 | call to source | +| map.cpp:371:7:371:9 | call to unordered_map | map.cpp:370:39:370:44 | call to source | +| map.cpp:371:7:371:9 | call to unordered_map | map.cpp:370:49:370:54 | call to source | +| map.cpp:373:7:373:9 | call to unordered_map | map.cpp:369:39:369:44 | call to source | +| map.cpp:373:7:373:9 | call to unordered_map | map.cpp:369:49:369:54 | call to source | +| map.cpp:373:7:373:9 | call to unordered_map | map.cpp:370:39:370:44 | call to source | +| map.cpp:373:7:373:9 | call to unordered_map | map.cpp:370:49:370:54 | call to source | +| map.cpp:375:7:375:9 | call to unordered_map | map.cpp:369:39:369:44 | call to source | +| map.cpp:375:7:375:9 | call to unordered_map | map.cpp:369:49:369:54 | call to source | +| map.cpp:375:7:375:9 | call to unordered_map | map.cpp:370:39:370:44 | call to source | +| map.cpp:375:7:375:9 | call to unordered_map | map.cpp:370:49:370:54 | call to source | | movableclass.cpp:44:8:44:9 | s1 | movableclass.cpp:39:21:39:26 | call to source | | movableclass.cpp:45:8:45:9 | s2 | movableclass.cpp:40:23:40:28 | call to source | | movableclass.cpp:46:8:46:9 | s3 | movableclass.cpp:42:8:42:13 | 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 3722b7337ad..d122a09780e 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 @@ -42,6 +42,78 @@ | map.cpp:94:15:94:19 | map.cpp:91:33:91:38 | IR only | | map.cpp:95:15:95:20 | map.cpp:91:33:91:38 | IR only | | map.cpp:96:9:96:14 | map.cpp:91:33:91:38 | IR only | +| map.cpp:105:7:105:54 | map.cpp:105:39:105:44 | IR only | +| map.cpp:106:7:106:54 | map.cpp:106:32:106:37 | IR only | +| map.cpp:111:7:111:8 | map.cpp:105:39:105:44 | AST only | +| map.cpp:112:7:112:8 | map.cpp:106:32:106:37 | AST only | +| map.cpp:113:7:113:8 | map.cpp:107:62:107:67 | AST only | +| map.cpp:134:7:134:8 | map.cpp:105:39:105:44 | AST only | +| map.cpp:135:7:135:8 | map.cpp:105:39:105:44 | AST only | +| map.cpp:136:7:136:8 | map.cpp:105:39:105:44 | AST only | +| map.cpp:190:7:190:9 | map.cpp:188:39:188:44 | AST only | +| map.cpp:190:7:190:9 | map.cpp:188:49:188:54 | AST only | +| map.cpp:193:7:193:9 | map.cpp:189:39:189:44 | AST only | +| map.cpp:193:7:193:9 | map.cpp:189:49:189:54 | AST only | +| map.cpp:196:7:196:9 | map.cpp:188:39:188:44 | AST only | +| map.cpp:196:7:196:9 | map.cpp:188:49:188:54 | AST only | +| map.cpp:199:7:199:9 | map.cpp:189:39:189:44 | AST only | +| map.cpp:199:7:199:9 | map.cpp:189:49:189:54 | AST only | +| map.cpp:207:7:207:9 | map.cpp:203:39:203:44 | AST only | +| map.cpp:207:7:207:9 | map.cpp:203:49:203:54 | AST only | +| map.cpp:210:7:210:9 | map.cpp:206:39:206:44 | AST only | +| map.cpp:210:7:210:9 | map.cpp:206:49:206:54 | AST only | +| map.cpp:213:7:213:9 | map.cpp:203:39:203:44 | AST only | +| map.cpp:213:7:213:9 | map.cpp:203:49:203:54 | AST only | +| map.cpp:216:7:216:9 | map.cpp:206:39:206:44 | AST only | +| map.cpp:216:7:216:9 | map.cpp:206:49:206:54 | AST only | +| map.cpp:222:7:222:9 | map.cpp:220:39:220:44 | AST only | +| map.cpp:222:7:222:9 | map.cpp:220:49:220:54 | AST only | +| map.cpp:222:7:222:9 | map.cpp:221:39:221:44 | AST only | +| map.cpp:222:7:222:9 | map.cpp:221:49:221:54 | AST only | +| map.cpp:224:7:224:9 | map.cpp:220:39:220:44 | AST only | +| map.cpp:224:7:224:9 | map.cpp:220:49:220:54 | AST only | +| map.cpp:224:7:224:9 | map.cpp:221:39:221:44 | AST only | +| map.cpp:224:7:224:9 | map.cpp:221:49:221:54 | AST only | +| map.cpp:226:7:226:9 | map.cpp:220:39:220:44 | AST only | +| map.cpp:226:7:226:9 | map.cpp:220:49:220:54 | AST only | +| map.cpp:226:7:226:9 | map.cpp:221:39:221:44 | AST only | +| map.cpp:226:7:226:9 | map.cpp:221:49:221:54 | AST only | +| map.cpp:257:7:257:54 | map.cpp:257:39:257:44 | IR only | +| map.cpp:258:7:258:54 | map.cpp:258:32:258:37 | IR only | +| map.cpp:263:7:263:8 | map.cpp:257:39:257:44 | AST only | +| map.cpp:264:7:264:8 | map.cpp:258:32:258:37 | AST only | +| map.cpp:265:7:265:8 | map.cpp:259:62:259:67 | AST only | +| map.cpp:286:7:286:8 | map.cpp:257:39:257:44 | AST only | +| map.cpp:287:7:287:8 | map.cpp:257:39:257:44 | AST only | +| map.cpp:288:7:288:8 | map.cpp:257:39:257:44 | AST only | +| map.cpp:339:7:339:9 | map.cpp:337:39:337:44 | AST only | +| map.cpp:339:7:339:9 | map.cpp:337:49:337:54 | AST only | +| map.cpp:342:7:342:9 | map.cpp:338:39:338:44 | AST only | +| map.cpp:342:7:342:9 | map.cpp:338:49:338:54 | AST only | +| map.cpp:345:7:345:9 | map.cpp:337:39:337:44 | AST only | +| map.cpp:345:7:345:9 | map.cpp:337:49:337:54 | AST only | +| map.cpp:348:7:348:9 | map.cpp:338:39:338:44 | AST only | +| map.cpp:348:7:348:9 | map.cpp:338:49:338:54 | AST only | +| map.cpp:356:7:356:9 | map.cpp:352:39:352:44 | AST only | +| map.cpp:356:7:356:9 | map.cpp:352:49:352:54 | AST only | +| map.cpp:359:7:359:9 | map.cpp:355:39:355:44 | AST only | +| map.cpp:359:7:359:9 | map.cpp:355:49:355:54 | AST only | +| map.cpp:362:7:362:9 | map.cpp:352:39:352:44 | AST only | +| map.cpp:362:7:362:9 | map.cpp:352:49:352:54 | AST only | +| map.cpp:365:7:365:9 | map.cpp:355:39:355:44 | AST only | +| map.cpp:365:7:365:9 | map.cpp:355:49:355:54 | AST only | +| map.cpp:371:7:371:9 | map.cpp:369:39:369:44 | AST only | +| map.cpp:371:7:371:9 | map.cpp:369:49:369:54 | AST only | +| map.cpp:371:7:371:9 | map.cpp:370:39:370:44 | AST only | +| map.cpp:371:7:371:9 | map.cpp:370:49:370:54 | AST only | +| map.cpp:373:7:373:9 | map.cpp:369:39:369:44 | AST only | +| map.cpp:373:7:373:9 | map.cpp:369:49:369:54 | AST only | +| map.cpp:373:7:373:9 | map.cpp:370:39:370:44 | AST only | +| map.cpp:373:7:373:9 | map.cpp:370:49:370:54 | AST only | +| map.cpp:375:7:375:9 | map.cpp:369:39:369:44 | AST only | +| map.cpp:375:7:375:9 | map.cpp:369:49:369:54 | AST only | +| map.cpp:375:7:375:9 | map.cpp:370:39:370:44 | AST only | +| map.cpp:375:7:375:9 | map.cpp:370:49:370:54 | AST only | | movableclass.cpp:65:11:65:11 | movableclass.cpp:65:13:65:18 | AST only | | movableclass.cpp:65:11:65:21 | movableclass.cpp:65:13:65:18 | IR only | | smart_pointer.cpp:12:10:12:10 | smart_pointer.cpp:11:52:11:57 | 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 ccdc330c7e2..b8398be1b45 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 @@ -78,8 +78,14 @@ | map.cpp:94:15:94:19 | first | map.cpp:91:33:91:38 | call to source | | map.cpp:95:15:95:20 | second | map.cpp:91:33:91:38 | call to source | | map.cpp:96:9:96:14 | second | map.cpp:91:33:91:38 | call to source | +| map.cpp:105:7:105:54 | call to iterator | map.cpp:105:39:105:44 | call to source | +| map.cpp:106:7:106:54 | call to iterator | map.cpp:106:32:106:37 | call to source | +| map.cpp:107:10:107:15 | call to insert | map.cpp:107:62:107:67 | call to source | | map.cpp:165:7:165:27 | ... = ... | map.cpp:165:20:165:25 | call to source | | map.cpp:167:7:167:30 | ... = ... | map.cpp:167:23:167:28 | call to source | +| map.cpp:257:7:257:54 | call to iterator | map.cpp:257:39:257:44 | call to source | +| map.cpp:258:7:258:54 | call to iterator | map.cpp:258:32:258:37 | call to source | +| map.cpp:259:10:259:15 | call to insert | map.cpp:259:62:259:67 | call to source | | map.cpp:317:7:317:27 | ... = ... | map.cpp:317:20:317:25 | call to source | | map.cpp:319:7:319:30 | ... = ... | map.cpp:319:23:319:28 | call to source | | movableclass.cpp:44:8:44:9 | s1 | movableclass.cpp:39:21:39:26 | call to source | From 6119bf3430a1fd0f57a562b3be693a37ec0e1898 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Sep 2020 17:10:41 +0100 Subject: [PATCH 049/411] C++: Model begin and end. --- .../cpp/models/implementations/StdMap.qll | 17 ++++++++++++ .../dataflow/taint-tests/localTaint.expected | 26 +++++++++++++++++++ .../dataflow/taint-tests/map.cpp | 24 ++++++++--------- .../dataflow/taint-tests/taint.expected | 4 +++ .../dataflow/taint-tests/test_diff.expected | 8 ++++++ .../dataflow/taint-tests/test_ir.expected | 12 +++++++++ 6 files changed, 79 insertions(+), 12 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll index f6ac66091f5..151c8e31841 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll @@ -23,3 +23,20 @@ class StdMapInsert extends TaintFunction { ) } } + +/** + * The standard map `begin` and `end` functions and their + * variants. + */ +class StdMapBeginEnd extends TaintFunction { + StdMapBeginEnd() { + this.hasQualifiedName("std", ["map", "unordered_map"], ["begin", "end", "cbegin", "cend"]) + or + this.hasQualifiedName("std", "map", ["rbegin", "crbegin", "rend", "crend"]) + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + input.isQualifierObject() and + output.isReturnValue() + } +} 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 52944e7cdbe..c1acd2c59c8 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -657,6 +657,7 @@ | map.cpp:107:7:107:8 | ref arg m4 | map.cpp:119:7:119:8 | m4 | | | map.cpp:107:7:107:8 | ref arg m4 | map.cpp:125:7:125:8 | m4 | | | map.cpp:107:7:107:8 | ref arg m4 | map.cpp:249:1:249:1 | m4 | | +| map.cpp:107:17:107:18 | m4 | map.cpp:107:20:107:24 | call to begin | TAINT | | map.cpp:107:17:107:18 | ref arg m4 | map.cpp:107:7:107:8 | m4 | | | map.cpp:107:17:107:18 | ref arg m4 | map.cpp:113:7:113:8 | m4 | | | map.cpp:107:17:107:18 | ref arg m4 | map.cpp:119:7:119:8 | m4 | | @@ -677,6 +678,7 @@ | map.cpp:109:7:109:8 | ref arg m6 | map.cpp:121:7:121:8 | m6 | | | map.cpp:109:7:109:8 | ref arg m6 | map.cpp:127:7:127:8 | m6 | | | map.cpp:109:7:109:8 | ref arg m6 | map.cpp:249:1:249:1 | m6 | | +| map.cpp:109:27:109:28 | m6 | map.cpp:109:30:109:34 | call to begin | TAINT | | map.cpp:109:27:109:28 | ref arg m6 | map.cpp:109:7:109:8 | m6 | | | map.cpp:109:27:109:28 | ref arg m6 | map.cpp:115:7:115:8 | m6 | | | map.cpp:109:27:109:28 | ref arg m6 | map.cpp:121:7:121:8 | m6 | | @@ -760,6 +762,7 @@ | map.cpp:137:7:137:8 | ref arg m7 | map.cpp:249:1:249:1 | m7 | | | map.cpp:138:7:138:8 | ref arg m8 | map.cpp:249:1:249:1 | m8 | | | map.cpp:139:7:139:8 | ref arg m9 | map.cpp:249:1:249:1 | m9 | | +| map.cpp:143:12:143:13 | m1 | map.cpp:143:15:143:19 | call to begin | TAINT | | map.cpp:143:12:143:13 | ref arg m1 | map.cpp:143:30:143:31 | m1 | | | map.cpp:143:12:143:13 | ref arg m1 | map.cpp:249:1:249:1 | m1 | | | map.cpp:143:15:143:19 | call to begin | map.cpp:143:7:143:21 | ... = ... | | @@ -768,6 +771,7 @@ | map.cpp:143:15:143:19 | call to begin | map.cpp:145:9:145:10 | i1 | | | map.cpp:143:15:143:19 | call to begin | map.cpp:146:8:146:9 | i1 | | | map.cpp:143:15:143:19 | call to begin | map.cpp:147:8:147:9 | i1 | | +| map.cpp:143:30:143:31 | m1 | map.cpp:143:33:143:35 | call to end | TAINT | | map.cpp:143:30:143:31 | ref arg m1 | map.cpp:143:30:143:31 | m1 | | | map.cpp:143:30:143:31 | ref arg m1 | map.cpp:249:1:249:1 | m1 | | | map.cpp:143:40:143:41 | i1 | map.cpp:143:42:143:42 | call to operator++ | | @@ -780,6 +784,7 @@ | map.cpp:145:9:145:10 | i1 | map.cpp:145:8:145:8 | call to operator* | TAINT | | map.cpp:146:8:146:9 | i1 | map.cpp:146:10:146:10 | call to operator-> | TAINT | | map.cpp:147:8:147:9 | i1 | map.cpp:147:10:147:10 | call to operator-> | TAINT | +| map.cpp:149:12:149:13 | m2 | map.cpp:149:15:149:19 | call to begin | TAINT | | map.cpp:149:12:149:13 | ref arg m2 | map.cpp:149:30:149:31 | m2 | | | map.cpp:149:12:149:13 | ref arg m2 | map.cpp:179:7:179:8 | m2 | | | map.cpp:149:12:149:13 | ref arg m2 | map.cpp:180:7:180:8 | m2 | | @@ -796,6 +801,7 @@ | map.cpp:149:15:149:19 | call to begin | map.cpp:153:8:153:9 | i2 | | | map.cpp:149:15:149:19 | call to begin | map.cpp:158:8:158:9 | i2 | | | map.cpp:149:15:149:19 | call to begin | map.cpp:159:8:159:9 | i2 | | +| map.cpp:149:30:149:31 | m2 | map.cpp:149:33:149:35 | call to end | TAINT | | map.cpp:149:30:149:31 | ref arg m2 | map.cpp:149:30:149:31 | m2 | | | map.cpp:149:30:149:31 | ref arg m2 | map.cpp:179:7:179:8 | m2 | | | map.cpp:149:30:149:31 | ref arg m2 | map.cpp:180:7:180:8 | m2 | | @@ -816,12 +822,14 @@ | map.cpp:151:9:151:10 | i2 | map.cpp:151:8:151:8 | call to operator* | TAINT | | map.cpp:152:8:152:9 | i2 | map.cpp:152:10:152:10 | call to operator-> | TAINT | | map.cpp:153:8:153:9 | i2 | map.cpp:153:10:153:10 | call to operator-> | TAINT | +| map.cpp:155:12:155:13 | m3 | map.cpp:155:15:155:19 | call to begin | TAINT | | map.cpp:155:12:155:13 | ref arg m3 | map.cpp:155:30:155:31 | m3 | | | map.cpp:155:12:155:13 | ref arg m3 | map.cpp:249:1:249:1 | m3 | | | map.cpp:155:15:155:19 | call to begin | map.cpp:155:7:155:21 | ... = ... | | | map.cpp:155:15:155:19 | call to begin | map.cpp:155:24:155:25 | i3 | | | map.cpp:155:15:155:19 | call to begin | map.cpp:155:40:155:41 | i3 | | | map.cpp:155:15:155:19 | call to begin | map.cpp:157:9:157:10 | i3 | | +| map.cpp:155:30:155:31 | m3 | map.cpp:155:33:155:35 | call to end | TAINT | | map.cpp:155:30:155:31 | ref arg m3 | map.cpp:155:30:155:31 | m3 | | | map.cpp:155:30:155:31 | ref arg m3 | map.cpp:249:1:249:1 | m3 | | | map.cpp:155:40:155:41 | i3 | map.cpp:155:42:155:42 | call to operator++ | | @@ -1084,6 +1092,7 @@ | map.cpp:223:7:223:9 | ref arg m23 | map.cpp:225:2:225:4 | m23 | | | map.cpp:223:7:223:9 | ref arg m23 | map.cpp:226:7:226:9 | m23 | | | map.cpp:223:7:223:9 | ref arg m23 | map.cpp:249:1:249:1 | m23 | | +| map.cpp:223:17:223:19 | m23 | map.cpp:223:21:223:25 | call to begin | TAINT | | map.cpp:223:17:223:19 | ref arg m23 | map.cpp:223:7:223:9 | m23 | | | map.cpp:223:17:223:19 | ref arg m23 | map.cpp:224:7:224:9 | m23 | | | map.cpp:223:17:223:19 | ref arg m23 | map.cpp:225:2:225:4 | m23 | | @@ -1120,6 +1129,7 @@ | map.cpp:234:7:234:9 | ref arg m25 | map.cpp:236:24:236:26 | m25 | | | map.cpp:234:7:234:9 | ref arg m25 | map.cpp:237:7:237:9 | m25 | | | map.cpp:234:7:234:9 | ref arg m25 | map.cpp:249:1:249:1 | m25 | | +| map.cpp:234:24:234:26 | m25 | map.cpp:234:28:234:32 | call to begin | TAINT | | map.cpp:234:24:234:26 | ref arg m25 | map.cpp:234:7:234:9 | m25 | | | map.cpp:234:24:234:26 | ref arg m25 | map.cpp:235:7:235:9 | m25 | | | map.cpp:234:24:234:26 | ref arg m25 | map.cpp:236:7:236:9 | m25 | | @@ -1130,6 +1140,7 @@ | map.cpp:235:7:235:9 | m25 | map.cpp:235:7:235:9 | call to map | | | map.cpp:236:7:236:9 | ref arg m25 | map.cpp:237:7:237:9 | m25 | | | map.cpp:236:7:236:9 | ref arg m25 | map.cpp:249:1:249:1 | m25 | | +| map.cpp:236:24:236:26 | m25 | map.cpp:236:28:236:32 | call to begin | TAINT | | map.cpp:236:24:236:26 | ref arg m25 | map.cpp:236:7:236:9 | m25 | | | map.cpp:236:24:236:26 | ref arg m25 | map.cpp:237:7:237:9 | m25 | | | map.cpp:236:24:236:26 | ref arg m25 | map.cpp:249:1:249:1 | m25 | | @@ -1162,6 +1173,7 @@ | map.cpp:245:7:245:9 | ref arg m27 | map.cpp:247:23:247:25 | m27 | | | map.cpp:245:7:245:9 | ref arg m27 | map.cpp:248:7:248:9 | m27 | | | map.cpp:245:7:245:9 | ref arg m27 | map.cpp:249:1:249:1 | m27 | | +| map.cpp:245:23:245:25 | m27 | map.cpp:245:27:245:31 | call to begin | TAINT | | map.cpp:245:23:245:25 | ref arg m27 | map.cpp:245:7:245:9 | m27 | | | map.cpp:245:23:245:25 | ref arg m27 | map.cpp:246:7:246:9 | m27 | | | map.cpp:245:23:245:25 | ref arg m27 | map.cpp:247:7:247:9 | m27 | | @@ -1172,6 +1184,7 @@ | map.cpp:246:7:246:9 | m27 | map.cpp:246:7:246:9 | call to map | | | map.cpp:247:7:247:9 | ref arg m27 | map.cpp:248:7:248:9 | m27 | | | map.cpp:247:7:247:9 | ref arg m27 | map.cpp:249:1:249:1 | m27 | | +| map.cpp:247:23:247:25 | m27 | map.cpp:247:27:247:31 | call to begin | TAINT | | map.cpp:247:23:247:25 | ref arg m27 | map.cpp:247:7:247:9 | m27 | | | map.cpp:247:23:247:25 | ref arg m27 | map.cpp:248:7:248:9 | m27 | | | map.cpp:247:23:247:25 | ref arg m27 | map.cpp:249:1:249:1 | m27 | | @@ -1267,6 +1280,7 @@ | map.cpp:259:7:259:8 | ref arg m4 | map.cpp:271:7:271:8 | m4 | | | map.cpp:259:7:259:8 | ref arg m4 | map.cpp:277:7:277:8 | m4 | | | map.cpp:259:7:259:8 | ref arg m4 | map.cpp:398:1:398:1 | m4 | | +| map.cpp:259:17:259:18 | m4 | map.cpp:259:20:259:24 | call to begin | TAINT | | map.cpp:259:17:259:18 | ref arg m4 | map.cpp:259:7:259:8 | m4 | | | map.cpp:259:17:259:18 | ref arg m4 | map.cpp:265:7:265:8 | m4 | | | map.cpp:259:17:259:18 | ref arg m4 | map.cpp:271:7:271:8 | m4 | | @@ -1287,6 +1301,7 @@ | map.cpp:261:7:261:8 | ref arg m6 | map.cpp:273:7:273:8 | m6 | | | map.cpp:261:7:261:8 | ref arg m6 | map.cpp:279:7:279:8 | m6 | | | map.cpp:261:7:261:8 | ref arg m6 | map.cpp:398:1:398:1 | m6 | | +| map.cpp:261:27:261:28 | m6 | map.cpp:261:30:261:34 | call to begin | TAINT | | map.cpp:261:27:261:28 | ref arg m6 | map.cpp:261:7:261:8 | m6 | | | map.cpp:261:27:261:28 | ref arg m6 | map.cpp:267:7:267:8 | m6 | | | map.cpp:261:27:261:28 | ref arg m6 | map.cpp:273:7:273:8 | m6 | | @@ -1364,6 +1379,7 @@ | map.cpp:289:7:289:8 | ref arg m7 | map.cpp:398:1:398:1 | m7 | | | map.cpp:290:7:290:8 | ref arg m8 | map.cpp:398:1:398:1 | m8 | | | map.cpp:291:7:291:8 | ref arg m9 | map.cpp:398:1:398:1 | m9 | | +| map.cpp:295:12:295:13 | m1 | map.cpp:295:15:295:19 | call to begin | TAINT | | map.cpp:295:12:295:13 | ref arg m1 | map.cpp:295:30:295:31 | m1 | | | map.cpp:295:12:295:13 | ref arg m1 | map.cpp:398:1:398:1 | m1 | | | map.cpp:295:15:295:19 | call to begin | map.cpp:295:7:295:21 | ... = ... | | @@ -1372,6 +1388,7 @@ | map.cpp:295:15:295:19 | call to begin | map.cpp:297:9:297:10 | i1 | | | map.cpp:295:15:295:19 | call to begin | map.cpp:298:8:298:9 | i1 | | | map.cpp:295:15:295:19 | call to begin | map.cpp:299:8:299:9 | i1 | | +| map.cpp:295:30:295:31 | m1 | map.cpp:295:33:295:35 | call to end | TAINT | | map.cpp:295:30:295:31 | ref arg m1 | map.cpp:295:30:295:31 | m1 | | | map.cpp:295:30:295:31 | ref arg m1 | map.cpp:398:1:398:1 | m1 | | | map.cpp:295:40:295:41 | i1 | map.cpp:295:42:295:42 | call to operator++ | | @@ -1384,6 +1401,7 @@ | map.cpp:297:9:297:10 | i1 | map.cpp:297:8:297:8 | call to operator* | TAINT | | map.cpp:298:8:298:9 | i1 | map.cpp:298:10:298:10 | call to operator-> | TAINT | | map.cpp:299:8:299:9 | i1 | map.cpp:299:10:299:10 | call to operator-> | TAINT | +| map.cpp:301:12:301:13 | m2 | map.cpp:301:15:301:19 | call to begin | TAINT | | map.cpp:301:12:301:13 | ref arg m2 | map.cpp:301:30:301:31 | m2 | | | map.cpp:301:12:301:13 | ref arg m2 | map.cpp:331:7:331:8 | m2 | | | map.cpp:301:12:301:13 | ref arg m2 | map.cpp:332:7:332:8 | m2 | | @@ -1397,6 +1415,7 @@ | map.cpp:301:15:301:19 | call to begin | map.cpp:305:8:305:9 | i2 | | | map.cpp:301:15:301:19 | call to begin | map.cpp:310:8:310:9 | i2 | | | map.cpp:301:15:301:19 | call to begin | map.cpp:311:8:311:9 | i2 | | +| map.cpp:301:30:301:31 | m2 | map.cpp:301:33:301:35 | call to end | TAINT | | map.cpp:301:30:301:31 | ref arg m2 | map.cpp:301:30:301:31 | m2 | | | map.cpp:301:30:301:31 | ref arg m2 | map.cpp:331:7:331:8 | m2 | | | map.cpp:301:30:301:31 | ref arg m2 | map.cpp:332:7:332:8 | m2 | | @@ -1414,12 +1433,14 @@ | map.cpp:303:9:303:10 | i2 | map.cpp:303:8:303:8 | call to operator* | TAINT | | map.cpp:304:8:304:9 | i2 | map.cpp:304:10:304:10 | call to operator-> | TAINT | | map.cpp:305:8:305:9 | i2 | map.cpp:305:10:305:10 | call to operator-> | TAINT | +| map.cpp:307:12:307:13 | m3 | map.cpp:307:15:307:19 | call to begin | TAINT | | map.cpp:307:12:307:13 | ref arg m3 | map.cpp:307:30:307:31 | m3 | | | map.cpp:307:12:307:13 | ref arg m3 | map.cpp:398:1:398:1 | m3 | | | map.cpp:307:15:307:19 | call to begin | map.cpp:307:7:307:21 | ... = ... | | | map.cpp:307:15:307:19 | call to begin | map.cpp:307:24:307:25 | i3 | | | map.cpp:307:15:307:19 | call to begin | map.cpp:307:40:307:41 | i3 | | | map.cpp:307:15:307:19 | call to begin | map.cpp:309:9:309:10 | i3 | | +| map.cpp:307:30:307:31 | m3 | map.cpp:307:33:307:35 | call to end | TAINT | | map.cpp:307:30:307:31 | ref arg m3 | map.cpp:307:30:307:31 | m3 | | | map.cpp:307:30:307:31 | ref arg m3 | map.cpp:398:1:398:1 | m3 | | | map.cpp:307:40:307:41 | i3 | map.cpp:307:42:307:42 | call to operator++ | | @@ -1667,6 +1688,7 @@ | map.cpp:372:7:372:9 | ref arg m23 | map.cpp:374:2:374:4 | m23 | | | map.cpp:372:7:372:9 | ref arg m23 | map.cpp:375:7:375:9 | m23 | | | map.cpp:372:7:372:9 | ref arg m23 | map.cpp:398:1:398:1 | m23 | | +| map.cpp:372:17:372:19 | m23 | map.cpp:372:21:372:25 | call to begin | TAINT | | map.cpp:372:17:372:19 | ref arg m23 | map.cpp:372:7:372:9 | m23 | | | map.cpp:372:17:372:19 | ref arg m23 | map.cpp:373:7:373:9 | m23 | | | map.cpp:372:17:372:19 | ref arg m23 | map.cpp:374:2:374:4 | m23 | | @@ -1703,6 +1725,7 @@ | map.cpp:383:7:383:9 | ref arg m25 | map.cpp:385:24:385:26 | m25 | | | map.cpp:383:7:383:9 | ref arg m25 | map.cpp:386:7:386:9 | m25 | | | map.cpp:383:7:383:9 | ref arg m25 | map.cpp:398:1:398:1 | m25 | | +| map.cpp:383:24:383:26 | m25 | map.cpp:383:28:383:32 | call to begin | TAINT | | map.cpp:383:24:383:26 | ref arg m25 | map.cpp:383:7:383:9 | m25 | | | map.cpp:383:24:383:26 | ref arg m25 | map.cpp:384:7:384:9 | m25 | | | map.cpp:383:24:383:26 | ref arg m25 | map.cpp:385:7:385:9 | m25 | | @@ -1713,6 +1736,7 @@ | map.cpp:384:7:384:9 | m25 | map.cpp:384:7:384:9 | call to unordered_map | | | map.cpp:385:7:385:9 | ref arg m25 | map.cpp:386:7:386:9 | m25 | | | map.cpp:385:7:385:9 | ref arg m25 | map.cpp:398:1:398:1 | m25 | | +| map.cpp:385:24:385:26 | m25 | map.cpp:385:28:385:32 | call to begin | TAINT | | map.cpp:385:24:385:26 | ref arg m25 | map.cpp:385:7:385:9 | m25 | | | map.cpp:385:24:385:26 | ref arg m25 | map.cpp:386:7:386:9 | m25 | | | map.cpp:385:24:385:26 | ref arg m25 | map.cpp:398:1:398:1 | m25 | | @@ -1745,6 +1769,7 @@ | map.cpp:394:7:394:9 | ref arg m27 | map.cpp:396:23:396:25 | m27 | | | map.cpp:394:7:394:9 | ref arg m27 | map.cpp:397:7:397:9 | m27 | | | map.cpp:394:7:394:9 | ref arg m27 | map.cpp:398:1:398:1 | m27 | | +| map.cpp:394:23:394:25 | m27 | map.cpp:394:27:394:31 | call to begin | TAINT | | map.cpp:394:23:394:25 | ref arg m27 | map.cpp:394:7:394:9 | m27 | | | map.cpp:394:23:394:25 | ref arg m27 | map.cpp:395:7:395:9 | m27 | | | map.cpp:394:23:394:25 | ref arg m27 | map.cpp:396:7:396:9 | m27 | | @@ -1755,6 +1780,7 @@ | map.cpp:395:7:395:9 | m27 | map.cpp:395:7:395:9 | call to unordered_map | | | map.cpp:396:7:396:9 | ref arg m27 | map.cpp:397:7:397:9 | m27 | | | map.cpp:396:7:396:9 | ref arg m27 | map.cpp:398:1:398:1 | m27 | | +| map.cpp:396:23:396:25 | m27 | map.cpp:396:27:396:31 | call to begin | TAINT | | map.cpp:396:23:396:25 | ref arg m27 | map.cpp:396:7:396:9 | m27 | | | map.cpp:396:23:396:25 | ref arg m27 | map.cpp:397:7:397:9 | m27 | | | map.cpp:396:23:396:25 | ref arg m27 | map.cpp:398:1:398:1 | m27 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp index 530e63b5770..519ce65fba6 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp @@ -148,15 +148,15 @@ void test_map() } for (i2 = m2.begin(); i2 != m2.end(); i2++) { - sink(*i2); // tainted [NOT DETECTED] - sink(i2->first); - sink(i2->second); // tainted [NOT DETECTED] + sink(*i2); // tainted + sink(i2->first); // [FALSE POSITIVE] + sink(i2->second); // tainted } for (i3 = m3.begin(); i3 != m3.end(); i3++) { - sink(*i3); // tainted [NOT DETECTED] - sink(i2->first); // tainted [NOT DETECTED] - sink(i2->second); + sink(*i3); // tainted + sink(i2->first); // tainted + sink(i2->second); // [FALSE POSITIVE] } // array-like access @@ -300,15 +300,15 @@ void test_unordered_map() } for (i2 = m2.begin(); i2 != m2.end(); i2++) { - sink(*i2); // tainted [NOT DETECTED] - sink(i2->first); - sink(i2->second); // tainted [NOT DETECTED] + sink(*i2); // tainted + sink(i2->first); // [FALSE POSITIVE] + sink(i2->second); // tainted } for (i3 = m3.begin(); i3 != m3.end(); i3++) { - sink(*i3); // tainted [NOT DETECTED] - sink(i2->first); // tainted [NOT DETECTED] - sink(i2->second); + sink(*i3); // tainted + sink(i2->first); // tainted + sink(i2->second); // [FALSE POSITIVE] } // array-like access 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 9c849b429db..cce0e24c789 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -53,6 +53,8 @@ | map.cpp:134:7:134:8 | call to map | map.cpp:105:39:105:44 | call to source | | map.cpp:135:7:135:8 | call to map | map.cpp:105:39:105:44 | call to source | | map.cpp:136:7:136:8 | call to map | map.cpp:105:39:105:44 | call to source | +| map.cpp:151:8:151:10 | call to pair | map.cpp:105:39:105:44 | call to source | +| map.cpp:157:8:157:10 | call to pair | map.cpp:106:32:106:37 | call to source | | map.cpp:165:7:165:27 | ... = ... | map.cpp:165:20:165:25 | call to source | | map.cpp:167:7:167:30 | ... = ... | map.cpp:167:23:167:28 | call to source | | map.cpp:190:7:190:9 | call to map | map.cpp:188:39:188:44 | call to source | @@ -90,6 +92,8 @@ | map.cpp:286:7:286:8 | call to unordered_map | map.cpp:257:39:257:44 | call to source | | map.cpp:287:7:287:8 | call to unordered_map | map.cpp:257:39:257:44 | call to source | | map.cpp:288:7:288:8 | call to unordered_map | map.cpp:257:39:257:44 | call to source | +| map.cpp:303:8:303:10 | call to pair | map.cpp:257:39:257:44 | call to source | +| map.cpp:309:8:309:10 | call to pair | map.cpp:258:32:258:37 | call to source | | map.cpp:317:7:317:27 | ... = ... | map.cpp:317:20:317:25 | call to source | | map.cpp:319:7:319:30 | ... = ... | map.cpp:319:23:319:28 | call to source | | map.cpp:339:7:339:9 | call to unordered_map | map.cpp:337:39:337:44 | 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 d122a09780e..1aef1aed8db 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 @@ -50,6 +50,10 @@ | map.cpp:134:7:134:8 | map.cpp:105:39:105:44 | AST only | | map.cpp:135:7:135:8 | map.cpp:105:39:105:44 | AST only | | map.cpp:136:7:136:8 | map.cpp:105:39:105:44 | AST only | +| map.cpp:152:12:152:16 | map.cpp:105:39:105:44 | IR only | +| map.cpp:153:12:153:17 | map.cpp:105:39:105:44 | IR only | +| map.cpp:158:12:158:16 | map.cpp:105:39:105:44 | IR only | +| map.cpp:159:12:159:17 | map.cpp:105:39:105:44 | IR only | | map.cpp:190:7:190:9 | map.cpp:188:39:188:44 | AST only | | map.cpp:190:7:190:9 | map.cpp:188:49:188:54 | AST only | | map.cpp:193:7:193:9 | map.cpp:189:39:189:44 | AST only | @@ -86,6 +90,10 @@ | map.cpp:286:7:286:8 | map.cpp:257:39:257:44 | AST only | | map.cpp:287:7:287:8 | map.cpp:257:39:257:44 | AST only | | map.cpp:288:7:288:8 | map.cpp:257:39:257:44 | AST only | +| map.cpp:304:12:304:16 | map.cpp:257:39:257:44 | IR only | +| map.cpp:305:12:305:17 | map.cpp:257:39:257:44 | IR only | +| map.cpp:310:12:310:16 | map.cpp:257:39:257:44 | IR only | +| map.cpp:311:12:311:17 | map.cpp:257:39:257:44 | IR only | | map.cpp:339:7:339:9 | map.cpp:337:39:337:44 | AST only | | map.cpp:339:7:339:9 | map.cpp:337:49:337:54 | AST only | | map.cpp:342:7:342:9 | map.cpp:338:39:338:44 | 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 b8398be1b45..4b109a6f676 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 @@ -81,11 +81,23 @@ | map.cpp:105:7:105:54 | call to iterator | map.cpp:105:39:105:44 | call to source | | map.cpp:106:7:106:54 | call to iterator | map.cpp:106:32:106:37 | call to source | | map.cpp:107:10:107:15 | call to insert | map.cpp:107:62:107:67 | call to source | +| map.cpp:151:8:151:10 | call to pair | map.cpp:105:39:105:44 | call to source | +| map.cpp:152:12:152:16 | first | map.cpp:105:39:105:44 | call to source | +| map.cpp:153:12:153:17 | second | map.cpp:105:39:105:44 | call to source | +| map.cpp:157:8:157:10 | call to pair | map.cpp:106:32:106:37 | call to source | +| map.cpp:158:12:158:16 | first | map.cpp:105:39:105:44 | call to source | +| map.cpp:159:12:159:17 | second | map.cpp:105:39:105:44 | call to source | | map.cpp:165:7:165:27 | ... = ... | map.cpp:165:20:165:25 | call to source | | map.cpp:167:7:167:30 | ... = ... | map.cpp:167:23:167:28 | call to source | | map.cpp:257:7:257:54 | call to iterator | map.cpp:257:39:257:44 | call to source | | map.cpp:258:7:258:54 | call to iterator | map.cpp:258:32:258:37 | call to source | | map.cpp:259:10:259:15 | call to insert | map.cpp:259:62:259:67 | call to source | +| map.cpp:303:8:303:10 | call to pair | map.cpp:257:39:257:44 | call to source | +| map.cpp:304:12:304:16 | first | map.cpp:257:39:257:44 | call to source | +| map.cpp:305:12:305:17 | second | map.cpp:257:39:257:44 | call to source | +| map.cpp:309:8:309:10 | call to pair | map.cpp:258:32:258:37 | call to source | +| map.cpp:310:12:310:16 | first | map.cpp:257:39:257:44 | call to source | +| map.cpp:311:12:311:17 | second | map.cpp:257:39:257:44 | call to source | | map.cpp:317:7:317:27 | ... = ... | map.cpp:317:20:317:25 | call to source | | map.cpp:319:7:319:30 | ... = ... | map.cpp:319:23:319:28 | call to source | | movableclass.cpp:44:8:44:9 | s1 | movableclass.cpp:39:21:39:26 | call to source | From 13b15d9bcd9ed989caa3a16d20f6beb0f4999720 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Sep 2020 17:26:44 +0100 Subject: [PATCH 050/411] C++: Model swap. --- .../code/cpp/models/implementations/StdMap.qll | 16 ++++++++++++++++ .../dataflow/taint-tests/localTaint.expected | 8 ++++++++ .../library-tests/dataflow/taint-tests/map.cpp | 8 ++++---- .../dataflow/taint-tests/taint.expected | 8 ++++++++ .../dataflow/taint-tests/test_diff.expected | 8 ++++++++ 5 files changed, 44 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll index 151c8e31841..71f3e7217d9 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll @@ -40,3 +40,19 @@ class StdMapBeginEnd extends TaintFunction { output.isReturnValue() } } + +/** + * The standard map `swap` functions. + */ +class StdMapSwap extends TaintFunction { + StdMapSwap() { this.hasQualifiedName("std", ["map", "unordered_map"], "swap") } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // container1.swap(container2) + input.isQualifierObject() and + output.isParameterDeref(0) + or + 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 c1acd2c59c8..814c80f4cae 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -977,15 +977,19 @@ | map.cpp:191:7:191:9 | m16 | map.cpp:191:7:191:9 | call to map | | | map.cpp:192:7:192:9 | m17 | map.cpp:192:7:192:9 | call to map | | | map.cpp:193:7:193:9 | m18 | map.cpp:193:7:193:9 | call to map | | +| map.cpp:194:2:194:4 | m15 | map.cpp:194:11:194:13 | ref arg m16 | TAINT | | map.cpp:194:2:194:4 | ref arg m15 | map.cpp:196:7:196:9 | m15 | | | map.cpp:194:2:194:4 | ref arg m15 | map.cpp:211:2:211:4 | m15 | | | map.cpp:194:2:194:4 | ref arg m15 | map.cpp:249:1:249:1 | m15 | | +| map.cpp:194:11:194:13 | m16 | map.cpp:194:2:194:4 | ref arg m15 | TAINT | | map.cpp:194:11:194:13 | ref arg m16 | map.cpp:197:7:197:9 | m16 | | | map.cpp:194:11:194:13 | ref arg m16 | map.cpp:211:12:211:14 | m16 | | | map.cpp:194:11:194:13 | ref arg m16 | map.cpp:249:1:249:1 | m16 | | +| map.cpp:195:2:195:4 | m17 | map.cpp:195:11:195:13 | ref arg m18 | TAINT | | map.cpp:195:2:195:4 | ref arg m17 | map.cpp:198:7:198:9 | m17 | | | map.cpp:195:2:195:4 | ref arg m17 | map.cpp:212:2:212:4 | m17 | | | map.cpp:195:2:195:4 | ref arg m17 | map.cpp:249:1:249:1 | m17 | | +| map.cpp:195:11:195:13 | m18 | map.cpp:195:2:195:4 | ref arg m17 | TAINT | | map.cpp:195:11:195:13 | ref arg m18 | map.cpp:199:7:199:9 | m18 | | | map.cpp:195:11:195:13 | ref arg m18 | map.cpp:212:12:212:14 | m18 | | | map.cpp:195:11:195:13 | ref arg m18 | map.cpp:249:1:249:1 | m18 | | @@ -1573,15 +1577,19 @@ | map.cpp:340:7:340:9 | m16 | map.cpp:340:7:340:9 | call to unordered_map | | | map.cpp:341:7:341:9 | m17 | map.cpp:341:7:341:9 | call to unordered_map | | | map.cpp:342:7:342:9 | m18 | map.cpp:342:7:342:9 | call to unordered_map | | +| map.cpp:343:2:343:4 | m15 | map.cpp:343:11:343:13 | ref arg m16 | TAINT | | map.cpp:343:2:343:4 | ref arg m15 | map.cpp:345:7:345:9 | m15 | | | map.cpp:343:2:343:4 | ref arg m15 | map.cpp:360:2:360:4 | m15 | | | map.cpp:343:2:343:4 | ref arg m15 | map.cpp:398:1:398:1 | m15 | | +| map.cpp:343:11:343:13 | m16 | map.cpp:343:2:343:4 | ref arg m15 | TAINT | | map.cpp:343:11:343:13 | ref arg m16 | map.cpp:346:7:346:9 | m16 | | | map.cpp:343:11:343:13 | ref arg m16 | map.cpp:360:12:360:14 | m16 | | | map.cpp:343:11:343:13 | ref arg m16 | map.cpp:398:1:398:1 | m16 | | +| map.cpp:344:2:344:4 | m17 | map.cpp:344:11:344:13 | ref arg m18 | TAINT | | map.cpp:344:2:344:4 | ref arg m17 | map.cpp:347:7:347:9 | m17 | | | map.cpp:344:2:344:4 | ref arg m17 | map.cpp:361:2:361:4 | m17 | | | map.cpp:344:2:344:4 | ref arg m17 | map.cpp:398:1:398:1 | m17 | | +| map.cpp:344:11:344:13 | m18 | map.cpp:344:2:344:4 | ref arg m17 | TAINT | | map.cpp:344:11:344:13 | ref arg m18 | map.cpp:348:7:348:9 | m18 | | | map.cpp:344:11:344:13 | ref arg m18 | map.cpp:361:12:361:14 | m18 | | | map.cpp:344:11:344:13 | ref arg m18 | map.cpp:398:1:398:1 | m18 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp index 519ce65fba6..d878fd4d37e 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp @@ -194,8 +194,8 @@ void test_map() m15.swap(m16); m17.swap(m18); sink(m15); // [FALSE POSITIVE] - sink(m16); // tainted [NOT DETECTED] - sink(m17); // tainted [NOT DETECTED] + sink(m16); // tainted + sink(m17); // tainted sink(m18); // [FALSE POSITIVE] // merge @@ -343,8 +343,8 @@ void test_unordered_map() m15.swap(m16); m17.swap(m18); sink(m15); // [FALSE POSITIVE] - sink(m16); // tainted [NOT DETECTED] - sink(m17); // tainted [NOT DETECTED] + sink(m16); // tainted + sink(m17); // tainted sink(m18); // [FALSE POSITIVE] // merge 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 cce0e24c789..05d1a76d53a 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -63,6 +63,10 @@ | map.cpp:193:7:193:9 | call to map | map.cpp:189:49:189:54 | call to source | | map.cpp:196:7:196:9 | call to map | map.cpp:188:39:188:44 | call to source | | map.cpp:196:7:196:9 | call to map | map.cpp:188:49:188:54 | call to source | +| map.cpp:197:7:197:9 | call to map | map.cpp:188:39:188:44 | call to source | +| map.cpp:197:7:197:9 | call to map | map.cpp:188:49:188:54 | call to source | +| map.cpp:198:7:198:9 | call to map | map.cpp:189:39:189:44 | call to source | +| map.cpp:198:7:198:9 | call to map | map.cpp:189:49:189:54 | call to source | | map.cpp:199:7:199:9 | call to map | map.cpp:189:39:189:44 | call to source | | map.cpp:199:7:199:9 | call to map | map.cpp:189:49:189:54 | call to source | | map.cpp:207:7:207:9 | call to map | map.cpp:203:39:203:44 | call to source | @@ -102,6 +106,10 @@ | map.cpp:342:7:342:9 | call to unordered_map | map.cpp:338:49:338:54 | call to source | | map.cpp:345:7:345:9 | call to unordered_map | map.cpp:337:39:337:44 | call to source | | map.cpp:345:7:345:9 | call to unordered_map | map.cpp:337:49:337:54 | call to source | +| map.cpp:346:7:346:9 | call to unordered_map | map.cpp:337:39:337:44 | call to source | +| map.cpp:346:7:346:9 | call to unordered_map | map.cpp:337:49:337:54 | call to source | +| map.cpp:347:7:347:9 | call to unordered_map | map.cpp:338:39:338:44 | call to source | +| map.cpp:347:7:347:9 | call to unordered_map | map.cpp:338:49:338:54 | call to source | | map.cpp:348:7:348:9 | call to unordered_map | map.cpp:338:39:338:44 | call to source | | map.cpp:348:7:348:9 | call to unordered_map | map.cpp:338:49:338:54 | call to source | | map.cpp:356:7:356:9 | call to unordered_map | map.cpp:352:39:352:44 | 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 1aef1aed8db..9a4e5ec0f7a 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 @@ -60,6 +60,10 @@ | map.cpp:193:7:193:9 | map.cpp:189:49:189:54 | AST only | | map.cpp:196:7:196:9 | map.cpp:188:39:188:44 | AST only | | map.cpp:196:7:196:9 | map.cpp:188:49:188:54 | AST only | +| map.cpp:197:7:197:9 | map.cpp:188:39:188:44 | AST only | +| map.cpp:197:7:197:9 | map.cpp:188:49:188:54 | AST only | +| map.cpp:198:7:198:9 | map.cpp:189:39:189:44 | AST only | +| map.cpp:198:7:198:9 | map.cpp:189:49:189:54 | AST only | | map.cpp:199:7:199:9 | map.cpp:189:39:189:44 | AST only | | map.cpp:199:7:199:9 | map.cpp:189:49:189:54 | AST only | | map.cpp:207:7:207:9 | map.cpp:203:39:203:44 | AST only | @@ -100,6 +104,10 @@ | map.cpp:342:7:342:9 | map.cpp:338:49:338:54 | AST only | | map.cpp:345:7:345:9 | map.cpp:337:39:337:44 | AST only | | map.cpp:345:7:345:9 | map.cpp:337:49:337:54 | AST only | +| map.cpp:346:7:346:9 | map.cpp:337:39:337:44 | AST only | +| map.cpp:346:7:346:9 | map.cpp:337:49:337:54 | AST only | +| map.cpp:347:7:347:9 | map.cpp:338:39:338:44 | AST only | +| map.cpp:347:7:347:9 | map.cpp:338:49:338:54 | AST only | | map.cpp:348:7:348:9 | map.cpp:338:39:338:44 | AST only | | map.cpp:348:7:348:9 | map.cpp:338:49:338:54 | AST only | | map.cpp:356:7:356:9 | map.cpp:352:39:352:44 | AST only | From c51294e423cce5e325c4966cb74b18e98e81b2e9 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Sep 2020 17:39:49 +0100 Subject: [PATCH 051/411] C++: Model operator[] and at. --- .../cpp/models/implementations/StdMap.qll | 17 +++++++++++++ .../dataflow/taint-tests/localTaint.expected | 24 +++++++++++++++++++ .../dataflow/taint-tests/map.cpp | 8 +++---- .../dataflow/taint-tests/taint.expected | 4 ++++ .../dataflow/taint-tests/test_diff.expected | 4 ++++ 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll index 71f3e7217d9..b85b6435ff5 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll @@ -56,3 +56,20 @@ class StdMapSwap extends TaintFunction { output.isQualifierObject() } } + +/** + * The standard map functions `at` and `operator[]`. + */ +class StdMapAt extends TaintFunction { + StdMapAt() { this.hasQualifiedName("std", ["map", "unordered_map"], ["at", "operator[]"]) } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from qualifier to referenced return value + input.isQualifierObject() and + output.isReturnValueDeref() + or + // reverse flow from returned reference to the qualifier + input.isReturnValueDeref() and + output.isQualifierObject() + } +} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 814c80f4cae..7882c9c1106 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -852,25 +852,37 @@ | map.cpp:163:42:163:44 | call to map | map.cpp:167:7:167:9 | m13 | | | map.cpp:163:42:163:44 | call to map | map.cpp:171:7:171:9 | m13 | | | map.cpp:163:42:163:44 | call to map | map.cpp:249:1:249:1 | m13 | | +| map.cpp:164:7:164:9 | m10 | map.cpp:164:10:164:10 | call to operator[] | TAINT | | map.cpp:164:7:164:9 | ref arg m10 | map.cpp:168:7:168:9 | m10 | | | map.cpp:164:7:164:9 | ref arg m10 | map.cpp:249:1:249:1 | m10 | | | map.cpp:164:7:164:24 | ... = ... | map.cpp:164:10:164:10 | call to operator[] [post update] | | +| map.cpp:164:10:164:10 | call to operator[] [post update] | map.cpp:164:7:164:9 | ref arg m10 | TAINT | | map.cpp:164:20:164:24 | def | map.cpp:164:7:164:24 | ... = ... | | +| map.cpp:165:7:165:9 | m11 | map.cpp:165:10:165:10 | call to operator[] | TAINT | | map.cpp:165:7:165:9 | ref arg m11 | map.cpp:169:7:169:9 | m11 | | | map.cpp:165:7:165:9 | ref arg m11 | map.cpp:249:1:249:1 | m11 | | | map.cpp:165:7:165:27 | ... = ... | map.cpp:165:10:165:10 | call to operator[] [post update] | | +| map.cpp:165:10:165:10 | call to operator[] [post update] | map.cpp:165:7:165:9 | ref arg m11 | TAINT | | map.cpp:165:20:165:25 | call to source | map.cpp:165:7:165:27 | ... = ... | | +| map.cpp:166:7:166:9 | m12 | map.cpp:166:11:166:12 | call to at | TAINT | | map.cpp:166:7:166:9 | ref arg m12 | map.cpp:170:7:170:9 | m12 | | | map.cpp:166:7:166:9 | ref arg m12 | map.cpp:249:1:249:1 | m12 | | | map.cpp:166:7:166:27 | ... = ... | map.cpp:166:11:166:12 | call to at [post update] | | +| map.cpp:166:11:166:12 | call to at [post update] | map.cpp:166:7:166:9 | ref arg m12 | TAINT | | map.cpp:166:23:166:27 | def | map.cpp:166:7:166:27 | ... = ... | | +| map.cpp:167:7:167:9 | m13 | map.cpp:167:11:167:12 | call to at | TAINT | | map.cpp:167:7:167:9 | ref arg m13 | map.cpp:171:7:171:9 | m13 | | | map.cpp:167:7:167:9 | ref arg m13 | map.cpp:249:1:249:1 | m13 | | | map.cpp:167:7:167:30 | ... = ... | map.cpp:167:11:167:12 | call to at [post update] | | +| map.cpp:167:11:167:12 | call to at [post update] | map.cpp:167:7:167:9 | ref arg m13 | TAINT | | map.cpp:167:23:167:28 | call to source | map.cpp:167:7:167:30 | ... = ... | | +| map.cpp:168:7:168:9 | m10 | map.cpp:168:10:168:10 | call to operator[] | TAINT | | map.cpp:168:7:168:9 | ref arg m10 | map.cpp:249:1:249:1 | m10 | | +| map.cpp:169:7:169:9 | m11 | map.cpp:169:10:169:10 | call to operator[] | TAINT | | map.cpp:169:7:169:9 | ref arg m11 | map.cpp:249:1:249:1 | m11 | | +| map.cpp:170:7:170:9 | m12 | map.cpp:170:10:170:10 | call to operator[] | TAINT | | map.cpp:170:7:170:9 | ref arg m12 | map.cpp:249:1:249:1 | m12 | | +| map.cpp:171:7:171:9 | m13 | map.cpp:171:10:171:10 | call to operator[] | TAINT | | map.cpp:171:7:171:9 | ref arg m13 | map.cpp:249:1:249:1 | m13 | | | map.cpp:174:27:174:29 | call to map | map.cpp:175:2:175:4 | m14 | | | map.cpp:174:27:174:29 | call to map | map.cpp:176:2:176:4 | m14 | | @@ -1467,25 +1479,37 @@ | map.cpp:315:52:315:54 | call to unordered_map | map.cpp:319:7:319:9 | m13 | | | map.cpp:315:52:315:54 | call to unordered_map | map.cpp:323:7:323:9 | m13 | | | map.cpp:315:52:315:54 | call to unordered_map | map.cpp:398:1:398:1 | m13 | | +| map.cpp:316:7:316:9 | m10 | map.cpp:316:10:316:10 | call to operator[] | TAINT | | map.cpp:316:7:316:9 | ref arg m10 | map.cpp:320:7:320:9 | m10 | | | map.cpp:316:7:316:9 | ref arg m10 | map.cpp:398:1:398:1 | m10 | | | map.cpp:316:7:316:24 | ... = ... | map.cpp:316:10:316:10 | call to operator[] [post update] | | +| map.cpp:316:10:316:10 | call to operator[] [post update] | map.cpp:316:7:316:9 | ref arg m10 | TAINT | | map.cpp:316:20:316:24 | def | map.cpp:316:7:316:24 | ... = ... | | +| map.cpp:317:7:317:9 | m11 | map.cpp:317:10:317:10 | call to operator[] | TAINT | | map.cpp:317:7:317:9 | ref arg m11 | map.cpp:321:7:321:9 | m11 | | | map.cpp:317:7:317:9 | ref arg m11 | map.cpp:398:1:398:1 | m11 | | | map.cpp:317:7:317:27 | ... = ... | map.cpp:317:10:317:10 | call to operator[] [post update] | | +| map.cpp:317:10:317:10 | call to operator[] [post update] | map.cpp:317:7:317:9 | ref arg m11 | TAINT | | map.cpp:317:20:317:25 | call to source | map.cpp:317:7:317:27 | ... = ... | | +| map.cpp:318:7:318:9 | m12 | map.cpp:318:11:318:12 | call to at | TAINT | | map.cpp:318:7:318:9 | ref arg m12 | map.cpp:322:7:322:9 | m12 | | | map.cpp:318:7:318:9 | ref arg m12 | map.cpp:398:1:398:1 | m12 | | | map.cpp:318:7:318:27 | ... = ... | map.cpp:318:11:318:12 | call to at [post update] | | +| map.cpp:318:11:318:12 | call to at [post update] | map.cpp:318:7:318:9 | ref arg m12 | TAINT | | map.cpp:318:23:318:27 | def | map.cpp:318:7:318:27 | ... = ... | | +| map.cpp:319:7:319:9 | m13 | map.cpp:319:11:319:12 | call to at | TAINT | | map.cpp:319:7:319:9 | ref arg m13 | map.cpp:323:7:323:9 | m13 | | | map.cpp:319:7:319:9 | ref arg m13 | map.cpp:398:1:398:1 | m13 | | | map.cpp:319:7:319:30 | ... = ... | map.cpp:319:11:319:12 | call to at [post update] | | +| map.cpp:319:11:319:12 | call to at [post update] | map.cpp:319:7:319:9 | ref arg m13 | TAINT | | map.cpp:319:23:319:28 | call to source | map.cpp:319:7:319:30 | ... = ... | | +| map.cpp:320:7:320:9 | m10 | map.cpp:320:10:320:10 | call to operator[] | TAINT | | map.cpp:320:7:320:9 | ref arg m10 | map.cpp:398:1:398:1 | m10 | | +| map.cpp:321:7:321:9 | m11 | map.cpp:321:10:321:10 | call to operator[] | TAINT | | map.cpp:321:7:321:9 | ref arg m11 | map.cpp:398:1:398:1 | m11 | | +| map.cpp:322:7:322:9 | m12 | map.cpp:322:10:322:10 | call to operator[] | TAINT | | map.cpp:322:7:322:9 | ref arg m12 | map.cpp:398:1:398:1 | m12 | | +| map.cpp:323:7:323:9 | m13 | map.cpp:323:10:323:10 | call to operator[] | TAINT | | map.cpp:323:7:323:9 | ref arg m13 | map.cpp:398:1:398:1 | m13 | | | map.cpp:326:37:326:39 | call to unordered_map | map.cpp:327:2:327:4 | m14 | | | map.cpp:326:37:326:39 | call to unordered_map | map.cpp:328:2:328:4 | m14 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp index d878fd4d37e..34441b012ae 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp @@ -166,9 +166,9 @@ void test_map() sink(m12.at("abc") = "def"); sink(m13.at("abc") = source()); // tainted sink(m10["abc"]); - sink(m11["abc"]); // tainted [NOT DETECTED] + sink(m11["abc"]); // tainted sink(m12["abc"]); - sink(m13["abc"]); // tainted [NOT DETECTED] + sink(m13["abc"]); // tainted // ranges std::map m14; @@ -318,9 +318,9 @@ void test_unordered_map() sink(m12.at("abc") = "def"); sink(m13.at("abc") = source()); // tainted sink(m10["abc"]); - sink(m11["abc"]); // tainted [NOT DETECTED] + sink(m11["abc"]); // tainted sink(m12["abc"]); - sink(m13["abc"]); // tainted [NOT DETECTED] + sink(m13["abc"]); // tainted // ranges std::unordered_map m14; 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 05d1a76d53a..f5b483010a8 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -57,6 +57,8 @@ | map.cpp:157:8:157:10 | call to pair | map.cpp:106:32:106:37 | call to source | | map.cpp:165:7:165:27 | ... = ... | map.cpp:165:20:165:25 | call to source | | map.cpp:167:7:167:30 | ... = ... | map.cpp:167:23:167:28 | call to source | +| map.cpp:169:10:169:10 | call to operator[] | map.cpp:165:20:165:25 | call to source | +| map.cpp:171:10:171:10 | call to operator[] | map.cpp:167:23:167:28 | call to source | | map.cpp:190:7:190:9 | call to map | map.cpp:188:39:188:44 | call to source | | map.cpp:190:7:190:9 | call to map | map.cpp:188:49:188:54 | call to source | | map.cpp:193:7:193:9 | call to map | map.cpp:189:39:189:44 | call to source | @@ -100,6 +102,8 @@ | map.cpp:309:8:309:10 | call to pair | map.cpp:258:32:258:37 | call to source | | map.cpp:317:7:317:27 | ... = ... | map.cpp:317:20:317:25 | call to source | | map.cpp:319:7:319:30 | ... = ... | map.cpp:319:23:319:28 | call to source | +| map.cpp:321:10:321:10 | call to operator[] | map.cpp:317:20:317:25 | call to source | +| map.cpp:323:10:323:10 | call to operator[] | map.cpp:319:23:319:28 | call to source | | map.cpp:339:7:339:9 | call to unordered_map | map.cpp:337:39:337:44 | call to source | | map.cpp:339:7:339:9 | call to unordered_map | map.cpp:337:49:337:54 | call to source | | map.cpp:342:7:342:9 | call to unordered_map | map.cpp:338:39:338:44 | 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 9a4e5ec0f7a..3f0e87fac6b 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 @@ -54,6 +54,8 @@ | map.cpp:153:12:153:17 | map.cpp:105:39:105:44 | IR only | | map.cpp:158:12:158:16 | map.cpp:105:39:105:44 | IR only | | map.cpp:159:12:159:17 | map.cpp:105:39:105:44 | IR only | +| map.cpp:169:10:169:10 | map.cpp:165:20:165:25 | AST only | +| map.cpp:171:10:171:10 | map.cpp:167:23:167:28 | AST only | | map.cpp:190:7:190:9 | map.cpp:188:39:188:44 | AST only | | map.cpp:190:7:190:9 | map.cpp:188:49:188:54 | AST only | | map.cpp:193:7:193:9 | map.cpp:189:39:189:44 | AST only | @@ -98,6 +100,8 @@ | map.cpp:305:12:305:17 | map.cpp:257:39:257:44 | IR only | | map.cpp:310:12:310:16 | map.cpp:257:39:257:44 | IR only | | map.cpp:311:12:311:17 | map.cpp:257:39:257:44 | IR only | +| map.cpp:321:10:321:10 | map.cpp:317:20:317:25 | AST only | +| map.cpp:323:10:323:10 | map.cpp:319:23:319:28 | AST only | | map.cpp:339:7:339:9 | map.cpp:337:39:337:44 | AST only | | map.cpp:339:7:339:9 | map.cpp:337:49:337:54 | AST only | | map.cpp:342:7:342:9 | map.cpp:338:39:338:44 | AST only | From d550741c0c82d105c88d9800d15169a041e7c4cb Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Sep 2020 17:50:23 +0100 Subject: [PATCH 052/411] C++: Model insert_or_assign. --- .../code/cpp/models/implementations/StdMap.qll | 4 ++-- .../dataflow/taint-tests/localTaint.expected | 8 ++++++++ .../library-tests/dataflow/taint-tests/map.cpp | 16 ++++++++-------- .../dataflow/taint-tests/taint.expected | 6 ++++++ .../dataflow/taint-tests/test_diff.expected | 6 ++++++ .../dataflow/taint-tests/test_ir.expected | 4 ++++ 6 files changed, 34 insertions(+), 10 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll index b85b6435ff5..9ada1315a77 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll @@ -6,11 +6,11 @@ import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.implementations.Iterator /** - * The standard map `insert` function. + * The standard map `insert` and `insert_or_assign` functions. */ class StdMapInsert extends TaintFunction { StdMapInsert() { - this.hasQualifiedName("std", ["map", "unordered_map"], "insert") + this.hasQualifiedName("std", ["map", "unordered_map"], ["insert", "insert_or_assign"]) } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { 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 7882c9c1106..fbb319fc11d 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -673,6 +673,8 @@ | map.cpp:108:7:108:8 | ref arg m5 | map.cpp:120:7:120:8 | m5 | | | map.cpp:108:7:108:8 | ref arg m5 | map.cpp:126:7:126:8 | m5 | | | map.cpp:108:7:108:8 | ref arg m5 | map.cpp:249:1:249:1 | m5 | | +| map.cpp:108:34:108:39 | call to source | map.cpp:108:7:108:8 | ref arg m5 | TAINT | +| map.cpp:108:34:108:39 | call to source | map.cpp:108:10:108:25 | call to insert_or_assign | TAINT | | map.cpp:108:44:108:48 | first | map.cpp:108:7:108:48 | call to iterator | | | map.cpp:109:7:109:8 | ref arg m6 | map.cpp:115:7:115:8 | m6 | | | map.cpp:109:7:109:8 | ref arg m6 | map.cpp:121:7:121:8 | m6 | | @@ -685,6 +687,8 @@ | map.cpp:109:27:109:28 | ref arg m6 | map.cpp:127:7:127:8 | m6 | | | map.cpp:109:27:109:28 | ref arg m6 | map.cpp:249:1:249:1 | m6 | | | map.cpp:109:30:109:34 | call to begin | map.cpp:109:27:109:36 | call to iterator | TAINT | +| map.cpp:109:46:109:51 | call to source | map.cpp:109:7:109:8 | ref arg m6 | TAINT | +| map.cpp:109:46:109:51 | call to source | map.cpp:109:10:109:25 | call to insert_or_assign | TAINT | | map.cpp:110:7:110:8 | m1 | map.cpp:110:7:110:8 | call to map | | | map.cpp:111:7:111:8 | m2 | map.cpp:111:7:111:8 | call to map | | | map.cpp:112:7:112:8 | m3 | map.cpp:112:7:112:8 | call to map | | @@ -1312,6 +1316,8 @@ | map.cpp:260:7:260:8 | ref arg m5 | map.cpp:272:7:272:8 | m5 | | | map.cpp:260:7:260:8 | ref arg m5 | map.cpp:278:7:278:8 | m5 | | | map.cpp:260:7:260:8 | ref arg m5 | map.cpp:398:1:398:1 | m5 | | +| map.cpp:260:34:260:39 | call to source | map.cpp:260:7:260:8 | ref arg m5 | TAINT | +| map.cpp:260:34:260:39 | call to source | map.cpp:260:10:260:25 | call to insert_or_assign | TAINT | | map.cpp:260:44:260:48 | first | map.cpp:260:7:260:48 | call to iterator | | | map.cpp:261:7:261:8 | ref arg m6 | map.cpp:267:7:267:8 | m6 | | | map.cpp:261:7:261:8 | ref arg m6 | map.cpp:273:7:273:8 | m6 | | @@ -1324,6 +1330,8 @@ | map.cpp:261:27:261:28 | ref arg m6 | map.cpp:279:7:279:8 | m6 | | | map.cpp:261:27:261:28 | ref arg m6 | map.cpp:398:1:398:1 | m6 | | | map.cpp:261:30:261:34 | call to begin | map.cpp:261:27:261:36 | call to iterator | TAINT | +| map.cpp:261:46:261:51 | call to source | map.cpp:261:7:261:8 | ref arg m6 | TAINT | +| map.cpp:261:46:261:51 | call to source | map.cpp:261:10:261:25 | call to insert_or_assign | TAINT | | map.cpp:262:7:262:8 | m1 | map.cpp:262:7:262:8 | call to unordered_map | | | map.cpp:263:7:263:8 | m2 | map.cpp:263:7:263:8 | call to unordered_map | | | map.cpp:264:7:264:8 | m3 | map.cpp:264:7:264:8 | call to unordered_map | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp index 34441b012ae..fc474862fa9 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp @@ -105,14 +105,14 @@ void test_map() sink(m2.insert(std::make_pair("abc", source())).first); // tainted [NOT DETECTED] sink(m3.insert(std::make_pair(source(), "def")).first); // tainted [NOT DETECTED] sink(m4.insert(m4.begin(), std::pair("abc", source()))); // tainted - sink(m5.insert_or_assign("abc", source()).first); // tainted [NOT DETECTED] - sink(m6.insert_or_assign(m6.begin(), "abc", source())); // tainted [NOT DETECTED] + sink(m5.insert_or_assign("abc", source()).first); // tainted + sink(m6.insert_or_assign(m6.begin(), "abc", source())); // tainted sink(m1); sink(m2); // tainted sink(m3); // tainted sink(m4); // tainted - sink(m5); // tainted [NOT DETECTED] - sink(m6); // tainted [NOT DETECTED] + sink(m5); // tainted + sink(m6); // tainted sink(m1.find("abc")); sink(m2.find("abc")); // tainted [NOT DETECTED] sink(m3.find("abc")); @@ -257,14 +257,14 @@ void test_unordered_map() sink(m2.insert(std::make_pair("abc", source())).first); // tainted [NOT DETECTED] sink(m3.insert(std::make_pair(source(), "def")).first); // tainted [NOT DETECTED] sink(m4.insert(m4.begin(), std::pair("abc", source()))); // tainted - sink(m5.insert_or_assign("abc", source()).first); // tainted [NOT DETECTED] - sink(m6.insert_or_assign(m6.begin(), "abc", source())); // tainted [NOT DETECTED] + sink(m5.insert_or_assign("abc", source()).first); // tainted + sink(m6.insert_or_assign(m6.begin(), "abc", source())); // tainted sink(m1); sink(m2); // tainted sink(m3); // tainted sink(m4); // tainted - sink(m5); // tainted [NOT DETECTED] - sink(m6); // tainted [NOT DETECTED] + sink(m5); // tainted + sink(m6); // tainted sink(m1.find("abc")); sink(m2.find("abc")); // tainted [NOT DETECTED] sink(m3.find("abc")); 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 f5b483010a8..1dff0a61f9f 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -47,9 +47,12 @@ | map.cpp:86:7:86:32 | call to pair | map.cpp:86:24:86:29 | call to source | | map.cpp:92:7:92:7 | call to pair | map.cpp:91:33:91:38 | call to source | | map.cpp:107:10:107:15 | call to insert | map.cpp:107:62:107:67 | call to source | +| map.cpp:109:10:109:25 | call to insert_or_assign | map.cpp:109:46:109:51 | call to source | | map.cpp:111:7:111:8 | call to map | map.cpp:105:39:105:44 | call to source | | map.cpp:112:7:112:8 | call to map | map.cpp:106:32:106:37 | call to source | | map.cpp:113:7:113:8 | call to map | map.cpp:107:62:107:67 | call to source | +| map.cpp:114:7:114:8 | call to map | map.cpp:108:34:108:39 | call to source | +| map.cpp:115:7:115:8 | call to map | map.cpp:109:46:109:51 | call to source | | map.cpp:134:7:134:8 | call to map | map.cpp:105:39:105:44 | call to source | | map.cpp:135:7:135:8 | call to map | map.cpp:105:39:105:44 | call to source | | map.cpp:136:7:136:8 | call to map | map.cpp:105:39:105:44 | call to source | @@ -92,9 +95,12 @@ | map.cpp:226:7:226:9 | call to map | map.cpp:221:39:221:44 | call to source | | map.cpp:226:7:226:9 | call to map | map.cpp:221:49:221:54 | call to source | | map.cpp:259:10:259:15 | call to insert | map.cpp:259:62:259:67 | call to source | +| map.cpp:261:10:261:25 | call to insert_or_assign | map.cpp:261:46:261:51 | call to source | | map.cpp:263:7:263:8 | call to unordered_map | map.cpp:257:39:257:44 | call to source | | map.cpp:264:7:264:8 | call to unordered_map | map.cpp:258:32:258:37 | call to source | | map.cpp:265:7:265:8 | call to unordered_map | map.cpp:259:62:259:67 | call to source | +| map.cpp:266:7:266:8 | call to unordered_map | map.cpp:260:34:260:39 | call to source | +| map.cpp:267:7:267:8 | call to unordered_map | map.cpp:261:46:261:51 | call to source | | map.cpp:286:7:286:8 | call to unordered_map | map.cpp:257:39:257:44 | call to source | | map.cpp:287:7:287:8 | call to unordered_map | map.cpp:257:39:257:44 | call to source | | map.cpp:288:7:288:8 | call to unordered_map | map.cpp:257:39:257:44 | 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 3f0e87fac6b..3886aee6ea7 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 @@ -44,9 +44,12 @@ | map.cpp:96:9:96:14 | map.cpp:91:33:91:38 | IR only | | map.cpp:105:7:105:54 | map.cpp:105:39:105:44 | IR only | | map.cpp:106:7:106:54 | map.cpp:106:32:106:37 | IR only | +| map.cpp:108:7:108:48 | map.cpp:108:34:108:39 | IR only | | map.cpp:111:7:111:8 | map.cpp:105:39:105:44 | AST only | | map.cpp:112:7:112:8 | map.cpp:106:32:106:37 | AST only | | map.cpp:113:7:113:8 | map.cpp:107:62:107:67 | AST only | +| map.cpp:114:7:114:8 | map.cpp:108:34:108:39 | AST only | +| map.cpp:115:7:115:8 | map.cpp:109:46:109:51 | AST only | | map.cpp:134:7:134:8 | map.cpp:105:39:105:44 | AST only | | map.cpp:135:7:135:8 | map.cpp:105:39:105:44 | AST only | | map.cpp:136:7:136:8 | map.cpp:105:39:105:44 | AST only | @@ -90,9 +93,12 @@ | map.cpp:226:7:226:9 | map.cpp:221:49:221:54 | AST only | | map.cpp:257:7:257:54 | map.cpp:257:39:257:44 | IR only | | map.cpp:258:7:258:54 | map.cpp:258:32:258:37 | IR only | +| map.cpp:260:7:260:48 | map.cpp:260:34:260:39 | IR only | | map.cpp:263:7:263:8 | map.cpp:257:39:257:44 | AST only | | map.cpp:264:7:264:8 | map.cpp:258:32:258:37 | AST only | | map.cpp:265:7:265:8 | map.cpp:259:62:259:67 | AST only | +| map.cpp:266:7:266:8 | map.cpp:260:34:260:39 | AST only | +| map.cpp:267:7:267:8 | map.cpp:261:46:261:51 | AST only | | map.cpp:286:7:286:8 | map.cpp:257:39:257:44 | AST only | | map.cpp:287:7:287:8 | map.cpp:257:39:257:44 | AST only | | map.cpp:288:7:288:8 | map.cpp:257:39:257:44 | 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 4b109a6f676..41803ad3039 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 @@ -81,6 +81,8 @@ | map.cpp:105:7:105:54 | call to iterator | map.cpp:105:39:105:44 | call to source | | map.cpp:106:7:106:54 | call to iterator | map.cpp:106:32:106:37 | call to source | | map.cpp:107:10:107:15 | call to insert | map.cpp:107:62:107:67 | call to source | +| map.cpp:108:7:108:48 | call to iterator | map.cpp:108:34:108:39 | call to source | +| map.cpp:109:10:109:25 | call to insert_or_assign | map.cpp:109:46:109:51 | call to source | | map.cpp:151:8:151:10 | call to pair | map.cpp:105:39:105:44 | call to source | | map.cpp:152:12:152:16 | first | map.cpp:105:39:105:44 | call to source | | map.cpp:153:12:153:17 | second | map.cpp:105:39:105:44 | call to source | @@ -92,6 +94,8 @@ | map.cpp:257:7:257:54 | call to iterator | map.cpp:257:39:257:44 | call to source | | map.cpp:258:7:258:54 | call to iterator | map.cpp:258:32:258:37 | call to source | | map.cpp:259:10:259:15 | call to insert | map.cpp:259:62:259:67 | call to source | +| map.cpp:260:7:260:48 | call to iterator | map.cpp:260:34:260:39 | call to source | +| map.cpp:261:10:261:25 | call to insert_or_assign | map.cpp:261:46:261:51 | call to source | | map.cpp:303:8:303:10 | call to pair | map.cpp:257:39:257:44 | call to source | | map.cpp:304:12:304:16 | first | map.cpp:257:39:257:44 | call to source | | map.cpp:305:12:305:17 | second | map.cpp:257:39:257:44 | call to source | From 8b91d5077d0ea0f036ebcfed66f765240aeb48c2 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Sep 2020 18:06:41 +0100 Subject: [PATCH 053/411] C++: Model find. --- .../cpp/models/implementations/StdMap.qll | 14 +++++ .../dataflow/taint-tests/localTaint.expected | 30 +++++++++++ .../dataflow/taint-tests/map.cpp | 52 +++++++++---------- .../dataflow/taint-tests/taint.expected | 26 ++++++++++ .../dataflow/taint-tests/test_diff.expected | 12 +++++ .../dataflow/taint-tests/test_ir.expected | 14 +++++ 6 files changed, 122 insertions(+), 26 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll index 9ada1315a77..098da1ec8da 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll @@ -73,3 +73,17 @@ class StdMapAt extends TaintFunction { output.isQualifierObject() } } + +/** + * The standard map `find` function. + */ +class StdMapFind extends TaintFunction { + StdMapFind() { + this.hasQualifiedName("std", ["map", "unordered_map"], "find") + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + input.isQualifierObject() and + output.isReturnValue() + } +} 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 fbb319fc11d..d0d4f6462f9 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -695,10 +695,12 @@ | map.cpp:113:7:113:8 | m4 | map.cpp:113:7:113:8 | call to map | | | map.cpp:114:7:114:8 | m5 | map.cpp:114:7:114:8 | call to map | | | map.cpp:115:7:115:8 | m6 | map.cpp:115:7:115:8 | call to map | | +| map.cpp:116:7:116:8 | m1 | map.cpp:116:10:116:13 | call to find | TAINT | | map.cpp:116:7:116:8 | ref arg m1 | map.cpp:122:7:122:8 | m1 | | | map.cpp:116:7:116:8 | ref arg m1 | map.cpp:143:12:143:13 | m1 | | | map.cpp:116:7:116:8 | ref arg m1 | map.cpp:143:30:143:31 | m1 | | | map.cpp:116:7:116:8 | ref arg m1 | map.cpp:249:1:249:1 | m1 | | +| map.cpp:117:7:117:8 | m2 | map.cpp:117:10:117:13 | call to find | TAINT | | map.cpp:117:7:117:8 | ref arg m2 | map.cpp:123:7:123:8 | m2 | | | map.cpp:117:7:117:8 | ref arg m2 | map.cpp:130:30:130:31 | m2 | | | map.cpp:117:7:117:8 | ref arg m2 | map.cpp:131:32:131:33 | m2 | | @@ -712,19 +714,25 @@ | map.cpp:117:7:117:8 | ref arg m2 | map.cpp:183:7:183:8 | m2 | | | map.cpp:117:7:117:8 | ref arg m2 | map.cpp:184:7:184:8 | m2 | | | map.cpp:117:7:117:8 | ref arg m2 | map.cpp:249:1:249:1 | m2 | | +| map.cpp:118:7:118:8 | m3 | map.cpp:118:10:118:13 | call to find | TAINT | | map.cpp:118:7:118:8 | ref arg m3 | map.cpp:124:7:124:8 | m3 | | | map.cpp:118:7:118:8 | ref arg m3 | map.cpp:155:12:155:13 | m3 | | | map.cpp:118:7:118:8 | ref arg m3 | map.cpp:155:30:155:31 | m3 | | | map.cpp:118:7:118:8 | ref arg m3 | map.cpp:249:1:249:1 | m3 | | +| map.cpp:119:7:119:8 | m4 | map.cpp:119:10:119:13 | call to find | TAINT | | map.cpp:119:7:119:8 | ref arg m4 | map.cpp:125:7:125:8 | m4 | | | map.cpp:119:7:119:8 | ref arg m4 | map.cpp:249:1:249:1 | m4 | | +| map.cpp:120:7:120:8 | m5 | map.cpp:120:10:120:13 | call to find | TAINT | | map.cpp:120:7:120:8 | ref arg m5 | map.cpp:126:7:126:8 | m5 | | | map.cpp:120:7:120:8 | ref arg m5 | map.cpp:249:1:249:1 | m5 | | +| map.cpp:121:7:121:8 | m6 | map.cpp:121:10:121:13 | call to find | TAINT | | map.cpp:121:7:121:8 | ref arg m6 | map.cpp:127:7:127:8 | m6 | | | map.cpp:121:7:121:8 | ref arg m6 | map.cpp:249:1:249:1 | m6 | | +| map.cpp:122:7:122:8 | m1 | map.cpp:122:10:122:13 | call to find | TAINT | | map.cpp:122:7:122:8 | ref arg m1 | map.cpp:143:12:143:13 | m1 | | | map.cpp:122:7:122:8 | ref arg m1 | map.cpp:143:30:143:31 | m1 | | | map.cpp:122:7:122:8 | ref arg m1 | map.cpp:249:1:249:1 | m1 | | +| map.cpp:123:7:123:8 | m2 | map.cpp:123:10:123:13 | call to find | TAINT | | map.cpp:123:7:123:8 | ref arg m2 | map.cpp:130:30:130:31 | m2 | | | map.cpp:123:7:123:8 | ref arg m2 | map.cpp:131:32:131:33 | m2 | | | map.cpp:123:7:123:8 | ref arg m2 | map.cpp:133:7:133:8 | m2 | | @@ -737,11 +745,15 @@ | map.cpp:123:7:123:8 | ref arg m2 | map.cpp:183:7:183:8 | m2 | | | map.cpp:123:7:123:8 | ref arg m2 | map.cpp:184:7:184:8 | m2 | | | map.cpp:123:7:123:8 | ref arg m2 | map.cpp:249:1:249:1 | m2 | | +| map.cpp:124:7:124:8 | m3 | map.cpp:124:10:124:13 | call to find | TAINT | | map.cpp:124:7:124:8 | ref arg m3 | map.cpp:155:12:155:13 | m3 | | | map.cpp:124:7:124:8 | ref arg m3 | map.cpp:155:30:155:31 | m3 | | | map.cpp:124:7:124:8 | ref arg m3 | map.cpp:249:1:249:1 | m3 | | +| map.cpp:125:7:125:8 | m4 | map.cpp:125:10:125:13 | call to find | TAINT | | map.cpp:125:7:125:8 | ref arg m4 | map.cpp:249:1:249:1 | m4 | | +| map.cpp:126:7:126:8 | m5 | map.cpp:126:10:126:13 | call to find | TAINT | | map.cpp:126:7:126:8 | ref arg m5 | map.cpp:249:1:249:1 | m5 | | +| map.cpp:127:7:127:8 | m6 | map.cpp:127:10:127:13 | call to find | TAINT | | map.cpp:127:7:127:8 | ref arg m6 | map.cpp:249:1:249:1 | m6 | | | map.cpp:130:30:130:31 | m2 | map.cpp:130:30:130:32 | call to map | | | map.cpp:130:30:130:32 | call to map | map.cpp:134:7:134:8 | m7 | | @@ -763,8 +775,11 @@ | map.cpp:134:7:134:8 | m7 | map.cpp:134:7:134:8 | call to map | | | map.cpp:135:7:135:8 | m8 | map.cpp:135:7:135:8 | call to map | | | map.cpp:136:7:136:8 | m9 | map.cpp:136:7:136:8 | call to map | | +| map.cpp:137:7:137:8 | m7 | map.cpp:137:10:137:13 | call to find | TAINT | | map.cpp:137:7:137:8 | ref arg m7 | map.cpp:249:1:249:1 | m7 | | +| map.cpp:138:7:138:8 | m8 | map.cpp:138:10:138:13 | call to find | TAINT | | map.cpp:138:7:138:8 | ref arg m8 | map.cpp:249:1:249:1 | m8 | | +| map.cpp:139:7:139:8 | m9 | map.cpp:139:10:139:13 | call to find | TAINT | | map.cpp:139:7:139:8 | ref arg m9 | map.cpp:249:1:249:1 | m9 | | | map.cpp:143:12:143:13 | m1 | map.cpp:143:15:143:19 | call to begin | TAINT | | map.cpp:143:12:143:13 | ref arg m1 | map.cpp:143:30:143:31 | m1 | | @@ -1338,10 +1353,12 @@ | map.cpp:265:7:265:8 | m4 | map.cpp:265:7:265:8 | call to unordered_map | | | map.cpp:266:7:266:8 | m5 | map.cpp:266:7:266:8 | call to unordered_map | | | map.cpp:267:7:267:8 | m6 | map.cpp:267:7:267:8 | call to unordered_map | | +| map.cpp:268:7:268:8 | m1 | map.cpp:268:10:268:13 | call to find | TAINT | | map.cpp:268:7:268:8 | ref arg m1 | map.cpp:274:7:274:8 | m1 | | | map.cpp:268:7:268:8 | ref arg m1 | map.cpp:295:12:295:13 | m1 | | | map.cpp:268:7:268:8 | ref arg m1 | map.cpp:295:30:295:31 | m1 | | | map.cpp:268:7:268:8 | ref arg m1 | map.cpp:398:1:398:1 | m1 | | +| map.cpp:269:7:269:8 | m2 | map.cpp:269:10:269:13 | call to find | TAINT | | map.cpp:269:7:269:8 | ref arg m2 | map.cpp:275:7:275:8 | m2 | | | map.cpp:269:7:269:8 | ref arg m2 | map.cpp:282:40:282:41 | m2 | | | map.cpp:269:7:269:8 | ref arg m2 | map.cpp:283:42:283:43 | m2 | | @@ -1352,19 +1369,25 @@ | map.cpp:269:7:269:8 | ref arg m2 | map.cpp:332:7:332:8 | m2 | | | map.cpp:269:7:269:8 | ref arg m2 | map.cpp:333:7:333:8 | m2 | | | map.cpp:269:7:269:8 | ref arg m2 | map.cpp:398:1:398:1 | m2 | | +| map.cpp:270:7:270:8 | m3 | map.cpp:270:10:270:13 | call to find | TAINT | | map.cpp:270:7:270:8 | ref arg m3 | map.cpp:276:7:276:8 | m3 | | | map.cpp:270:7:270:8 | ref arg m3 | map.cpp:307:12:307:13 | m3 | | | map.cpp:270:7:270:8 | ref arg m3 | map.cpp:307:30:307:31 | m3 | | | map.cpp:270:7:270:8 | ref arg m3 | map.cpp:398:1:398:1 | m3 | | +| map.cpp:271:7:271:8 | m4 | map.cpp:271:10:271:13 | call to find | TAINT | | map.cpp:271:7:271:8 | ref arg m4 | map.cpp:277:7:277:8 | m4 | | | map.cpp:271:7:271:8 | ref arg m4 | map.cpp:398:1:398:1 | m4 | | +| map.cpp:272:7:272:8 | m5 | map.cpp:272:10:272:13 | call to find | TAINT | | map.cpp:272:7:272:8 | ref arg m5 | map.cpp:278:7:278:8 | m5 | | | map.cpp:272:7:272:8 | ref arg m5 | map.cpp:398:1:398:1 | m5 | | +| map.cpp:273:7:273:8 | m6 | map.cpp:273:10:273:13 | call to find | TAINT | | map.cpp:273:7:273:8 | ref arg m6 | map.cpp:279:7:279:8 | m6 | | | map.cpp:273:7:273:8 | ref arg m6 | map.cpp:398:1:398:1 | m6 | | +| map.cpp:274:7:274:8 | m1 | map.cpp:274:10:274:13 | call to find | TAINT | | map.cpp:274:7:274:8 | ref arg m1 | map.cpp:295:12:295:13 | m1 | | | map.cpp:274:7:274:8 | ref arg m1 | map.cpp:295:30:295:31 | m1 | | | map.cpp:274:7:274:8 | ref arg m1 | map.cpp:398:1:398:1 | m1 | | +| map.cpp:275:7:275:8 | m2 | map.cpp:275:10:275:13 | call to find | TAINT | | map.cpp:275:7:275:8 | ref arg m2 | map.cpp:282:40:282:41 | m2 | | | map.cpp:275:7:275:8 | ref arg m2 | map.cpp:283:42:283:43 | m2 | | | map.cpp:275:7:275:8 | ref arg m2 | map.cpp:285:7:285:8 | m2 | | @@ -1374,11 +1397,15 @@ | map.cpp:275:7:275:8 | ref arg m2 | map.cpp:332:7:332:8 | m2 | | | map.cpp:275:7:275:8 | ref arg m2 | map.cpp:333:7:333:8 | m2 | | | map.cpp:275:7:275:8 | ref arg m2 | map.cpp:398:1:398:1 | m2 | | +| map.cpp:276:7:276:8 | m3 | map.cpp:276:10:276:13 | call to find | TAINT | | map.cpp:276:7:276:8 | ref arg m3 | map.cpp:307:12:307:13 | m3 | | | map.cpp:276:7:276:8 | ref arg m3 | map.cpp:307:30:307:31 | m3 | | | map.cpp:276:7:276:8 | ref arg m3 | map.cpp:398:1:398:1 | m3 | | +| map.cpp:277:7:277:8 | m4 | map.cpp:277:10:277:13 | call to find | TAINT | | map.cpp:277:7:277:8 | ref arg m4 | map.cpp:398:1:398:1 | m4 | | +| map.cpp:278:7:278:8 | m5 | map.cpp:278:10:278:13 | call to find | TAINT | | map.cpp:278:7:278:8 | ref arg m5 | map.cpp:398:1:398:1 | m5 | | +| map.cpp:279:7:279:8 | m6 | map.cpp:279:10:279:13 | call to find | TAINT | | map.cpp:279:7:279:8 | ref arg m6 | map.cpp:398:1:398:1 | m6 | | | map.cpp:282:40:282:41 | m2 | map.cpp:282:40:282:42 | call to unordered_map | | | map.cpp:282:40:282:42 | call to unordered_map | map.cpp:286:7:286:8 | m7 | | @@ -1400,8 +1427,11 @@ | map.cpp:286:7:286:8 | m7 | map.cpp:286:7:286:8 | call to unordered_map | | | map.cpp:287:7:287:8 | m8 | map.cpp:287:7:287:8 | call to unordered_map | | | map.cpp:288:7:288:8 | m9 | map.cpp:288:7:288:8 | call to unordered_map | | +| map.cpp:289:7:289:8 | m7 | map.cpp:289:10:289:13 | call to find | TAINT | | map.cpp:289:7:289:8 | ref arg m7 | map.cpp:398:1:398:1 | m7 | | +| map.cpp:290:7:290:8 | m8 | map.cpp:290:10:290:13 | call to find | TAINT | | map.cpp:290:7:290:8 | ref arg m8 | map.cpp:398:1:398:1 | m8 | | +| map.cpp:291:7:291:8 | m9 | map.cpp:291:10:291:13 | call to find | TAINT | | map.cpp:291:7:291:8 | ref arg m9 | map.cpp:398:1:398:1 | m9 | | | map.cpp:295:12:295:13 | m1 | map.cpp:295:15:295:19 | call to begin | TAINT | | map.cpp:295:12:295:13 | ref arg m1 | map.cpp:295:30:295:31 | m1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp index fc474862fa9..122f2f10336 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp @@ -114,17 +114,17 @@ void test_map() sink(m5); // tainted sink(m6); // tainted sink(m1.find("abc")); - sink(m2.find("abc")); // tainted [NOT DETECTED] - sink(m3.find("abc")); - sink(m4.find("abc")); // tainted [NOT DETECTED] - sink(m5.find("abc")); // tainted [NOT DETECTED] - sink(m6.find("abc")); // tainted [NOT DETECTED] + sink(m2.find("abc")); // tainted + sink(m3.find("abc")); // [FALSE POSITIVE] + sink(m4.find("abc")); // tainted + sink(m5.find("abc")); // tainted + sink(m6.find("abc")); // tainted sink(m1.find("def")); - sink(m2.find("def")); - sink(m3.find("def")); - sink(m4.find("def")); - sink(m5.find("def")); - sink(m6.find("def")); + sink(m2.find("def")); // [FALSE POSITIVE] + sink(m3.find("def")); // [FALSE POSITIVE] + sink(m4.find("def")); // [FALSE POSITIVE] + sink(m5.find("def")); // [FALSE POSITIVE] + sink(m6.find("def")); // [FALSE POSITIVE] // copy constructors and assignment std::map m7(m2); @@ -134,9 +134,9 @@ void test_map() sink(m7); // tainted sink(m8); // tainted sink(m9); // tainted - sink(m7.find("abc")); // tainted [NOT DETECTED] - sink(m8.find("abc")); // tainted [NOT DETECTED] - sink(m9.find("abc")); // tainted [NOT DETECTED] + sink(m7.find("abc")); // tainted + sink(m8.find("abc")); // tainted + sink(m9.find("abc")); // tainted // iterators std::map::iterator i1, i2, i3; @@ -266,17 +266,17 @@ void test_unordered_map() sink(m5); // tainted sink(m6); // tainted sink(m1.find("abc")); - sink(m2.find("abc")); // tainted [NOT DETECTED] - sink(m3.find("abc")); - sink(m4.find("abc")); // tainted [NOT DETECTED] - sink(m5.find("abc")); // tainted [NOT DETECTED] - sink(m6.find("abc")); // tainted [NOT DETECTED] + sink(m2.find("abc")); // tainted + sink(m3.find("abc")); // [FALSE POSITIVE] + sink(m4.find("abc")); // tainted + sink(m5.find("abc")); // tainted + sink(m6.find("abc")); // tainted sink(m1.find("def")); - sink(m2.find("def")); - sink(m3.find("def")); - sink(m4.find("def")); - sink(m5.find("def")); - sink(m6.find("def")); + sink(m2.find("def")); // [FALSE POSITIVE] + sink(m3.find("def")); // [FALSE POSITIVE] + sink(m4.find("def")); // [FALSE POSITIVE] + sink(m5.find("def")); // [FALSE POSITIVE] + sink(m6.find("def")); // [FALSE POSITIVE] // copy constructors and assignment std::unordered_map m7(m2); @@ -286,9 +286,9 @@ void test_unordered_map() sink(m7); // tainted sink(m8); // tainted sink(m9); // tainted - sink(m7.find("abc")); // tainted [NOT DETECTED] - sink(m8.find("abc")); // tainted [NOT DETECTED] - sink(m9.find("abc")); // tainted [NOT DETECTED] + sink(m7.find("abc")); // tainted + sink(m8.find("abc")); // tainted + sink(m9.find("abc")); // tainted // iterators std::unordered_map::iterator i1, i2, i3; 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 1dff0a61f9f..045321e82c5 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -53,9 +53,22 @@ | map.cpp:113:7:113:8 | call to map | map.cpp:107:62:107:67 | call to source | | map.cpp:114:7:114:8 | call to map | map.cpp:108:34:108:39 | call to source | | map.cpp:115:7:115:8 | call to map | map.cpp:109:46:109:51 | call to source | +| map.cpp:117:10:117:13 | call to find | map.cpp:105:39:105:44 | call to source | +| map.cpp:118:10:118:13 | call to find | map.cpp:106:32:106:37 | call to source | +| map.cpp:119:10:119:13 | call to find | map.cpp:107:62:107:67 | call to source | +| map.cpp:120:10:120:13 | call to find | map.cpp:108:34:108:39 | call to source | +| map.cpp:121:10:121:13 | call to find | map.cpp:109:46:109:51 | call to source | +| map.cpp:123:10:123:13 | call to find | map.cpp:105:39:105:44 | call to source | +| map.cpp:124:10:124:13 | call to find | map.cpp:106:32:106:37 | call to source | +| map.cpp:125:10:125:13 | call to find | map.cpp:107:62:107:67 | call to source | +| map.cpp:126:10:126:13 | call to find | map.cpp:108:34:108:39 | call to source | +| map.cpp:127:10:127:13 | call to find | map.cpp:109:46:109:51 | call to source | | map.cpp:134:7:134:8 | call to map | map.cpp:105:39:105:44 | call to source | | map.cpp:135:7:135:8 | call to map | map.cpp:105:39:105:44 | call to source | | map.cpp:136:7:136:8 | call to map | map.cpp:105:39:105:44 | call to source | +| map.cpp:137:10:137:13 | call to find | map.cpp:105:39:105:44 | call to source | +| map.cpp:138:10:138:13 | call to find | map.cpp:105:39:105:44 | call to source | +| map.cpp:139:10:139:13 | call to find | map.cpp:105:39:105:44 | call to source | | map.cpp:151:8:151:10 | call to pair | map.cpp:105:39:105:44 | call to source | | map.cpp:157:8:157:10 | call to pair | map.cpp:106:32:106:37 | call to source | | map.cpp:165:7:165:27 | ... = ... | map.cpp:165:20:165:25 | call to source | @@ -101,9 +114,22 @@ | map.cpp:265:7:265:8 | call to unordered_map | map.cpp:259:62:259:67 | call to source | | map.cpp:266:7:266:8 | call to unordered_map | map.cpp:260:34:260:39 | call to source | | map.cpp:267:7:267:8 | call to unordered_map | map.cpp:261:46:261:51 | call to source | +| map.cpp:269:10:269:13 | call to find | map.cpp:257:39:257:44 | call to source | +| map.cpp:270:10:270:13 | call to find | map.cpp:258:32:258:37 | call to source | +| map.cpp:271:10:271:13 | call to find | map.cpp:259:62:259:67 | call to source | +| map.cpp:272:10:272:13 | call to find | map.cpp:260:34:260:39 | call to source | +| map.cpp:273:10:273:13 | call to find | map.cpp:261:46:261:51 | call to source | +| map.cpp:275:10:275:13 | call to find | map.cpp:257:39:257:44 | call to source | +| map.cpp:276:10:276:13 | call to find | map.cpp:258:32:258:37 | call to source | +| map.cpp:277:10:277:13 | call to find | map.cpp:259:62:259:67 | call to source | +| map.cpp:278:10:278:13 | call to find | map.cpp:260:34:260:39 | call to source | +| map.cpp:279:10:279:13 | call to find | map.cpp:261:46:261:51 | call to source | | map.cpp:286:7:286:8 | call to unordered_map | map.cpp:257:39:257:44 | call to source | | map.cpp:287:7:287:8 | call to unordered_map | map.cpp:257:39:257:44 | call to source | | map.cpp:288:7:288:8 | call to unordered_map | map.cpp:257:39:257:44 | call to source | +| map.cpp:289:10:289:13 | call to find | map.cpp:257:39:257:44 | call to source | +| map.cpp:290:10:290:13 | call to find | map.cpp:257:39:257:44 | call to source | +| map.cpp:291:10:291:13 | call to find | map.cpp:257:39:257:44 | call to source | | map.cpp:303:8:303:10 | call to pair | map.cpp:257:39:257:44 | call to source | | map.cpp:309:8:309:10 | call to pair | map.cpp:258:32:258:37 | call to source | | map.cpp:317:7:317:27 | ... = ... | map.cpp:317:20:317:25 | 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 3886aee6ea7..fb50ba7f29c 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 @@ -50,9 +50,15 @@ | map.cpp:113:7:113:8 | map.cpp:107:62:107:67 | AST only | | map.cpp:114:7:114:8 | map.cpp:108:34:108:39 | AST only | | map.cpp:115:7:115:8 | map.cpp:109:46:109:51 | AST only | +| map.cpp:120:10:120:13 | map.cpp:108:34:108:39 | AST only | +| map.cpp:121:10:121:13 | map.cpp:109:46:109:51 | AST only | +| map.cpp:126:10:126:13 | map.cpp:108:34:108:39 | AST only | +| map.cpp:127:10:127:13 | map.cpp:109:46:109:51 | AST only | | map.cpp:134:7:134:8 | map.cpp:105:39:105:44 | AST only | | map.cpp:135:7:135:8 | map.cpp:105:39:105:44 | AST only | | map.cpp:136:7:136:8 | map.cpp:105:39:105:44 | AST only | +| map.cpp:137:10:137:13 | map.cpp:105:39:105:44 | AST only | +| map.cpp:138:10:138:13 | map.cpp:105:39:105:44 | AST only | | map.cpp:152:12:152:16 | map.cpp:105:39:105:44 | IR only | | map.cpp:153:12:153:17 | map.cpp:105:39:105:44 | IR only | | map.cpp:158:12:158:16 | map.cpp:105:39:105:44 | IR only | @@ -99,9 +105,15 @@ | map.cpp:265:7:265:8 | map.cpp:259:62:259:67 | AST only | | map.cpp:266:7:266:8 | map.cpp:260:34:260:39 | AST only | | map.cpp:267:7:267:8 | map.cpp:261:46:261:51 | AST only | +| map.cpp:272:10:272:13 | map.cpp:260:34:260:39 | AST only | +| map.cpp:273:10:273:13 | map.cpp:261:46:261:51 | AST only | +| map.cpp:278:10:278:13 | map.cpp:260:34:260:39 | AST only | +| map.cpp:279:10:279:13 | map.cpp:261:46:261:51 | AST only | | map.cpp:286:7:286:8 | map.cpp:257:39:257:44 | AST only | | map.cpp:287:7:287:8 | map.cpp:257:39:257:44 | AST only | | map.cpp:288:7:288:8 | map.cpp:257:39:257:44 | AST only | +| map.cpp:289:10:289:13 | map.cpp:257:39:257:44 | AST only | +| map.cpp:290:10:290:13 | map.cpp:257:39:257:44 | AST only | | map.cpp:304:12:304:16 | map.cpp:257:39:257:44 | IR only | | map.cpp:305:12:305:17 | map.cpp:257:39:257:44 | IR only | | map.cpp:310:12:310:16 | map.cpp:257:39:257:44 | IR 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 41803ad3039..6ffcf3628e3 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 @@ -83,6 +83,13 @@ | map.cpp:107:10:107:15 | call to insert | map.cpp:107:62:107:67 | call to source | | map.cpp:108:7:108:48 | call to iterator | map.cpp:108:34:108:39 | call to source | | map.cpp:109:10:109:25 | call to insert_or_assign | map.cpp:109:46:109:51 | call to source | +| map.cpp:117:10:117:13 | call to find | map.cpp:105:39:105:44 | call to source | +| map.cpp:118:10:118:13 | call to find | map.cpp:106:32:106:37 | call to source | +| map.cpp:119:10:119:13 | call to find | map.cpp:107:62:107:67 | call to source | +| map.cpp:123:10:123:13 | call to find | map.cpp:105:39:105:44 | call to source | +| map.cpp:124:10:124:13 | call to find | map.cpp:106:32:106:37 | call to source | +| map.cpp:125:10:125:13 | call to find | map.cpp:107:62:107:67 | call to source | +| map.cpp:139:10:139:13 | call to find | map.cpp:105:39:105:44 | call to source | | map.cpp:151:8:151:10 | call to pair | map.cpp:105:39:105:44 | call to source | | map.cpp:152:12:152:16 | first | map.cpp:105:39:105:44 | call to source | | map.cpp:153:12:153:17 | second | map.cpp:105:39:105:44 | call to source | @@ -96,6 +103,13 @@ | map.cpp:259:10:259:15 | call to insert | map.cpp:259:62:259:67 | call to source | | map.cpp:260:7:260:48 | call to iterator | map.cpp:260:34:260:39 | call to source | | map.cpp:261:10:261:25 | call to insert_or_assign | map.cpp:261:46:261:51 | call to source | +| map.cpp:269:10:269:13 | call to find | map.cpp:257:39:257:44 | call to source | +| map.cpp:270:10:270:13 | call to find | map.cpp:258:32:258:37 | call to source | +| map.cpp:271:10:271:13 | call to find | map.cpp:259:62:259:67 | call to source | +| map.cpp:275:10:275:13 | call to find | map.cpp:257:39:257:44 | call to source | +| map.cpp:276:10:276:13 | call to find | map.cpp:258:32:258:37 | call to source | +| map.cpp:277:10:277:13 | call to find | map.cpp:259:62:259:67 | call to source | +| map.cpp:291:10:291:13 | call to find | map.cpp:257:39:257:44 | call to source | | map.cpp:303:8:303:10 | call to pair | map.cpp:257:39:257:44 | call to source | | map.cpp:304:12:304:16 | first | map.cpp:257:39:257:44 | call to source | | map.cpp:305:12:305:17 | second | map.cpp:257:39:257:44 | call to source | From ec3c1568d2b0717f400d7e1505a70bdb372cef25 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 24 Sep 2020 18:21:47 +0100 Subject: [PATCH 054/411] C++: Model erase. --- .../code/cpp/models/implementations/StdMap.qll | 16 ++++++++++++++++ .../dataflow/taint-tests/localTaint.expected | 2 ++ .../library-tests/dataflow/taint-tests/map.cpp | 4 ++-- .../dataflow/taint-tests/taint.expected | 8 ++++++++ .../dataflow/taint-tests/test_ir.expected | 8 ++++++++ 5 files changed, 36 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll index 098da1ec8da..adf74973b50 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll @@ -87,3 +87,19 @@ class StdMapFind extends TaintFunction { output.isReturnValue() } } + +/** + * The standard map `erase` function. + */ +class StdMapErase extends TaintFunction { + StdMapErase() { + this.hasQualifiedName("std", ["map", "unordered_map"], "erase") + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from qualifier to iterator return value + getType().getUnderlyingType() instanceof Iterator and + input.isQualifierObject() and + output.isReturnValue() + } +} 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 d0d4f6462f9..ca68373079b 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -1123,6 +1123,7 @@ | map.cpp:221:39:221:44 | call to source | map.cpp:221:13:221:57 | call to pair | TAINT | | map.cpp:221:49:221:54 | call to source | map.cpp:221:13:221:57 | call to pair | TAINT | | map.cpp:222:7:222:9 | m23 | map.cpp:222:7:222:9 | call to map | | +| map.cpp:223:7:223:9 | m23 | map.cpp:223:11:223:15 | call to erase | TAINT | | map.cpp:223:7:223:9 | ref arg m23 | map.cpp:224:7:224:9 | m23 | | | map.cpp:223:7:223:9 | ref arg m23 | map.cpp:225:2:225:4 | m23 | | | map.cpp:223:7:223:9 | ref arg m23 | map.cpp:226:7:226:9 | m23 | | @@ -1754,6 +1755,7 @@ | map.cpp:370:39:370:44 | call to source | map.cpp:370:13:370:57 | call to pair | TAINT | | map.cpp:370:49:370:54 | call to source | map.cpp:370:13:370:57 | call to pair | TAINT | | map.cpp:371:7:371:9 | m23 | map.cpp:371:7:371:9 | call to unordered_map | | +| map.cpp:372:7:372:9 | m23 | map.cpp:372:11:372:15 | call to erase | TAINT | | map.cpp:372:7:372:9 | ref arg m23 | map.cpp:373:7:373:9 | m23 | | | map.cpp:372:7:372:9 | ref arg m23 | map.cpp:374:2:374:4 | m23 | | | map.cpp:372:7:372:9 | ref arg m23 | map.cpp:375:7:375:9 | m23 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp index 122f2f10336..eb022736918 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp @@ -220,7 +220,7 @@ void test_map() m23.insert(std::pair(source(), source())); m23.insert(std::pair(source(), source())); sink(m23); // tainted - sink(m23.erase(m23.begin())); // tainted [NOT DETECTED] + sink(m23.erase(m23.begin())); // tainted sink(m23); // tainted m23.clear(); sink(m23); // [FALSE POSITIVE] @@ -369,7 +369,7 @@ void test_unordered_map() m23.insert(std::pair(source(), source())); m23.insert(std::pair(source(), source())); sink(m23); // tainted - sink(m23.erase(m23.begin())); // tainted [NOT DETECTED] + sink(m23.erase(m23.begin())); // tainted sink(m23); // tainted m23.clear(); sink(m23); // [FALSE POSITIVE] 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 045321e82c5..ca407a2fd15 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -99,6 +99,10 @@ | map.cpp:222:7:222:9 | call to map | map.cpp:220:49:220:54 | call to source | | map.cpp:222:7:222:9 | call to map | map.cpp:221:39:221:44 | call to source | | map.cpp:222:7:222:9 | call to map | map.cpp:221:49:221:54 | call to source | +| map.cpp:223:11:223:15 | call to erase | map.cpp:220:39:220:44 | call to source | +| map.cpp:223:11:223:15 | call to erase | map.cpp:220:49:220:54 | call to source | +| map.cpp:223:11:223:15 | call to erase | map.cpp:221:39:221:44 | call to source | +| map.cpp:223:11:223:15 | call to erase | map.cpp:221:49:221:54 | call to source | | map.cpp:224:7:224:9 | call to map | map.cpp:220:39:220:44 | call to source | | map.cpp:224:7:224:9 | call to map | map.cpp:220:49:220:54 | call to source | | map.cpp:224:7:224:9 | call to map | map.cpp:221:39:221:44 | call to source | @@ -160,6 +164,10 @@ | map.cpp:371:7:371:9 | call to unordered_map | map.cpp:369:49:369:54 | call to source | | map.cpp:371:7:371:9 | call to unordered_map | map.cpp:370:39:370:44 | call to source | | map.cpp:371:7:371:9 | call to unordered_map | map.cpp:370:49:370:54 | call to source | +| map.cpp:372:11:372:15 | call to erase | map.cpp:369:39:369:44 | call to source | +| map.cpp:372:11:372:15 | call to erase | map.cpp:369:49:369:54 | call to source | +| map.cpp:372:11:372:15 | call to erase | map.cpp:370:39:370:44 | call to source | +| map.cpp:372:11:372:15 | call to erase | map.cpp:370:49:370:54 | call to source | | map.cpp:373:7:373:9 | call to unordered_map | map.cpp:369:39:369:44 | call to source | | map.cpp:373:7:373:9 | call to unordered_map | map.cpp:369:49:369:54 | call to source | | map.cpp:373:7:373:9 | call to unordered_map | map.cpp:370:39:370:44 | 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 6ffcf3628e3..3536273a806 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 @@ -98,6 +98,10 @@ | map.cpp:159:12:159:17 | second | map.cpp:105:39:105:44 | call to source | | map.cpp:165:7:165:27 | ... = ... | map.cpp:165:20:165:25 | call to source | | map.cpp:167:7:167:30 | ... = ... | map.cpp:167:23:167:28 | call to source | +| map.cpp:223:11:223:15 | call to erase | map.cpp:220:39:220:44 | call to source | +| map.cpp:223:11:223:15 | call to erase | map.cpp:220:49:220:54 | call to source | +| map.cpp:223:11:223:15 | call to erase | map.cpp:221:39:221:44 | call to source | +| map.cpp:223:11:223:15 | call to erase | map.cpp:221:49:221:54 | call to source | | map.cpp:257:7:257:54 | call to iterator | map.cpp:257:39:257:44 | call to source | | map.cpp:258:7:258:54 | call to iterator | map.cpp:258:32:258:37 | call to source | | map.cpp:259:10:259:15 | call to insert | map.cpp:259:62:259:67 | call to source | @@ -118,6 +122,10 @@ | map.cpp:311:12:311:17 | second | map.cpp:257:39:257:44 | call to source | | map.cpp:317:7:317:27 | ... = ... | map.cpp:317:20:317:25 | call to source | | map.cpp:319:7:319:30 | ... = ... | map.cpp:319:23:319:28 | call to source | +| map.cpp:372:11:372:15 | call to erase | map.cpp:369:39:369:44 | call to source | +| map.cpp:372:11:372:15 | call to erase | map.cpp:369:49:369:54 | call to source | +| map.cpp:372:11:372:15 | call to erase | map.cpp:370:39:370:44 | call to source | +| map.cpp:372:11:372:15 | call to erase | map.cpp:370:49:370:54 | call to source | | movableclass.cpp:44:8:44:9 | s1 | movableclass.cpp:39:21:39:26 | call to source | | movableclass.cpp:45:8:45:9 | s2 | movableclass.cpp:40:23:40:28 | call to source | | movableclass.cpp:46:8:46:9 | s3 | movableclass.cpp:42:8:42:13 | call to source | From ca06637de0d4adaeb27286e8385ad42073dcec4f Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 24 Sep 2020 10:40:45 -0700 Subject: [PATCH 055/411] C++: add qldoc comment --- .../semmle/code/cpp/dataflow/internal/DataFlowUtil.qll | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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 25a37f9db0f..9bbedfc16a8 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -182,6 +182,13 @@ class ImplicitParameterNode extends ParameterNode, TInstanceParameterNode { override predicate isParameterOf(Function fun, int i) { f = fun and i = -1 } } +/** + * INTERNAL: do not use. + * + * A node that represents the value of a variable after a function call that + * may have changed the variable because it's passed by reference or because an + * iterator for it was passed by value or by reference. + */ class DefinitionByReferenceOrIteratorNode extends PartialDefinitionNode { Expr inner; Expr argument; @@ -215,7 +222,6 @@ class DefinitionByReferenceOrIteratorNode extends PartialDefinitionNode { } } - /** * A node that represents the value of a variable after a function call that * may have changed the variable because it's passed by reference. From b8154d41b17995c0248dcbafee307c93356c67d7 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 24 Sep 2020 20:55:25 +0200 Subject: [PATCH 056/411] type-track objects where the "$where" property has been written --- .../ql/src/semmle/javascript/frameworks/NoSQL.qll | 14 +++++++++++++- .../CWE-094/CodeInjection/CodeInjection.expected | 10 ++++++++++ .../HeuristicSourceCodeInjection.expected | 9 +++++++++ .../CWE-094/CodeInjection/NoSQLCodeInjection.js | 6 ++++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll index 13385057b5d..2854cdaa8f4 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll @@ -12,11 +12,23 @@ module NoSQL { } } +/** + * Gets a reference to an object where the "$where" property has been assigned to`rhs`. + */ +DataFlow::SourceNode getADollarWherePropertyValueSource(DataFlow::TypeTracker t, DataFlow::Node rhs) { + t.start() and + rhs = result.getAPropertyWrite("$where").getRhs() + or + exists(DataFlow::TypeTracker t2 | + result = getADollarWherePropertyValueSource(t2, rhs).track(t2, t) + ) +} + /** * Gets the value of a `$where` property of an object that flows to `n`. */ private DataFlow::Node getADollarWherePropertyValue(DataFlow::Node n) { - result = n.getALocalSource().getAPropertyWrite("$where").getRhs() + getADollarWherePropertyValueSource(DataFlow::TypeTracker::end(), result).flowsTo(n) } /** diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected index 5b23332d205..dec023d72f3 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected @@ -8,6 +8,11 @@ nodes | NoSQLCodeInjection.js:19:36:19:43 | req.body | | NoSQLCodeInjection.js:19:36:19:43 | req.body | | NoSQLCodeInjection.js:19:36:19:48 | req.body.name | +| NoSQLCodeInjection.js:22:24:22:48 | "name = ... dy.name | +| NoSQLCodeInjection.js:22:24:22:48 | "name = ... dy.name | +| NoSQLCodeInjection.js:22:36:22:43 | req.body | +| NoSQLCodeInjection.js:22:36:22:43 | req.body | +| NoSQLCodeInjection.js:22:36:22:48 | req.body.name | | angularjs.js:10:22:10:29 | location | | angularjs.js:10:22:10:29 | location | | angularjs.js:10:22:10:36 | location.search | @@ -152,6 +157,10 @@ edges | NoSQLCodeInjection.js:19:36:19:43 | req.body | NoSQLCodeInjection.js:19:36:19:48 | req.body.name | | NoSQLCodeInjection.js:19:36:19:48 | req.body.name | NoSQLCodeInjection.js:19:24:19:48 | "name = ... dy.name | | NoSQLCodeInjection.js:19:36:19:48 | req.body.name | NoSQLCodeInjection.js:19:24:19:48 | "name = ... dy.name | +| NoSQLCodeInjection.js:22:36:22:43 | req.body | NoSQLCodeInjection.js:22:36:22:48 | req.body.name | +| NoSQLCodeInjection.js:22:36:22:43 | req.body | NoSQLCodeInjection.js:22:36:22:48 | req.body.name | +| NoSQLCodeInjection.js:22:36:22:48 | req.body.name | NoSQLCodeInjection.js:22:24:22:48 | "name = ... dy.name | +| NoSQLCodeInjection.js:22:36:22:48 | req.body.name | NoSQLCodeInjection.js:22:24:22:48 | "name = ... dy.name | | angularjs.js:10:22:10:29 | location | angularjs.js:10:22:10:36 | location.search | | angularjs.js:10:22:10:29 | location | angularjs.js:10:22:10:36 | location.search | | angularjs.js:10:22:10:29 | location | angularjs.js:10:22:10:36 | location.search | @@ -275,6 +284,7 @@ edges #select | NoSQLCodeInjection.js:18:24:18:37 | req.body.query | NoSQLCodeInjection.js:18:24:18:31 | req.body | NoSQLCodeInjection.js:18:24:18:37 | req.body.query | $@ flows to here and is interpreted as code. | NoSQLCodeInjection.js:18:24:18:31 | req.body | User-provided value | | NoSQLCodeInjection.js:19:24:19:48 | "name = ... dy.name | NoSQLCodeInjection.js:19:36:19:43 | req.body | NoSQLCodeInjection.js:19:24:19:48 | "name = ... dy.name | $@ flows to here and is interpreted as code. | NoSQLCodeInjection.js:19:36:19:43 | req.body | User-provided value | +| NoSQLCodeInjection.js:22:24:22:48 | "name = ... dy.name | NoSQLCodeInjection.js:22:36:22:43 | req.body | NoSQLCodeInjection.js:22:24:22:48 | "name = ... dy.name | $@ flows to here and is interpreted as code. | NoSQLCodeInjection.js:22:36:22:43 | req.body | User-provided value | | angularjs.js:10:22:10:36 | location.search | angularjs.js:10:22:10:29 | location | angularjs.js:10:22:10:36 | location.search | $@ flows to here and is interpreted as code. | angularjs.js:10:22:10:29 | location | User-provided value | | angularjs.js:13:23:13:37 | location.search | angularjs.js:13:23:13:30 | location | angularjs.js:13:23:13:37 | location.search | $@ flows to here and is interpreted as code. | angularjs.js:13:23:13:30 | location | User-provided value | | angularjs.js:16:28:16:42 | location.search | angularjs.js:16:28:16:35 | location | angularjs.js:16:28:16:42 | location.search | $@ flows to here and is interpreted as code. | angularjs.js:16:28:16:35 | location | User-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected index 50bf4e455a2..fa34f829b92 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected @@ -8,6 +8,11 @@ nodes | NoSQLCodeInjection.js:19:36:19:43 | req.body | | NoSQLCodeInjection.js:19:36:19:43 | req.body | | NoSQLCodeInjection.js:19:36:19:48 | req.body.name | +| NoSQLCodeInjection.js:22:24:22:48 | "name = ... dy.name | +| NoSQLCodeInjection.js:22:24:22:48 | "name = ... dy.name | +| NoSQLCodeInjection.js:22:36:22:43 | req.body | +| NoSQLCodeInjection.js:22:36:22:43 | req.body | +| NoSQLCodeInjection.js:22:36:22:48 | req.body.name | | angularjs.js:10:22:10:29 | location | | angularjs.js:10:22:10:29 | location | | angularjs.js:10:22:10:36 | location.search | @@ -156,6 +161,10 @@ edges | NoSQLCodeInjection.js:19:36:19:43 | req.body | NoSQLCodeInjection.js:19:36:19:48 | req.body.name | | NoSQLCodeInjection.js:19:36:19:48 | req.body.name | NoSQLCodeInjection.js:19:24:19:48 | "name = ... dy.name | | NoSQLCodeInjection.js:19:36:19:48 | req.body.name | NoSQLCodeInjection.js:19:24:19:48 | "name = ... dy.name | +| NoSQLCodeInjection.js:22:36:22:43 | req.body | NoSQLCodeInjection.js:22:36:22:48 | req.body.name | +| NoSQLCodeInjection.js:22:36:22:43 | req.body | NoSQLCodeInjection.js:22:36:22:48 | req.body.name | +| NoSQLCodeInjection.js:22:36:22:48 | req.body.name | NoSQLCodeInjection.js:22:24:22:48 | "name = ... dy.name | +| NoSQLCodeInjection.js:22:36:22:48 | req.body.name | NoSQLCodeInjection.js:22:24:22:48 | "name = ... dy.name | | angularjs.js:10:22:10:29 | location | angularjs.js:10:22:10:36 | location.search | | angularjs.js:10:22:10:29 | location | angularjs.js:10:22:10:36 | location.search | | angularjs.js:10:22:10:29 | location | angularjs.js:10:22:10:36 | location.search | diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/NoSQLCodeInjection.js b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/NoSQLCodeInjection.js index 3e7025a8e6c..6facf5ec75a 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/NoSQLCodeInjection.js +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/NoSQLCodeInjection.js @@ -17,5 +17,11 @@ app.post("/documents/find", (req, res) => { doc.find(query); // NOT OK, but that is flagged by js/sql-injection [INCONSISTENCY] doc.find({ $where: req.body.query }); // NOT OK doc.find({ $where: "name = " + req.body.name }); // NOT OK + + function mkWhereObj() { + return { $where: "name = " + req.body.name }; // NOT OK + } + + doc.find(mkWhereObj()); // the alert location is in mkWhereObj. }); }); From 46ff4d524fe3ff18b76a006e099fab12072a903e Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 24 Sep 2020 14:54:31 -0700 Subject: [PATCH 057/411] C++: autoformat --- cpp/ql/src/semmle/code/cpp/models/interfaces/Iterator.qll | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/Iterator.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/Iterator.qll index 1086e088979..de697776525 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/Iterator.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/Iterator.qll @@ -14,5 +14,4 @@ import semmle.code.cpp.models.Models * A function which takes an iterator argument and returns a reference that * can be used to write to the iterator's underlying collection. */ -abstract class IteratorReferenceFunction extends Function { -} +abstract class IteratorReferenceFunction extends Function { } From e9b1d817c757ee96747cdbba3c935e05a7a9bf92 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 24 Sep 2020 15:55:57 -0700 Subject: [PATCH 058/411] C++: QLDoc for VirtualVariable in IR construction --- .../ir/implementation/aliased_ssa/internal/AliasedSSA.qll | 6 ++++++ .../ir/implementation/unaliased_ssa/internal/SimpleSSA.qll | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll index 8124fa438d4..1e034051f05 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll @@ -133,6 +133,12 @@ abstract class MemoryLocation extends TMemoryLocation { predicate isAlwaysAllocatedOnStack() { none() } } +/** + * Represents a set of `MemoryLocation`s that cannot overlap with + * `MemoryLocation`s outside of the set. The `VirtualVariable` will be + * represented by a `MemoryLocation` that totally overlaps all other + * `MemoryLocations` in the set. + */ abstract class VirtualVariable extends MemoryLocation { } abstract class AllocationMemoryLocation extends MemoryLocation { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll index 3de8f5259f8..a7b9160bdc7 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll @@ -59,6 +59,12 @@ class MemoryLocation extends TMemoryLocation { final string getUniqueId() { result = var.getUniqueId() } } +/** + * Represents a set of `MemoryLocation`s that cannot overlap with + * `MemoryLocation`s outside of the set. The `VirtualVariable` will be + * represented by a `MemoryLocation` that totally overlaps all other + * `MemoryLocations` in the set. + */ class VirtualVariable extends MemoryLocation { } /** A virtual variable that groups all escaped memory within a function. */ From e51b9215e4b3c391d7227ca163b298baa316fec6 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 24 Sep 2020 15:56:29 -0700 Subject: [PATCH 059/411] C++: QLDoc for Overlap in IR construction --- .../src/semmle/code/cpp/ir/internal/Overlap.qll | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/Overlap.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/Overlap.qll index 8ce0549b2b4..f9a0c574f8c 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/Overlap.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/Overlap.qll @@ -3,18 +3,33 @@ private newtype TOverlap = TMustTotallyOverlap() or TMustExactlyOverlap() +/** + * Represents a possible overlap between two memory ranges. + */ abstract class Overlap extends TOverlap { abstract string toString(); } +/** + * Represents a partial overlap between two memory ranges, which may or may not + * actually occur in practice. + */ class MayPartiallyOverlap extends Overlap, TMayPartiallyOverlap { final override string toString() { result = "MayPartiallyOverlap" } } +/** + * Represents an overlap in which the first memory range is known to include all + * bits of the second memory range, but may be larger or have a different type. + */ class MustTotallyOverlap extends Overlap, TMustTotallyOverlap { final override string toString() { result = "MustTotallyOverlap" } } +/** + * Represents an overlap between two memory ranges that have the same extent and + * the same type. + */ class MustExactlyOverlap extends Overlap, TMustExactlyOverlap { final override string toString() { result = "MustExactlyOverlap" } } From 1445b3186464a33e04d67b1e1bb019f790f901d7 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 24 Sep 2020 16:34:16 -0700 Subject: [PATCH 060/411] C++: QLDoc for Operand --- .../code/cpp/ir/implementation/unaliased_ssa/Operand.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll index 14f62da51cd..e476aec60af 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll @@ -79,7 +79,8 @@ private PhiOperandBase phiOperand( } /** - * A source operand of an `Instruction`. The operand represents a value consumed by the instruction. + * An operand of an `Instruction`. The operand represents a use of the result of one instruction + * (the defining instruction) in another instruction (the use instruction) */ class Operand extends TOperand { /** Gets a textual representation of this element. */ From ba0a2e16657d43fb26a55b39d408208f219b5adb Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen Date: Fri, 25 Sep 2020 10:28:05 +0200 Subject: [PATCH 061/411] JS: tag consistency: replace cwe-20 with cwe-020 --- javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql | 2 +- .../src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql | 2 +- javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.ql | 2 +- .../ql/src/Security/CWE-020/UselessRegExpCharacterEscape.ql | 2 +- javascript/ql/src/Security/CWE-116/DoubleEscaping.ql | 2 +- .../src/Security/CWE-116/IncompleteHtmlAttributeSanitization.ql | 2 +- .../Security/CWE-116/IncompleteMultiCharacterSanitization.ql | 2 +- javascript/ql/src/Security/CWE-116/IncompleteSanitization.ql | 2 +- .../experimental/Security/CWE-020/PostMessageNoOriginCheck.ql | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql b/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql index 7cdef3c983b..68b0200ebed 100644 --- a/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql +++ b/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql @@ -7,7 +7,7 @@ * @id js/incomplete-hostname-regexp * @tags correctness * security - * external/cwe/cwe-20 + * external/cwe/cwe-020 */ import javascript diff --git a/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql b/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql index 09aad31c96d..554cf7759d2 100644 --- a/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql +++ b/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql @@ -7,7 +7,7 @@ * @id js/incomplete-url-substring-sanitization * @tags correctness * security - * external/cwe/cwe-20 + * external/cwe/cwe-020 */ import javascript diff --git a/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.ql b/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.ql index 972ca02ceb9..916edfb4f02 100644 --- a/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.ql +++ b/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.ql @@ -7,7 +7,7 @@ * @id js/regex/missing-regexp-anchor * @tags correctness * security - * external/cwe/cwe-20 + * external/cwe/cwe-020 */ import javascript diff --git a/javascript/ql/src/Security/CWE-020/UselessRegExpCharacterEscape.ql b/javascript/ql/src/Security/CWE-020/UselessRegExpCharacterEscape.ql index 062c0c2999c..7c3365a0434 100644 --- a/javascript/ql/src/Security/CWE-020/UselessRegExpCharacterEscape.ql +++ b/javascript/ql/src/Security/CWE-020/UselessRegExpCharacterEscape.ql @@ -9,7 +9,7 @@ * @id js/useless-regexp-character-escape * @tags correctness * security - * external/cwe/cwe-20 + * external/cwe/cwe-020 */ import javascript diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index cc1bb1290e5..7e79b21c7fd 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -10,7 +10,7 @@ * @tags correctness * security * external/cwe/cwe-116 - * external/cwe/cwe-20 + * external/cwe/cwe-020 */ import javascript diff --git a/javascript/ql/src/Security/CWE-116/IncompleteHtmlAttributeSanitization.ql b/javascript/ql/src/Security/CWE-116/IncompleteHtmlAttributeSanitization.ql index 1788f81bfc2..7e3688a9386 100644 --- a/javascript/ql/src/Security/CWE-116/IncompleteHtmlAttributeSanitization.ql +++ b/javascript/ql/src/Security/CWE-116/IncompleteHtmlAttributeSanitization.ql @@ -10,7 +10,7 @@ * @tags security * external/cwe/cwe-079 * external/cwe/cwe-116 - * external/cwe/cwe-20 + * external/cwe/cwe-020 */ import javascript diff --git a/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql b/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql index 9987bb3686f..d478c32fc15 100644 --- a/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql +++ b/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql @@ -8,7 +8,7 @@ * @tags correctness * security * external/cwe/cwe-116 - * external/cwe/cwe-20 + * external/cwe/cwe-020 */ import javascript diff --git a/javascript/ql/src/Security/CWE-116/IncompleteSanitization.ql b/javascript/ql/src/Security/CWE-116/IncompleteSanitization.ql index 9494dcde0e5..612f7a4f97d 100644 --- a/javascript/ql/src/Security/CWE-116/IncompleteSanitization.ql +++ b/javascript/ql/src/Security/CWE-116/IncompleteSanitization.ql @@ -9,7 +9,7 @@ * @tags correctness * security * external/cwe/cwe-116 - * external/cwe/cwe-20 + * external/cwe/cwe-020 */ import javascript diff --git a/javascript/ql/src/experimental/Security/CWE-020/PostMessageNoOriginCheck.ql b/javascript/ql/src/experimental/Security/CWE-020/PostMessageNoOriginCheck.ql index 2dcfd09c72f..ce2a11e3910 100644 --- a/javascript/ql/src/experimental/Security/CWE-020/PostMessageNoOriginCheck.ql +++ b/javascript/ql/src/experimental/Security/CWE-020/PostMessageNoOriginCheck.ql @@ -8,7 +8,7 @@ * @id js/missing-postmessageorigin-verification * @tags correctness * security - * external/cwe/cwe-20 + * external/cwe/cwe-020 */ import javascript From 6fd1bf89c1197d7a5316eb82d963c846afed04b4 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 25 Sep 2020 09:55:08 +0100 Subject: [PATCH 062/411] C++: Change note. --- change-notes/1.26/analysis-cpp.md | 1 + 1 file changed, 1 insertion(+) diff --git a/change-notes/1.26/analysis-cpp.md b/change-notes/1.26/analysis-cpp.md index 66386bbce5d..98e92886909 100644 --- a/change-notes/1.26/analysis-cpp.md +++ b/change-notes/1.26/analysis-cpp.md @@ -25,5 +25,6 @@ The following changes in version 1.26 affect C/C++ analysis in all applications. * The models library now models many more taint flows through `std::string`. * The models library now models many taint flows through `std::istream` and `std::ostream`. * The models library now models some taint flows through `std::shared_ptr`, `std::unique_ptr`, `std::make_shared` and `std::make_unique`. +* The models library now models some taint flows through `std::pair`, `std::map` and `std::unordered_map`. * The `SimpleRangeAnalysis` library now supports multiplications of the form `e1 * e2` and `x *= e2` when `e1` and `e2` are unsigned or constant. From 09b5fb675398e4fca24a2c55d9e2670fc55e4f69 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 25 Sep 2020 10:41:25 +0100 Subject: [PATCH 063/411] C++: Fix comments. --- .../src/semmle/code/cpp/models/implementations/StdPair.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll index f092b8bac2e..b317713812b 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll @@ -11,8 +11,8 @@ class StdPairConstructor extends Constructor, TaintFunction { StdPairConstructor() { this.getDeclaringType().hasQualifiedName("std", "pair") } /** - * Gets the index of a parameter to this function that is a reference to the - * value type of the container. + * Gets the index of a parameter to this function that is a reference to + * either value type of the pair. */ int getAValueTypeParameterIndex() { getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() = @@ -20,7 +20,7 @@ class StdPairConstructor extends Constructor, TaintFunction { } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // taint flow from any parameter of the value type to the returned object + // taint flow from any parameter of a value type to the qualifier input.isParameterDeref(getAValueTypeParameterIndex()) and ( output.isReturnValue() // TODO: this is only needed for AST data flow, which treats constructors as returning the new object From 120a569c6f1dec110b3434b259a54384502e9918 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 25 Sep 2020 11:40:49 +0200 Subject: [PATCH 064/411] Python: Explain how CallGraph test.py even works Also remove options file, since it did nothing at all (and blocked experimental/library-tests/options from taking effect) --- python/ql/test/experimental/library-tests/CallGraph/options | 1 - python/ql/test/experimental/library-tests/CallGraph/test.py | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) delete mode 100644 python/ql/test/experimental/library-tests/CallGraph/options diff --git a/python/ql/test/experimental/library-tests/CallGraph/options b/python/ql/test/experimental/library-tests/CallGraph/options deleted file mode 100644 index 86f027c42dd..00000000000 --- a/python/ql/test/experimental/library-tests/CallGraph/options +++ /dev/null @@ -1 +0,0 @@ -semmle-extractor-options: diff --git a/python/ql/test/experimental/library-tests/CallGraph/test.py b/python/ql/test/experimental/library-tests/CallGraph/test.py index 04176e98a74..87c585c5cf8 100644 --- a/python/ql/test/experimental/library-tests/CallGraph/test.py +++ b/python/ql/test/experimental/library-tests/CallGraph/test.py @@ -1 +1,3 @@ +# This import will only import code/__init__.py -- BUT we still analyse the other python +# files inside code/ which is what we want. from code import * From 3d5511221e3fdeb53d4a91d6eb3d133d25190649 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 25 Sep 2020 11:44:54 +0200 Subject: [PATCH 065/411] Python: Add test for implicit __init__.py files --- .../CallGraph-implicit-init/PointsTo.expected | 6 ++++++ .../CallGraph-implicit-init/PointsTo.qlref | 1 + .../CallGraph-implicit-init/Relative.expected | 5 +++++ .../CallGraph-implicit-init/Relative.qlref | 1 + .../TypeTracker.expected | 6 ++++++ .../CallGraph-implicit-init/TypeTracker.qlref | 1 + .../CallGraph-implicit-init/example.py | 18 ++++++++++++++++++ .../CallGraph-implicit-init/foo/bar/a.py | 4 ++++ .../CallGraph-implicit-init/options | 1 + 9 files changed, 43 insertions(+) create mode 100644 python/ql/test/experimental/library-tests/CallGraph-implicit-init/PointsTo.expected create mode 100644 python/ql/test/experimental/library-tests/CallGraph-implicit-init/PointsTo.qlref create mode 100644 python/ql/test/experimental/library-tests/CallGraph-implicit-init/Relative.expected create mode 100644 python/ql/test/experimental/library-tests/CallGraph-implicit-init/Relative.qlref create mode 100644 python/ql/test/experimental/library-tests/CallGraph-implicit-init/TypeTracker.expected create mode 100644 python/ql/test/experimental/library-tests/CallGraph-implicit-init/TypeTracker.qlref create mode 100644 python/ql/test/experimental/library-tests/CallGraph-implicit-init/example.py create mode 100644 python/ql/test/experimental/library-tests/CallGraph-implicit-init/foo/bar/a.py create mode 100644 python/ql/test/experimental/library-tests/CallGraph-implicit-init/options diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/PointsTo.expected b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/PointsTo.expected new file mode 100644 index 00000000000..e1f0f883631 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/PointsTo.expected @@ -0,0 +1,6 @@ +debug_missingAnnotationForCallable +debug_nonUniqueAnnotationForCallable +debug_missingAnnotationForCall +expectedCallEdgeNotFound +| example.py:12:1:12:7 | afunc() | foo/bar/a.py:2:1:2:12 | Function afunc | +unexpectedCallEdgeFound diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/PointsTo.qlref b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/PointsTo.qlref new file mode 100644 index 00000000000..da8a0d1631a --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/PointsTo.qlref @@ -0,0 +1 @@ +../CallGraph/PointsTo.ql diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/Relative.expected b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/Relative.expected new file mode 100644 index 00000000000..c25b2538ffa --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/Relative.expected @@ -0,0 +1,5 @@ +debug_missingAnnotationForCallable +debug_nonUniqueAnnotationForCallable +debug_missingAnnotationForCall +pointsTo_found_typeTracker_notFound +pointsTo_notFound_typeTracker_found diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/Relative.qlref b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/Relative.qlref new file mode 100644 index 00000000000..2ffa6c10d51 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/Relative.qlref @@ -0,0 +1 @@ +../CallGraph/Relative.ql diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/TypeTracker.expected b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/TypeTracker.expected new file mode 100644 index 00000000000..e1f0f883631 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/TypeTracker.expected @@ -0,0 +1,6 @@ +debug_missingAnnotationForCallable +debug_nonUniqueAnnotationForCallable +debug_missingAnnotationForCall +expectedCallEdgeNotFound +| example.py:12:1:12:7 | afunc() | foo/bar/a.py:2:1:2:12 | Function afunc | +unexpectedCallEdgeFound diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/TypeTracker.qlref b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/TypeTracker.qlref new file mode 100644 index 00000000000..60c029a5510 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/TypeTracker.qlref @@ -0,0 +1 @@ +../CallGraph/TypeTracker.ql diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/example.py b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/example.py new file mode 100644 index 00000000000..67bbf5c707c --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/example.py @@ -0,0 +1,18 @@ +""" +Test that we can resolve callables correctly without using explicit __init__.py files + +This is not included in the standard `CallGraph/code` folder, since we're testing our +understanding import work properly, so it's better to have a clean test setup that is +obviously correct (the other one isn't in regards to imports). + +Technically this is part of PEP 420 -- Implicit Namespace Packages, but does use the +*real* namespace package feature of allowing source code for a single package to reside +in multiple places. + +Since PEP 420 was accepted in Python 3, this test is Python 3 only. +""" + +from foo.bar.a import afunc + +# calls:afunc +afunc() diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/foo/bar/a.py b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/foo/bar/a.py new file mode 100644 index 00000000000..a294b33191e --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/foo/bar/a.py @@ -0,0 +1,4 @@ +# name:afunc +def afunc(): + print("afunc called") + return 1 diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/options b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/options new file mode 100644 index 00000000000..cfef58cf2b2 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/options @@ -0,0 +1 @@ +semmle-extractor-options: --max-import-depth=1 --lang=3 From 85607fe2d574bc6c123c62fa21b8af8fd55aab09 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 25 Sep 2020 11:56:45 +0200 Subject: [PATCH 066/411] Python: Adjust location for .expected output --- .../library-tests/CallGraph-implicit-init/PointsTo.expected | 2 +- .../library-tests/CallGraph-implicit-init/TypeTracker.expected | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/PointsTo.expected b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/PointsTo.expected index e1f0f883631..d4362c9edf5 100644 --- a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/PointsTo.expected +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/PointsTo.expected @@ -2,5 +2,5 @@ debug_missingAnnotationForCallable debug_nonUniqueAnnotationForCallable debug_missingAnnotationForCall expectedCallEdgeNotFound -| example.py:12:1:12:7 | afunc() | foo/bar/a.py:2:1:2:12 | Function afunc | +| example.py:18:1:18:7 | afunc() | foo/bar/a.py:2:1:2:12 | Function afunc | unexpectedCallEdgeFound diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/TypeTracker.expected b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/TypeTracker.expected index e1f0f883631..d4362c9edf5 100644 --- a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/TypeTracker.expected +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/TypeTracker.expected @@ -2,5 +2,5 @@ debug_missingAnnotationForCallable debug_nonUniqueAnnotationForCallable debug_missingAnnotationForCall expectedCallEdgeNotFound -| example.py:12:1:12:7 | afunc() | foo/bar/a.py:2:1:2:12 | Function afunc | +| example.py:18:1:18:7 | afunc() | foo/bar/a.py:2:1:2:12 | Function afunc | unexpectedCallEdgeFound From 5256c0ba39caba0b2939c5626e2edc3f7e9dc92b Mon Sep 17 00:00:00 2001 From: Joe Date: Fri, 25 Sep 2020 11:19:13 +0100 Subject: [PATCH 067/411] Java: Improve PrintAst tests and rename things Add tests for `EnhcancedForStmt`s and `InstanceOfExpr`s. Rename LocalVarDeclParent to SingleLocalVarDeclParent --- java/ql/src/semmle/code/java/PrintAst.qll | 35 ++++++++--------- .../java7/MultiCatch/PrintAst.expected | 6 +-- java/ql/test/library-tests/printAst/A.java | 16 ++++++++ .../library-tests/printAst/PrintAst.expected | 38 +++++++++++++++++++ java/ql/test/library-tests/printAst/options | 1 + 5 files changed, 74 insertions(+), 22 deletions(-) create mode 100644 java/ql/test/library-tests/printAst/options diff --git a/java/ql/src/semmle/code/java/PrintAst.qll b/java/ql/src/semmle/code/java/PrintAst.qll index ca1daf6c2a4..4e219603024 100644 --- a/java/ql/src/semmle/code/java/PrintAst.qll +++ b/java/ql/src/semmle/code/java/PrintAst.qll @@ -115,7 +115,7 @@ private newtype TPrintAstNode = TElementNode(Element el) { shouldPrint(el, _) } or TForInitNode(ForStmt fs) { shouldPrint(fs, _) and exists(fs.getAnInit()) } or TLocalVarDeclNode(LocalVariableDeclExpr lvde) { - shouldPrint(lvde, _) and lvde.getParent() instanceof LocalVarDeclParent + shouldPrint(lvde, _) and lvde.getParent() instanceof SingleLocalVarDeclParent } or TAnnotationsNode(Annotatable ann) { shouldPrint(ann, _) and ann.hasAnnotation() and not partOfAnnotation(ann) @@ -266,13 +266,11 @@ final class AnnotationPartNode extends ExprStmtNode { } private Expr getAnAnnotationChild() { - ( - result = element.(Annotation).getValue(_) - or - result = element.(ArrayInit).getAnInit() - or - result = element.(ArrayInit).(Annotatable).getAnAnnotation() - ) + result = element.(Annotation).getValue(_) + or + result = element.(ArrayInit).getAnInit() + or + result = element.(ArrayInit).(Annotatable).getAnAnnotation() } } @@ -334,11 +332,11 @@ final class ForStmtNode extends ExprStmtNode { } /** - * An element that can be the parent of a `LocalVariableDeclExpr` for which we want + * An element that can be the parent of up to one `LocalVariableDeclExpr` for which we want * to use a synthetic node to hold the variable declaration and its `TypeAccess`. */ -private class LocalVarDeclParent extends ExprOrStmt { - LocalVarDeclParent() { +private class SingleLocalVarDeclParent extends ExprOrStmt { + SingleLocalVarDeclParent() { this instanceof EnhancedForStmt or this instanceof CatchClause or this.(InstanceOfExpr).isPattern() @@ -352,17 +350,16 @@ private class LocalVarDeclParent extends ExprOrStmt { } /** - * A node representing an element that can be the parent of a `LocalVariableDeclExpr` for which we + * A node representing an element that can be the parent of up to one `LocalVariableDeclExpr` for which we * want to use a synthetic node to variable declaration and its type access. * - * Excludes: - * - `LocalVariableDeclStmt` because a synthetic node isn't needed - * - `ForStmt` becasue a different synthetic node is already used + * Excludes `LocalVariableDeclStmt` and `ForStmt`, as they can hold multiple declarations. + * For these cases, either a synthetic node is not necassary or a different synthetic node is used. */ -final class LocalVarDeclParentNode extends ExprStmtNode { - LocalVarDeclParent lvdp; +final class SingleLocalVarDeclParentNode extends ExprStmtNode { + SingleLocalVarDeclParent lvdp; - LocalVarDeclParentNode() { lvdp = element } + SingleLocalVarDeclParentNode() { lvdp = element } override PrintAstNode getChild(int childIndex) { result = super.getChild(childIndex) and @@ -560,7 +557,7 @@ final class LocalVarDeclSynthNode extends PrintAstNode, TLocalVarDeclNode { LocalVarDeclSynthNode() { this = TLocalVarDeclNode(lvde) } - override string toString() { result = "(Local Variable Declaration)" } + override string toString() { result = "(Single Local Variable Declaration)" } override ElementNode getChild(int childIndex) { childIndex = 0 and diff --git a/java/ql/test/library-tests/java7/MultiCatch/PrintAst.expected b/java/ql/test/library-tests/java7/MultiCatch/PrintAst.expected index 98172ceff75..bba3b450e3e 100644 --- a/java/ql/test/library-tests/java7/MultiCatch/PrintAst.expected +++ b/java/ql/test/library-tests/java7/MultiCatch/PrintAst.expected @@ -21,7 +21,7 @@ MultiCatch.java: # 14| 0: [ClassInstanceExpr] new SQLException(...) # 14| -3: [TypeAccess] SQLException # 15| 0: [CatchClause] stmt -#-----| 0: (Local Variable Declaration) +#-----| 0: (Single Local Variable Declaration) # 15| 0: [UnionTypeAccess] ...|... # 15| 0: [TypeAccess] IOException # 15| 1: [TypeAccess] SQLException @@ -56,7 +56,7 @@ MultiCatch.java: # 30| 0: [ClassInstanceExpr] new Exception(...) # 30| -3: [TypeAccess] Exception # 31| 0: [CatchClause] stmt -#-----| 0: (Local Variable Declaration) +#-----| 0: (Single Local Variable Declaration) # 31| 0: [UnionTypeAccess] ...|... # 31| 0: [TypeAccess] IOException # 31| 1: [TypeAccess] SQLException @@ -71,7 +71,7 @@ MultiCatch.java: # 39| 0: [ClassInstanceExpr] new IOException(...) # 39| -3: [TypeAccess] IOException # 40| 0: [CatchClause] stmt -#-----| 0: (Local Variable Declaration) +#-----| 0: (Single Local Variable Declaration) # 40| 0: [TypeAccess] Exception # 40| 1: [LocalVariableDeclExpr] e # 41| 1: [BlockStmt] stmt diff --git a/java/ql/test/library-tests/printAst/A.java b/java/ql/test/library-tests/printAst/A.java index c3176cc14f3..38319c64706 100644 --- a/java/ql/test/library-tests/printAst/A.java +++ b/java/ql/test/library-tests/printAst/A.java @@ -40,4 +40,20 @@ class A { @Ann2(7) }) String doSomethingElse() { return "c"; } + + void varDecls(Object[] things) { + try { + for(Object thing : things) { + if (thing instanceof Integer) { + return; + } + if (thing instanceof String s) { + throw new RuntimeException(s); + } + } + } + catch (RuntimeException rte) { + return; + } + } } \ No newline at end of file diff --git a/java/ql/test/library-tests/printAst/PrintAst.expected b/java/ql/test/library-tests/printAst/PrintAst.expected index c8f22de6950..922acc4011a 100644 --- a/java/ql/test/library-tests/printAst/PrintAst.expected +++ b/java/ql/test/library-tests/printAst/PrintAst.expected @@ -87,3 +87,41 @@ A.java: # 42| 5: [BlockStmt] stmt # 42| 0: [ReturnStmt] stmt # 42| 0: [StringLiteral] "c" +# 44| 9: [Method] varDecls +# 44| 3: [TypeAccess] void +#-----| 4: (Parameters) +# 44| 0: [Parameter] things +# 44| 0: [ArrayTypeAccess] ...[] +# 44| 0: [TypeAccess] Object +# 44| 5: [BlockStmt] stmt +# 45| 0: [TryStmt] stmt +# 45| -1: [BlockStmt] stmt +# 46| 0: [EnhancedForStmt] stmt +#-----| 0: (Single Local Variable Declaration) +# 46| 0: [TypeAccess] Object +# 46| 1: [LocalVariableDeclExpr] thing +# 46| 1: [VarAccess] things +# 46| 2: [BlockStmt] stmt +# 47| 0: [IfStmt] stmt +# 47| 0: [InstanceOfExpr] ...instanceof... +# 47| 0: [VarAccess] thing +# 47| 1: [TypeAccess] Integer +# 47| 1: [BlockStmt] stmt +# 48| 0: [ReturnStmt] stmt +# 50| 1: [IfStmt] stmt +# 50| 0: [InstanceOfExpr] ...instanceof... +#-----| 0: (Single Local Variable Declaration) +# 50| 0: [TypeAccess] String +# 50| 1: [LocalVariableDeclExpr] s +# 50| 0: [VarAccess] thing +# 50| 1: [BlockStmt] stmt +# 51| 0: [ThrowStmt] stmt +# 51| 0: [ClassInstanceExpr] new RuntimeException(...) +# 51| -3: [TypeAccess] RuntimeException +# 51| 0: [VarAccess] s +# 55| 0: [CatchClause] stmt +#-----| 0: (Single Local Variable Declaration) +# 55| 0: [TypeAccess] RuntimeException +# 55| 1: [LocalVariableDeclExpr] rte +# 55| 1: [BlockStmt] stmt +# 56| 0: [ReturnStmt] stmt diff --git a/java/ql/test/library-tests/printAst/options b/java/ql/test/library-tests/printAst/options new file mode 100644 index 00000000000..266b0eadc5e --- /dev/null +++ b/java/ql/test/library-tests/printAst/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args --enable-preview -source 14 -target 14 From 0ccbaf9e88f9053edf990a0aedfc035bc606ade9 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Fri, 25 Sep 2020 12:12:39 +0100 Subject: [PATCH 068/411] JavaScript: Handle empty `package.json` files gracefully. --- .../semmle/js/extractor/ScriptExtractor.java | 6 +++- .../tests/moduleTypes3/input/package.json | 0 .../extractor/tests/moduleTypes3/input/tst.js | 0 .../output/trap/package.json.trap | 15 ++++++++++ .../moduleTypes3/output/trap/tst.js.trap | 28 +++++++++++++++++++ 5 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 javascript/extractor/tests/moduleTypes3/input/package.json create mode 100644 javascript/extractor/tests/moduleTypes3/input/tst.js create mode 100644 javascript/extractor/tests/moduleTypes3/output/trap/package.json.trap create mode 100644 javascript/extractor/tests/moduleTypes3/output/trap/tst.js.trap diff --git a/javascript/extractor/src/com/semmle/js/extractor/ScriptExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ScriptExtractor.java index b0ce54d02aa..7d8ccc6b3b1 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ScriptExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ScriptExtractor.java @@ -126,7 +126,11 @@ public class ScriptExtractor implements IExtractor { } try { BufferedReader reader = new BufferedReader(new FileReader(file)); - String result = new Gson().fromJson(reader, PackageJSON.class).type; + PackageJSON pkgjson = new Gson().fromJson(reader, PackageJSON.class); + if (pkgjson == null) { + return null; + } + String result = pkgjson.type; packageTypeCache.put(folder, Optional.ofNullable(result)); return result; } catch (IOException | JsonSyntaxException e) { diff --git a/javascript/extractor/tests/moduleTypes3/input/package.json b/javascript/extractor/tests/moduleTypes3/input/package.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/javascript/extractor/tests/moduleTypes3/input/tst.js b/javascript/extractor/tests/moduleTypes3/input/tst.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/javascript/extractor/tests/moduleTypes3/output/trap/package.json.trap b/javascript/extractor/tests/moduleTypes3/output/trap/package.json.trap new file mode 100644 index 00000000000..eed0d0523d5 --- /dev/null +++ b/javascript/extractor/tests/moduleTypes3/output/trap/package.json.trap @@ -0,0 +1,15 @@ +#10000=@"/package.json;sourcefile" +files(#10000,"/package.json","package","json",0) +#10001=@"/;folder" +folders(#10001,"/","") +containerparent(#10001,#10000) +#10002=@"loc,{#10000},0,0,0,0" +locations_default(#10002,#10000,0,0,0,0) +hasLocation(#10000,#10002) +#20000=* +json_errors(#20000,"Error: Unexpected token") +#20001=@"loc,{#10000},1,1,1,1" +locations_default(#20001,#10000,1,1,1,1) +hasLocation(#20000,#20001) +numlines(#10000,0,0,0) +filetype(#10000,"json") diff --git a/javascript/extractor/tests/moduleTypes3/output/trap/tst.js.trap b/javascript/extractor/tests/moduleTypes3/output/trap/tst.js.trap new file mode 100644 index 00000000000..cedeb436b92 --- /dev/null +++ b/javascript/extractor/tests/moduleTypes3/output/trap/tst.js.trap @@ -0,0 +1,28 @@ +#10000=@"/tst.js;sourcefile" +files(#10000,"/tst.js","tst","js",0) +#10001=@"/;folder" +folders(#10001,"/","") +containerparent(#10001,#10000) +#10002=@"loc,{#10000},0,0,0,0" +locations_default(#10002,#10000,0,0,0,0) +hasLocation(#10000,#10002) +#20000=@"global_scope" +scopes(#20000,0) +#20001=@"script;{#10000},1,1" +numlines(#20001,0,0,0) +#20002=* +tokeninfo(#20002,0,#20001,0,"") +#20003=@"loc,{#10000},1,1,1,0" +locations_default(#20003,#10000,1,1,1,0) +hasLocation(#20002,#20003) +toplevels(#20001,0) +hasLocation(#20001,#20003) +#20004=* +entry_cfg_node(#20004,#20001) +hasLocation(#20004,#20003) +#20005=* +exit_cfg_node(#20005,#20001) +hasLocation(#20005,#20003) +successor(#20004,#20005) +numlines(#10000,0,0,0) +filetype(#10000,"javascript") From a22ddb145bd0124aea81ff0d3afc40005c1c73c0 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 25 Sep 2020 13:53:22 +0200 Subject: [PATCH 069/411] model calls to needle --- .../javascript/frameworks/ClientRequests.qll | 30 +++++++++++++++++++ .../ClientRequests/ClientRequests.expected | 5 ++++ .../frameworks/ClientRequests/tst.js | 6 ++++ 3 files changed, 41 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll index 1c0ac8d6a16..11a60eabb3b 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll @@ -327,6 +327,36 @@ module ClientRequest { } } + /** + * Classes for modelling the url request library `needle`. + */ + private module Needle { + /** + * A model of a URL request made using `require("needle")(...)`. + */ + class PromisedNeedleRequest extends ClientRequest::Range { + DataFlow::Node url; + + PromisedNeedleRequest() { this = DataFlow::moduleImport("needle").getACall() } + + override DataFlow::Node getUrl() { result = getArgument(1) } + + override DataFlow::Node getHost() { none() } + + override DataFlow::Node getADataNode() { + result = getOptionArgument([2, 3], "headers") + or + result = getArgument(2) + } + + override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) { + responseType = "fetch.response" and + promise = true and + result = this + } + } + } + /** * A model of a URL request made using the `got` library. */ diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected index 1c91826ac8d..3209b0e8be0 100644 --- a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected +++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected @@ -67,6 +67,7 @@ test_ClientRequest | tst.js:202:5:208:7 | $.ajax( ... }}) | | tst.js:210:2:210:21 | $.get("example.php") | | tst.js:219:5:219:41 | data.so ... Host"}) | +| tst.js:229:5:229:67 | needle( ... ptions) | test_getADataNode | tst.js:53:5:53:23 | axios({data: data}) | tst.js:53:18:53:21 | data | | tst.js:57:5:57:39 | axios.p ... data2}) | tst.js:57:19:57:23 | data1 | @@ -97,6 +98,8 @@ test_getADataNode | tst.js:183:2:183:60 | $.post( ... ) { }) | tst.js:183:28:183:37 | "PostData" | | tst.js:187:2:193:3 | $.ajax( ... on"\\n\\t}) | tst.js:190:11:190:20 | "AjaxData" | | tst.js:219:5:219:41 | data.so ... Host"}) | tst.js:223:23:223:30 | "foobar" | +| tst.js:229:5:229:67 | needle( ... ptions) | tst.js:228:32:228:70 | { 'X-Cu ... tuna' } | +| tst.js:229:5:229:67 | needle( ... ptions) | tst.js:229:50:229:57 | "MyData" | test_getHost | tst.js:87:5:87:39 | http.ge ... host}) | tst.js:87:34:87:37 | host | | tst.js:89:5:89:23 | axios({host: host}) | tst.js:89:18:89:21 | host | @@ -177,6 +180,7 @@ test_getUrl | tst.js:202:5:208:7 | $.ajax( ... }}) | tst.js:203:10:203:22 | "example.php" | | tst.js:210:2:210:21 | $.get("example.php") | tst.js:210:8:210:20 | "example.php" | | tst.js:219:5:219:41 | data.so ... Host"}) | tst.js:219:25:219:40 | {host: "myHost"} | +| tst.js:229:5:229:67 | needle( ... ptions) | tst.js:229:20:229:47 | "http:/ ... oo/bar" | test_getAResponseDataNode | tst.js:19:5:19:23 | requestPromise(url) | tst.js:19:5:19:23 | requestPromise(url) | text | true | | tst.js:21:5:21:23 | superagent.get(url) | tst.js:21:5:21:23 | superagent.get(url) | stream | true | @@ -238,3 +242,4 @@ test_getAResponseDataNode | tst.js:202:5:208:7 | $.ajax( ... }}) | tst.js:207:21:207:36 | err.responseText | json | false | | tst.js:210:2:210:21 | $.get("example.php") | tst.js:210:55:210:70 | xhr.responseText | | false | | tst.js:219:5:219:41 | data.so ... Host"}) | tst.js:221:29:221:32 | data | text | false | +| tst.js:229:5:229:67 | needle( ... ptions) | tst.js:229:5:229:67 | needle( ... ptions) | fetch.response | true | diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js b/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js index e828423f91c..8dd1c2d60f0 100644 --- a/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js +++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js @@ -221,4 +221,10 @@ const net = require("net"); data.socket.on("data", (data) => {}); data.socket.write("foobar"); +})(); + +const needle = require("needle"); +(function () { + const options = { headers: { 'X-Custom-Header': 'Bumbaway atuna' } }; + needle("POST", "http://example.org/foo/bar", "MyData", options).then(function(resp) { console.log(resp.body) }); })(); \ No newline at end of file From 6b9aea82ca963f065e6ade87bada4693ec634944 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 25 Sep 2020 14:13:31 +0200 Subject: [PATCH 070/411] model method calls in the needle library --- .../javascript/frameworks/ClientRequests.qll | 49 +++++++++++++++++++ .../ClientRequests/ClientRequests.expected | 10 ++++ .../frameworks/ClientRequests/tst.js | 8 +++ 3 files changed, 67 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll index 11a60eabb3b..fa9fb550330 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll @@ -355,6 +355,55 @@ module ClientRequest { result = this } } + + /** + * A model of a URL request made using `require("needle")[method](...)`. + * E.g. `needle.get("http://example.org", (err, resp, body) => {})`. + * + * As opposed to the calls modeled in `PromisedNeedleRequest` these calls do not return promises. + * Instead they take an optional callback as their last argument. + */ + class NeedleMethodRequest extends ClientRequest::Range { + boolean hasData; + + NeedleMethodRequest() { + exists(string method | + method = ["get", "head"] and hasData = false + or + method = ["post", "put", "patch", "delete"] and hasData = true + or + method = "request" and hasData = [true, false] + | + this = DataFlow::moduleMember("needle", method).getACall() + ) + } + + override DataFlow::Node getUrl() { result = getArgument(0) } + + override DataFlow::Node getHost() { none() } + + override DataFlow::Node getADataNode() { + hasData = true and + ( + result = getArgument(1) + or + result = getOptionArgument(2, "headers") + ) + or + hasData = false and + result = getOptionArgument(1, "headers") + } + + override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) { + promise = false and + result = this.getCallback(this.getNumArgument() - 1).getParameter(1) and + responseType = "fetch.response" + or + promise = false and + result = this.getCallback(this.getNumArgument() - 1).getParameter(2) and + responseType = "json" + } + } } /** diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected index 3209b0e8be0..5ba426c968f 100644 --- a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected +++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected @@ -68,6 +68,8 @@ test_ClientRequest | tst.js:210:2:210:21 | $.get("example.php") | | tst.js:219:5:219:41 | data.so ... Host"}) | | tst.js:229:5:229:67 | needle( ... ptions) | +| tst.js:231:5:233:6 | needle. ... \\n }) | +| tst.js:235:5:237:6 | needle. ... \\n }) | test_getADataNode | tst.js:53:5:53:23 | axios({data: data}) | tst.js:53:18:53:21 | data | | tst.js:57:5:57:39 | axios.p ... data2}) | tst.js:57:19:57:23 | data1 | @@ -100,6 +102,8 @@ test_getADataNode | tst.js:219:5:219:41 | data.so ... Host"}) | tst.js:223:23:223:30 | "foobar" | | tst.js:229:5:229:67 | needle( ... ptions) | tst.js:228:32:228:70 | { 'X-Cu ... tuna' } | | tst.js:229:5:229:67 | needle( ... ptions) | tst.js:229:50:229:57 | "MyData" | +| tst.js:235:5:237:6 | needle. ... \\n }) | tst.js:228:32:228:70 | { 'X-Cu ... tuna' } | +| tst.js:235:5:237:6 | needle. ... \\n }) | tst.js:235:44:235:49 | "data" | test_getHost | tst.js:87:5:87:39 | http.ge ... host}) | tst.js:87:34:87:37 | host | | tst.js:89:5:89:23 | axios({host: host}) | tst.js:89:18:89:21 | host | @@ -181,6 +185,8 @@ test_getUrl | tst.js:210:2:210:21 | $.get("example.php") | tst.js:210:8:210:20 | "example.php" | | tst.js:219:5:219:41 | data.so ... Host"}) | tst.js:219:25:219:40 | {host: "myHost"} | | tst.js:229:5:229:67 | needle( ... ptions) | tst.js:229:20:229:47 | "http:/ ... oo/bar" | +| tst.js:231:5:233:6 | needle. ... \\n }) | tst.js:231:16:231:35 | "http://example.org" | +| tst.js:235:5:237:6 | needle. ... \\n }) | tst.js:235:17:235:41 | "http:/ ... g/post" | test_getAResponseDataNode | tst.js:19:5:19:23 | requestPromise(url) | tst.js:19:5:19:23 | requestPromise(url) | text | true | | tst.js:21:5:21:23 | superagent.get(url) | tst.js:21:5:21:23 | superagent.get(url) | stream | true | @@ -243,3 +249,7 @@ test_getAResponseDataNode | tst.js:210:2:210:21 | $.get("example.php") | tst.js:210:55:210:70 | xhr.responseText | | false | | tst.js:219:5:219:41 | data.so ... Host"}) | tst.js:221:29:221:32 | data | text | false | | tst.js:229:5:229:67 | needle( ... ptions) | tst.js:229:5:229:67 | needle( ... ptions) | fetch.response | true | +| tst.js:231:5:233:6 | needle. ... \\n }) | tst.js:231:44:231:47 | resp | fetch.response | false | +| tst.js:231:5:233:6 | needle. ... \\n }) | tst.js:231:50:231:53 | body | json | false | +| tst.js:235:5:237:6 | needle. ... \\n }) | tst.js:235:67:235:70 | resp | fetch.response | false | +| tst.js:235:5:237:6 | needle. ... \\n }) | tst.js:235:73:235:76 | body | json | false | diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js b/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js index 8dd1c2d60f0..a24a0dca791 100644 --- a/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js +++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js @@ -227,4 +227,12 @@ const needle = require("needle"); (function () { const options = { headers: { 'X-Custom-Header': 'Bumbaway atuna' } }; needle("POST", "http://example.org/foo/bar", "MyData", options).then(function(resp) { console.log(resp.body) }); + + needle.get("http://example.org", (err, resp, body) => { + + }); + + needle.post("http://example.org/post", "data", options, (err, resp, body) => { + + }); })(); \ No newline at end of file From 2acfd4cdb1775ab311e36d4147c229bb3c7cf3ce Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 25 Sep 2020 18:28:31 +0200 Subject: [PATCH 071/411] Python: Show we're able to handle example with __init__.py files --- .../library-tests/CallGraph-implicit-init/PointsTo.expected | 2 +- .../library-tests/CallGraph-implicit-init/Relative.expected | 1 + .../CallGraph-implicit-init/TypeTracker.expected | 3 ++- .../library-tests/CallGraph-implicit-init/example.py | 4 ++++ .../CallGraph-implicit-init/foo_explicit/__init__.py | 0 .../CallGraph-implicit-init/foo_explicit/bar/__init__.py | 0 .../CallGraph-implicit-init/foo_explicit/bar/a.py | 4 ++++ 7 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 python/ql/test/experimental/library-tests/CallGraph-implicit-init/foo_explicit/__init__.py create mode 100644 python/ql/test/experimental/library-tests/CallGraph-implicit-init/foo_explicit/bar/__init__.py create mode 100644 python/ql/test/experimental/library-tests/CallGraph-implicit-init/foo_explicit/bar/a.py diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/PointsTo.expected b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/PointsTo.expected index d4362c9edf5..349d99b46d8 100644 --- a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/PointsTo.expected +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/PointsTo.expected @@ -2,5 +2,5 @@ debug_missingAnnotationForCallable debug_nonUniqueAnnotationForCallable debug_missingAnnotationForCall expectedCallEdgeNotFound -| example.py:18:1:18:7 | afunc() | foo/bar/a.py:2:1:2:12 | Function afunc | +| example.py:19:1:19:7 | afunc() | foo/bar/a.py:2:1:2:12 | Function afunc | unexpectedCallEdgeFound diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/Relative.expected b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/Relative.expected index c25b2538ffa..38aab0b5888 100644 --- a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/Relative.expected +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/Relative.expected @@ -2,4 +2,5 @@ debug_missingAnnotationForCallable debug_nonUniqueAnnotationForCallable debug_missingAnnotationForCall pointsTo_found_typeTracker_notFound +| example.py:22:1:22:16 | explicit_afunc() | foo_explicit/bar/a.py:2:1:2:21 | Function explicit_afunc | pointsTo_notFound_typeTracker_found diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/TypeTracker.expected b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/TypeTracker.expected index d4362c9edf5..5283683a6a5 100644 --- a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/TypeTracker.expected +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/TypeTracker.expected @@ -2,5 +2,6 @@ debug_missingAnnotationForCallable debug_nonUniqueAnnotationForCallable debug_missingAnnotationForCall expectedCallEdgeNotFound -| example.py:18:1:18:7 | afunc() | foo/bar/a.py:2:1:2:12 | Function afunc | +| example.py:19:1:19:7 | afunc() | foo/bar/a.py:2:1:2:12 | Function afunc | +| example.py:22:1:22:16 | explicit_afunc() | foo_explicit/bar/a.py:2:1:2:21 | Function explicit_afunc | unexpectedCallEdgeFound diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/example.py b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/example.py index 67bbf5c707c..35d56620af7 100644 --- a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/example.py +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/example.py @@ -13,6 +13,10 @@ Since PEP 420 was accepted in Python 3, this test is Python 3 only. """ from foo.bar.a import afunc +from foo_explicit.bar.a import explicit_afunc # calls:afunc afunc() + +# calls:explicit_afunc +explicit_afunc() diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/foo_explicit/__init__.py b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/foo_explicit/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/foo_explicit/bar/__init__.py b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/foo_explicit/bar/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/experimental/library-tests/CallGraph-implicit-init/foo_explicit/bar/a.py b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/foo_explicit/bar/a.py new file mode 100644 index 00000000000..616c3fddca1 --- /dev/null +++ b/python/ql/test/experimental/library-tests/CallGraph-implicit-init/foo_explicit/bar/a.py @@ -0,0 +1,4 @@ +# name:explicit_afunc +def explicit_afunc(): + print("explicit_afunc called") + return 1 From 9240256a9f0910b6aac8da05c087d6208f353f7f Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 25 Sep 2020 11:55:39 -0700 Subject: [PATCH 072/411] C++: fix QLDoc --- cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll index 15c15595c4f..40a671429f3 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll @@ -244,7 +244,7 @@ private module PartialDefinitions { } /** - * A partial definition that's a definition by reference. + * A partial definition that's a definition via an output iterator. */ class DefinitionByIterator extends IteratorPartialDefinition { DefinitionByIterator() { exists(Call c | this = c.getAnArgument() or this = c.getQualifier()) } From 713bdae77adc8f91fb7f43ac69823d93d4088b2c Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 25 Sep 2020 13:54:58 -0700 Subject: [PATCH 073/411] C++: sync identical files --- .../cpp/ir/implementation/aliased_ssa/Operand.qll | 3 ++- .../code/cpp/ir/implementation/raw/Operand.qll | 3 ++- .../ir/implementation/raw/Operand.qll | 3 ++- .../ir/implementation/unaliased_ssa/Operand.qll | 3 ++- .../unaliased_ssa/internal/SimpleSSA.qll | 6 ++++++ .../ql/src/experimental/ir/internal/Overlap.qll | 15 +++++++++++++++ 6 files changed, 29 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll index 14f62da51cd..e476aec60af 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll @@ -79,7 +79,8 @@ private PhiOperandBase phiOperand( } /** - * A source operand of an `Instruction`. The operand represents a value consumed by the instruction. + * An operand of an `Instruction`. The operand represents a use of the result of one instruction + * (the defining instruction) in another instruction (the use instruction) */ class Operand extends TOperand { /** Gets a textual representation of this element. */ diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll index 14f62da51cd..e476aec60af 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll @@ -79,7 +79,8 @@ private PhiOperandBase phiOperand( } /** - * A source operand of an `Instruction`. The operand represents a value consumed by the instruction. + * An operand of an `Instruction`. The operand represents a use of the result of one instruction + * (the defining instruction) in another instruction (the use instruction) */ class Operand extends TOperand { /** Gets a textual representation of this element. */ diff --git a/csharp/ql/src/experimental/ir/implementation/raw/Operand.qll b/csharp/ql/src/experimental/ir/implementation/raw/Operand.qll index 14f62da51cd..e476aec60af 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/Operand.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/Operand.qll @@ -79,7 +79,8 @@ private PhiOperandBase phiOperand( } /** - * A source operand of an `Instruction`. The operand represents a value consumed by the instruction. + * An operand of an `Instruction`. The operand represents a use of the result of one instruction + * (the defining instruction) in another instruction (the use instruction) */ class Operand extends TOperand { /** Gets a textual representation of this element. */ diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll index 14f62da51cd..e476aec60af 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll @@ -79,7 +79,8 @@ private PhiOperandBase phiOperand( } /** - * A source operand of an `Instruction`. The operand represents a value consumed by the instruction. + * An operand of an `Instruction`. The operand represents a use of the result of one instruction + * (the defining instruction) in another instruction (the use instruction) */ class Operand extends TOperand { /** Gets a textual representation of this element. */ diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll index 3de8f5259f8..a7b9160bdc7 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll @@ -59,6 +59,12 @@ class MemoryLocation extends TMemoryLocation { final string getUniqueId() { result = var.getUniqueId() } } +/** + * Represents a set of `MemoryLocation`s that cannot overlap with + * `MemoryLocation`s outside of the set. The `VirtualVariable` will be + * represented by a `MemoryLocation` that totally overlaps all other + * `MemoryLocations` in the set. + */ class VirtualVariable extends MemoryLocation { } /** A virtual variable that groups all escaped memory within a function. */ diff --git a/csharp/ql/src/experimental/ir/internal/Overlap.qll b/csharp/ql/src/experimental/ir/internal/Overlap.qll index 8ce0549b2b4..f9a0c574f8c 100644 --- a/csharp/ql/src/experimental/ir/internal/Overlap.qll +++ b/csharp/ql/src/experimental/ir/internal/Overlap.qll @@ -3,18 +3,33 @@ private newtype TOverlap = TMustTotallyOverlap() or TMustExactlyOverlap() +/** + * Represents a possible overlap between two memory ranges. + */ abstract class Overlap extends TOverlap { abstract string toString(); } +/** + * Represents a partial overlap between two memory ranges, which may or may not + * actually occur in practice. + */ class MayPartiallyOverlap extends Overlap, TMayPartiallyOverlap { final override string toString() { result = "MayPartiallyOverlap" } } +/** + * Represents an overlap in which the first memory range is known to include all + * bits of the second memory range, but may be larger or have a different type. + */ class MustTotallyOverlap extends Overlap, TMustTotallyOverlap { final override string toString() { result = "MustTotallyOverlap" } } +/** + * Represents an overlap between two memory ranges that have the same extent and + * the same type. + */ class MustExactlyOverlap extends Overlap, TMustExactlyOverlap { final override string toString() { result = "MustExactlyOverlap" } } From 27dc49ff7a6f0e1c0724367b628291b97f6b4407 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 25 Sep 2020 17:49:01 -0700 Subject: [PATCH 074/411] C++: Fix performance issue in PartialDefinition --- cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll index 40a671429f3..50395dbaafc 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll @@ -112,8 +112,6 @@ private module PartialDefinitions { abstract class PartialDefinition extends Expr { ControlFlowNode node; - PartialDefinition() { not this instanceof Conversion } - abstract deprecated predicate partiallyDefines(Variable v); abstract deprecated predicate partiallyDefinesThis(ThisExpr e); @@ -161,6 +159,7 @@ private module PartialDefinitions { IteratorPartialDefinition() { exists(Expr convertedInner | + not this instanceof Conversion and valueToUpdate(convertedInner, this.getFullyConverted(), node) and innerDefinedExpr = convertedInner.getUnconverted() and ( @@ -212,6 +211,7 @@ private module PartialDefinitions { Expr innerDefinedExpr; VariablePartialDefinition() { + not this instanceof Conversion and exists(Expr convertedInner | valueToUpdate(convertedInner, this.getFullyConverted(), node) and innerDefinedExpr = convertedInner.getUnconverted() From 664342dd0f2f273d702c14a2c05d715700df5b85 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sat, 26 Sep 2020 21:31:06 +0200 Subject: [PATCH 075/411] change `SimpleParameter` to `Parameter` in the express model to support destructuring parameters --- .../ql/src/semmle/javascript/frameworks/Express.qll | 12 ++++++------ .../ServerSideUrlRedirect.expected | 10 ++++++++++ .../CWE-601/ServerSideUrlRedirect/express.js | 7 +++++++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Express.qll b/javascript/ql/src/semmle/javascript/frameworks/Express.qll index 5a5af64aefc..af6675d188e 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Express.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Express.qll @@ -195,7 +195,7 @@ module Express { PassportRouteHandler() { this = any(PassportRouteSetup setup).getARouteHandler() } - override SimpleParameter getRouteHandlerParameter(string kind) { + override Parameter getRouteHandlerParameter(string kind) { kind = "request" and result = astNode.getParameter(0) } @@ -329,17 +329,17 @@ module Express { * * `kind` is one of: "error", "request", "response", "next", or "parameter". */ - abstract SimpleParameter getRouteHandlerParameter(string kind); + abstract Parameter getRouteHandlerParameter(string kind); /** * Gets the parameter of the route handler that contains the request object. */ - SimpleParameter getRequestParameter() { result = getRouteHandlerParameter("request") } + Parameter getRequestParameter() { result = getRouteHandlerParameter("request") } /** * Gets the parameter of the route handler that contains the response object. */ - SimpleParameter getResponseParameter() { result = getRouteHandlerParameter("response") } + Parameter getResponseParameter() { result = getRouteHandlerParameter("response") } /** * Gets a request body access of this handler. @@ -357,7 +357,7 @@ module Express { StandardRouteHandler() { this = routeSetup.getARouteHandler() } - override SimpleParameter getRouteHandlerParameter(string kind) { + override Parameter getRouteHandlerParameter(string kind) { if routeSetup.isParameterHandler() then result = getRouteParameterHandlerParameter(astNode, kind) else result = getRouteHandlerParameter(astNode, kind) @@ -890,7 +890,7 @@ module Express { TrackedRouteHandlerCandidateWithSetup() { this = routeSetup.getARouteHandler() } - override SimpleParameter getRouteHandlerParameter(string kind) { + override Parameter getRouteHandlerParameter(string kind) { if routeSetup.isParameterHandler() then result = getRouteParameterHandlerParameter(astNode, kind) else result = getRouteHandlerParameter(astNode, kind) diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected index 299c434f329..5a8ed33b530 100644 --- a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected +++ b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected @@ -44,6 +44,12 @@ nodes | express.js:136:16:136:36 | 'u' + r ... ms.user | | express.js:136:22:136:36 | req.params.user | | express.js:136:22:136:36 | req.params.user | +| express.js:143:16:143:28 | req.query.foo | +| express.js:143:16:143:28 | req.query.foo | +| express.js:143:16:143:28 | req.query.foo | +| express.js:146:16:146:24 | query.foo | +| express.js:146:16:146:24 | query.foo | +| express.js:146:16:146:24 | query.foo | | koa.js:6:6:6:27 | url | | koa.js:6:12:6:27 | ctx.query.target | | koa.js:6:12:6:27 | ctx.query.target | @@ -128,6 +134,8 @@ edges | express.js:136:22:136:36 | req.params.user | express.js:136:16:136:36 | 'u' + r ... ms.user | | express.js:136:22:136:36 | req.params.user | express.js:136:16:136:36 | 'u' + r ... ms.user | | express.js:136:22:136:36 | req.params.user | express.js:136:16:136:36 | 'u' + r ... ms.user | +| express.js:143:16:143:28 | req.query.foo | express.js:143:16:143:28 | req.query.foo | +| express.js:146:16:146:24 | query.foo | express.js:146:16:146:24 | query.foo | | koa.js:6:6:6:27 | url | koa.js:7:15:7:17 | url | | koa.js:6:6:6:27 | url | koa.js:7:15:7:17 | url | | koa.js:6:6:6:27 | url | koa.js:8:18:8:20 | url | @@ -181,6 +189,8 @@ edges | express.js:134:16:134:36 | '/' + r ... ms.user | express.js:134:22:134:36 | req.params.user | express.js:134:16:134:36 | '/' + r ... ms.user | Untrusted URL redirection due to $@. | express.js:134:22:134:36 | req.params.user | user-provided value | | express.js:135:16:135:37 | '//' + ... ms.user | express.js:135:23:135:37 | req.params.user | express.js:135:16:135:37 | '//' + ... ms.user | Untrusted URL redirection due to $@. | express.js:135:23:135:37 | req.params.user | user-provided value | | express.js:136:16:136:36 | 'u' + r ... ms.user | express.js:136:22:136:36 | req.params.user | express.js:136:16:136:36 | 'u' + r ... ms.user | Untrusted URL redirection due to $@. | express.js:136:22:136:36 | req.params.user | user-provided value | +| express.js:143:16:143:28 | req.query.foo | express.js:143:16:143:28 | req.query.foo | express.js:143:16:143:28 | req.query.foo | Untrusted URL redirection due to $@. | express.js:143:16:143:28 | req.query.foo | user-provided value | +| express.js:146:16:146:24 | query.foo | express.js:146:16:146:24 | query.foo | express.js:146:16:146:24 | query.foo | Untrusted URL redirection due to $@. | express.js:146:16:146:24 | query.foo | user-provided value | | koa.js:7:15:7:17 | url | koa.js:6:12:6:27 | ctx.query.target | koa.js:7:15:7:17 | url | Untrusted URL redirection due to $@. | koa.js:6:12:6:27 | ctx.query.target | user-provided value | | koa.js:8:15:8:26 | `${url}${x}` | koa.js:6:12:6:27 | ctx.query.target | koa.js:8:15:8:26 | `${url}${x}` | Untrusted URL redirection due to $@. | koa.js:6:12:6:27 | ctx.query.target | user-provided value | | koa.js:14:16:14:18 | url | koa.js:6:12:6:27 | ctx.query.target | koa.js:14:16:14:18 | url | Untrusted URL redirection due to $@. | koa.js:6:12:6:27 | ctx.query.target | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/express.js b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/express.js index 4c7c476a060..b319315b985 100644 --- a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/express.js +++ b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/express.js @@ -138,3 +138,10 @@ app.get('/redirect/:user', function(req, res) { res.redirect('/' + ('/u' + req.params.user)); // BAD - could go to //u.evil.com, but not flagged [INCONSISTENCY] res.redirect('/u' + req.params.user); // GOOD }); + +app.get("foo", (req, res) => { + res.redirect(req.query.foo); // NOT OK +}); +app.get("bar", ({query}, res) => { + res.redirect(query.foo); // NOT OK +}) \ No newline at end of file From 11587c930be898eb893c5cf9889812aa6b0a5034 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 28 Sep 2020 09:19:35 +0100 Subject: [PATCH 076/411] C++: Autoformat. --- .../src/semmle/code/cpp/models/implementations/StdMap.qll | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll index adf74973b50..7f2f3a1f4eb 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll @@ -78,9 +78,7 @@ class StdMapAt extends TaintFunction { * The standard map `find` function. */ class StdMapFind extends TaintFunction { - StdMapFind() { - this.hasQualifiedName("std", ["map", "unordered_map"], "find") - } + StdMapFind() { this.hasQualifiedName("std", ["map", "unordered_map"], "find") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isQualifierObject() and @@ -92,9 +90,7 @@ class StdMapFind extends TaintFunction { * The standard map `erase` function. */ class StdMapErase extends TaintFunction { - StdMapErase() { - this.hasQualifiedName("std", ["map", "unordered_map"], "erase") - } + StdMapErase() { this.hasQualifiedName("std", ["map", "unordered_map"], "erase") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from qualifier to iterator return value From a6b62a383835f9ec50dc44aac4709bf2ebded438 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 22 Sep 2020 08:42:06 +0200 Subject: [PATCH 077/411] C#: Add enum init value test --- csharp/ql/test/library-tests/enums/Enums11.expected | 0 csharp/ql/test/library-tests/enums/Enums11.ql | 9 +++++++++ 2 files changed, 9 insertions(+) create mode 100644 csharp/ql/test/library-tests/enums/Enums11.expected create mode 100644 csharp/ql/test/library-tests/enums/Enums11.ql diff --git a/csharp/ql/test/library-tests/enums/Enums11.expected b/csharp/ql/test/library-tests/enums/Enums11.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/csharp/ql/test/library-tests/enums/Enums11.ql b/csharp/ql/test/library-tests/enums/Enums11.ql new file mode 100644 index 00000000000..cf808bf4f29 --- /dev/null +++ b/csharp/ql/test/library-tests/enums/Enums11.ql @@ -0,0 +1,9 @@ +/** + * @name Test for enums + */ + +import csharp + +from FieldAccess fa +where fa.getParent().(Field).getDeclaringType() instanceof Enum +select fa, fa.getValue() From 77bb1b2cd9dbc80e174fad7307e3c79940ea0506 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 21 Sep 2020 17:43:38 +0200 Subject: [PATCH 078/411] C#: Extract constant value of enum member equal clauses --- .../Entities/Field.cs | 28 ++++++++++++++----- .../signanalysis/MissingSign.expected | 1 - .../signanalysis/SignAnalysis.expected | 3 ++ .../definitions/PrintAst.expected | 8 ++++-- .../test/library-tests/enums/Enums11.expected | 5 ++++ csharp/ql/test/library-tests/enums/Enums11.ql | 9 ++++-- .../library-tests/enums/PrintAst.expected | 27 ++++++++++++++---- csharp/ql/test/library-tests/enums/enums.cs | 2 +- 8 files changed, 64 insertions(+), 19 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs index 5f881338200..896614840ab 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs @@ -68,13 +68,12 @@ namespace Semmle.Extraction.CSharp.Entities Context.PopulateLater(() => { var loc = Context.Create(initializer.GetLocation()); - var simpleAssignExpr = new Expression(new ExpressionInfo(Context, Type, loc, ExprKind.SIMPLE_ASSIGN, this, child++, false, null)); - Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer.Initializer.Value, simpleAssignExpr, 0)); - var access = new Expression(new ExpressionInfo(Context, Type, Location, ExprKind.FIELD_ACCESS, simpleAssignExpr, 1, false, null)); - trapFile.expr_access(access, this); + + var fieldAccess = AddInitializerAssignment(trapFile, initializer.Initializer.Value, loc, null, ref child); + if (!symbol.IsStatic) { - This.CreateImplicit(Context, Entities.Type.Create(Context, symbol.ContainingType), Location, access, -1); + This.CreateImplicit(Context, Entities.Type.Create(Context, symbol.ContainingType), Location, fieldAccess, -1); } }); } @@ -85,8 +84,13 @@ namespace Semmle.Extraction.CSharp.Entities Where(n => n.EqualsValue != null)) { // Mark fields that have explicit initializers. - var expr = new Expression(new ExpressionInfo(Context, Type, Context.Create(initializer.EqualsValue.Value.FixedLocation()), Kinds.ExprKind.FIELD_ACCESS, this, child++, false, null)); - trapFile.expr_access(expr, this); + var constValue = symbol.HasConstantValue + ? Expression.ValueAsString(symbol.ConstantValue) + : null; + + var loc = Context.Create(initializer.GetLocation()); + + AddInitializerAssignment(trapFile, initializer.EqualsValue.Value, loc, constValue, ref child); } if (IsSourceDeclaration) @@ -96,6 +100,16 @@ namespace Semmle.Extraction.CSharp.Entities TypeMention.Create(Context, syntax.Type, this, Type); } + private Expression AddInitializerAssignment(TextWriter trapFile, ExpressionSyntax initializer, Extraction.Entities.Location loc, + string constValue, ref int child) + { + var simpleAssignExpr = new Expression(new ExpressionInfo(Context, Type, loc, ExprKind.SIMPLE_ASSIGN, this, child++, false, constValue)); + Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer, simpleAssignExpr, 0)); + var access = new Expression(new ExpressionInfo(Context, Type, Location, ExprKind.FIELD_ACCESS, simpleAssignExpr, 1, false, constValue)); + trapFile.expr_access(access, this); + return access; + } + readonly Lazy type; public AnnotatedType Type => type.Value; diff --git a/csharp/ql/test/library-tests/dataflow/signanalysis/MissingSign.expected b/csharp/ql/test/library-tests/dataflow/signanalysis/MissingSign.expected index 2fd751f77e0..e69de29bb2d 100644 --- a/csharp/ql/test/library-tests/dataflow/signanalysis/MissingSign.expected +++ b/csharp/ql/test/library-tests/dataflow/signanalysis/MissingSign.expected @@ -1 +0,0 @@ -| SignAnalysis.cs:428:23:428:24 | access to constant A | diff --git a/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.expected b/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.expected index 31220df1a3c..ec33fec9374 100644 --- a/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.expected +++ b/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.expected @@ -211,6 +211,9 @@ | SignAnalysis.cs:414:13:414:13 | access to local variable i | strictlyPositive | | SignAnalysis.cs:415:31:415:31 | access to local variable i | strictlyPositive | | SignAnalysis.cs:424:31:424:31 | access to local variable x | strictlyNegative | +| SignAnalysis.cs:428:19:428:19 | access to constant A | strictlyPositive | +| SignAnalysis.cs:428:19:428:24 | ... = ... | strictlyPositive | +| SignAnalysis.cs:428:23:428:24 | 12 | strictlyPositive | | SignAnalysis.cs:434:38:434:38 | access to local variable i | strictlyNegative | | SignAnalysis.cs:443:38:443:38 | access to local variable x | strictlyNegative | | SignAnalysis.cs:446:31:446:32 | 10 | strictlyPositive | diff --git a/csharp/ql/test/library-tests/definitions/PrintAst.expected b/csharp/ql/test/library-tests/definitions/PrintAst.expected index 18c13fe61bd..5543a3363d5 100644 --- a/csharp/ql/test/library-tests/definitions/PrintAst.expected +++ b/csharp/ql/test/library-tests/definitions/PrintAst.expected @@ -8,9 +8,13 @@ definitions.cs: # 9| 4: [BlockStmt] {...} # 13| 2: [Enum] Enumeration # 15| 5: [Field] e1 -# 15| 1: [MemberConstantAccess] access to constant e1 +# 15| 1: [AssignExpr] ... = ... +# 15| 0: [IntLiteral] 1 +# 15| 1: [MemberConstantAccess] access to constant e1 # 15| 6: [Field] e2 -# 15| 1: [MemberConstantAccess] access to constant e2 +# 15| 1: [AssignExpr] ... = ... +# 15| 0: [IntLiteral] 2 +# 15| 1: [MemberConstantAccess] access to constant e2 # 15| 7: [Field] e3 # 18| 3: [Class] C1 # 20| 4: [InstanceConstructor] C1 diff --git a/csharp/ql/test/library-tests/enums/Enums11.expected b/csharp/ql/test/library-tests/enums/Enums11.expected index e69de29bb2d..715beb400ff 100644 --- a/csharp/ql/test/library-tests/enums/Enums11.expected +++ b/csharp/ql/test/library-tests/enums/Enums11.expected @@ -0,0 +1,5 @@ +| enums.cs:28:18:28:18 | (...) ... | 1 | +| enums.cs:29:20:29:20 | (...) ... | 2 | +| enums.cs:30:20:30:20 | (...) ... | 4 | +| enums.cs:38:17:38:18 | 10 | 10 | +| enums.cs:40:23:40:32 | ... + ... | 11 | diff --git a/csharp/ql/test/library-tests/enums/Enums11.ql b/csharp/ql/test/library-tests/enums/Enums11.ql index cf808bf4f29..36b2c005a21 100644 --- a/csharp/ql/test/library-tests/enums/Enums11.ql +++ b/csharp/ql/test/library-tests/enums/Enums11.ql @@ -4,6 +4,9 @@ import csharp -from FieldAccess fa -where fa.getParent().(Field).getDeclaringType() instanceof Enum -select fa, fa.getValue() +from Expr e +where + exists(Assignment a | a.getRValue() = e | + a.getParent().(Field).getDeclaringType() instanceof Enum + ) +select e, e.getValue() diff --git a/csharp/ql/test/library-tests/enums/PrintAst.expected b/csharp/ql/test/library-tests/enums/PrintAst.expected index 05101b6ca19..446b4c01856 100644 --- a/csharp/ql/test/library-tests/enums/PrintAst.expected +++ b/csharp/ql/test/library-tests/enums/PrintAst.expected @@ -11,18 +11,35 @@ enums.cs: # 23| 3: [Enum] E # 25| 4: [Enum] ValueColor # 28| 5: [Field] OneRed -# 28| 1: [MemberConstantAccess] access to constant OneRed +# 28| 1: [AssignExpr] ... = ... +# 28| 0: [CastExpr] (...) ... +# 28| 0: [IntLiteral] 1 +# 28| 1: [MemberConstantAccess] access to constant OneRed # 29| 6: [Field] TwoGreen -# 29| 1: [MemberConstantAccess] access to constant TwoGreen +# 29| 1: [AssignExpr] ... = ... +# 29| 0: [CastExpr] (...) ... +# 29| 0: [IntLiteral] 2 +# 29| 1: [MemberConstantAccess] access to constant TwoGreen # 30| 7: [Field] FourBlue -# 30| 1: [MemberConstantAccess] access to constant FourBlue +# 30| 1: [AssignExpr] ... = ... +# 30| 0: [CastExpr] (...) ... +# 30| 0: [IntLiteral] 4 +# 30| 1: [MemberConstantAccess] access to constant FourBlue # 34| 5: [Enum] SparseColor # 37| 5: [Field] Red # 38| 6: [Field] Green -# 38| 1: [MemberConstantAccess] access to constant Green +# 38| 1: [AssignExpr] ... = ... +# 38| 0: [IntLiteral] 10 +# 38| 1: [MemberConstantAccess] access to constant Green # 39| 7: [Field] Blue # 40| 8: [Field] AnotherBlue -# 40| 1: [MemberConstantAccess] access to constant AnotherBlue +# 40| 1: [AssignExpr] ... = ... +# 40| 0: [AddExpr] ... + ... +# 40| 0: [CastExpr] (...) ... +# 40| 0: [MemberConstantAccess] access to constant Blue +# 40| 1: [CastExpr] (...) ... +# 40| 0: [MemberConstantAccess] access to constant Red +# 40| 1: [MemberConstantAccess] access to constant AnotherBlue # 44| 6: [Class] Test # 47| 5: [Method] Main # 48| 4: [BlockStmt] {...} diff --git a/csharp/ql/test/library-tests/enums/enums.cs b/csharp/ql/test/library-tests/enums/enums.cs index df7df79c066..784d4f64114 100644 --- a/csharp/ql/test/library-tests/enums/enums.cs +++ b/csharp/ql/test/library-tests/enums/enums.cs @@ -37,7 +37,7 @@ namespace Enums Red, Green = 10, Blue, - AnotherBlue = Blue + AnotherBlue = Blue + Red } From 3577b27f49ce6b38453d1a7413c70e87356aac57 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 25 Sep 2020 09:58:08 +0200 Subject: [PATCH 079/411] Fix to not report on enum member initialization --- csharp/ql/src/Likely Bugs/SelfAssignment.ql | 4 +++- .../query-tests/Likely Bugs/SelfAssignment/selfassigns.cs | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/csharp/ql/src/Likely Bugs/SelfAssignment.ql b/csharp/ql/src/Likely Bugs/SelfAssignment.ql index 0f0e23e8629..01c5d904cd4 100644 --- a/csharp/ql/src/Likely Bugs/SelfAssignment.ql +++ b/csharp/ql/src/Likely Bugs/SelfAssignment.ql @@ -20,7 +20,9 @@ class StructuralComparisonConfig extends StructuralComparisonConfiguration { exists(AssignExpr ae | // Member initializers are never self-assignments, in particular // not initializers such as `new C { F = F };` - not ae instanceof MemberInitializer + not ae instanceof MemberInitializer and + // Enum field initializers are never self assignments. `enum E { A = 42 }` + not ae.getParent().(Field).getDeclaringType() instanceof Enum | ae.getLValue() = x and ae.getRValue() = y diff --git a/csharp/ql/test/query-tests/Likely Bugs/SelfAssignment/selfassigns.cs b/csharp/ql/test/query-tests/Likely Bugs/SelfAssignment/selfassigns.cs index 3553606275f..6d1387a5e1d 100644 --- a/csharp/ql/test/query-tests/Likely Bugs/SelfAssignment/selfassigns.cs +++ b/csharp/ql/test/query-tests/Likely Bugs/SelfAssignment/selfassigns.cs @@ -82,4 +82,11 @@ class SelfAssigns : Super this.Self.Self.Self.StringProp = Self.Self.Self.StringProp; intArray[1] = this.intArray[1 + 0]; } + + enum Enum + { + X = 42, + Y = 100, + Z + } } From a635503be0987f4b3148f12f97cc093cd9596b54 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 25 Sep 2020 10:57:02 +0200 Subject: [PATCH 080/411] Add test cases to UselessCastToSelf --- .../UselessCastToSelf/UselessCastToSelf.cs | 9 +++++++++ .../UselessCastToSelf/UselessCastToSelf.expected | 2 ++ 2 files changed, 11 insertions(+) diff --git a/csharp/ql/test/query-tests/Language Abuse/UselessCastToSelf/UselessCastToSelf.cs b/csharp/ql/test/query-tests/Language Abuse/UselessCastToSelf/UselessCastToSelf.cs index 47df3468b4a..e36143d6b40 100644 --- a/csharp/ql/test/query-tests/Language Abuse/UselessCastToSelf/UselessCastToSelf.cs +++ b/csharp/ql/test/query-tests/Language Abuse/UselessCastToSelf/UselessCastToSelf.cs @@ -18,4 +18,13 @@ class Test var good6 = (Action)(delegate (int x) { }); var good7 = (Action)((int x) => { }); } + + enum Enum + { + A = 2, + B = 1 | A, + C = 1 | (int)A, // BAD + D = 9 | (32 << A), + E = 9 | (32 << (int)A) // BAD + } } diff --git a/csharp/ql/test/query-tests/Language Abuse/UselessCastToSelf/UselessCastToSelf.expected b/csharp/ql/test/query-tests/Language Abuse/UselessCastToSelf/UselessCastToSelf.expected index 28dcbbb9f6e..f5c4b708253 100644 --- a/csharp/ql/test/query-tests/Language Abuse/UselessCastToSelf/UselessCastToSelf.expected +++ b/csharp/ql/test/query-tests/Language Abuse/UselessCastToSelf/UselessCastToSelf.expected @@ -1,3 +1,5 @@ | UselessCastToSelf.cs:8:20:8:25 | (...) ... | This cast is redundant because the expression already has type Int32. | | UselessCastToSelf.cs:9:20:9:29 | (...) ... | This cast is redundant because the expression already has type Test. | | UselessCastToSelf.cs:10:20:10:31 | ... as ... | This cast is redundant because the expression already has type Test. | +| UselessCastToSelf.cs:26:17:26:22 | (...) ... | This cast is redundant because the expression already has type Int32. | +| UselessCastToSelf.cs:28:24:28:29 | (...) ... | This cast is redundant because the expression already has type Int32. | From 060720aae7d460627378359763cde591b518c5e8 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 24 Sep 2020 18:16:49 +0200 Subject: [PATCH 081/411] Python: Add tests for all SystemCommandExecution from stdlib Overall idea is that `test/experimental/meta/ConceptsTest.qll` will set up inline expectation tests for all the classes defined in `Concepts.qll`, so any time you model a new instance of Concepts, you simply just import that file. That makes the tests a little verbose, but allows us to share test-setup between all the different frameworks we model. Note that since the definitions of SystemCommandExecution subclasses are scattered across multieple framework modeling qll files, it think it makes the most sense to have the tests for each framework in one location. I'm not 100% convinced about if this is the right choice or not (especially when we want to write tests for sanitizers), but for now I'm going to try it out at least. --- .../frameworks/stdlib/ConceptsTest.expected | 4 + .../frameworks/stdlib/ConceptsTest.ql | 2 + .../stdlib/SystemCommandExecution.py | 122 ++++++++++++++++++ .../test/experimental/meta/ConceptsTest.qll | 33 +++++ 4 files changed, 161 insertions(+) create mode 100644 python/ql/test/experimental/library-tests/frameworks/stdlib/ConceptsTest.expected create mode 100644 python/ql/test/experimental/library-tests/frameworks/stdlib/ConceptsTest.ql create mode 100644 python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py create mode 100644 python/ql/test/experimental/meta/ConceptsTest.qll diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/ConceptsTest.expected b/python/ql/test/experimental/library-tests/frameworks/stdlib/ConceptsTest.expected new file mode 100644 index 00000000000..a92521c154c --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/ConceptsTest.expected @@ -0,0 +1,4 @@ +| SystemCommandExecution.py:16:10:16:21 | ControlFlowNode for Str | Fixed false negative:SystemCommandExecution_getCommand="cmd1; cmd2" | +| SystemCommandExecution.py:17:11:17:22 | ControlFlowNode for Str | Fixed false negative:SystemCommandExecution_getCommand="cmd1; cmd2" | +| SystemCommandExecution.py:27:11:27:22 | ControlFlowNode for Str | Fixed false negative:SystemCommandExecution_getCommand="cmd1; cmd2" | +| SystemCommandExecution.py:28:12:28:23 | ControlFlowNode for Str | Fixed false negative:SystemCommandExecution_getCommand="cmd1; cmd2" | diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/ConceptsTest.ql b/python/ql/test/experimental/library-tests/frameworks/stdlib/ConceptsTest.ql new file mode 100644 index 00000000000..b557a0bccb6 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/ConceptsTest.ql @@ -0,0 +1,2 @@ +import python +import experimental.meta.ConceptsTest diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py b/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py new file mode 100644 index 00000000000..03f520f2690 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py @@ -0,0 +1,122 @@ +# Note: Some of these commands will technically not allow an attacker to execute +# arbitrary system commands, but only specify the program to be executed. The general +# consensus was that even this is still a high security risk, so we also treat them as +# system command executions. +# +# As an example, executing `subprocess.Popen(["rm -rf /"])` will result in +# `FileNotFoundError: [Errno 2] No such file or directory: 'rm -rf /'` + +######################################## + + +import os + +# can't use a string literal with spaces in the tags of an InlineExpectationsTest, so using variables :| + +os.popen("cmd1; cmd2") # $f-:SystemCommandExecution_getCommand="cmd1; cmd2" +os.system("cmd1; cmd2") # $f-:SystemCommandExecution_getCommand="cmd1; cmd2" + + +def os_members(): + # hmm, it's kinda annoying to check that we handle this import correctly for + # everything. It's quite useful since I messed it up initially and didn't have a + # test for it, but in the long run it's just cumbersome to duplicate all the tests + # :| + from os import popen, system + + popen("cmd1; cmd2") # $f-:SystemCommandExecution_getCommand="cmd1; cmd2" + system("cmd1; cmd2") # $f-:SystemCommandExecution_getCommand="cmd1; cmd2" + + +######################################## +# https://docs.python.org/3.8/library/os.html#os.execv +# +# VS Code extension will ignore rest of program if encountering one of these, which we +# don't want. We could use `if False`, but just to be 100% sure we don't do anything too +# clever in our analysis that discards that code, I used `if UNKNOWN` instead +if UNKNOWN: + env = {"FOO": "foo"} + os.execl("executable", "", "arg0") # $f-:SystemCommandExecution_getCommand="executable" + os.execle("executable", "", "arg0", env) # $f-:SystemCommandExecution_getCommand="executable" + os.execlp("executable", "", "arg0") # $f-:SystemCommandExecution_getCommand="executable" + os.execlpe("executable", "", "arg0", env) # $f-:SystemCommandExecution_getCommand="executable" + os.execv("executable", ["", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" + os.execve("executable", ["", "arg0"], env) # $f-:SystemCommandExecution_getCommand="executable" + os.execvp("executable", ["", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" + os.execvpe("executable", ["", "arg0"], env) # $f-:SystemCommandExecution_getCommand="executable" + + +######################################## +# https://docs.python.org/3.8/library/os.html#os.spawnl +env = {"FOO": "foo"} +os.spawnl(os.P_WAIT, "executable", "", "arg0") # $f-:SystemCommandExecution_getCommand="executable" +os.spawnle(os.P_WAIT, "executable", "", "arg0", env) # $f-:SystemCommandExecution_getCommand="executable" +os.spawnlp(os.P_WAIT, "executable", "", "arg0") # $f-:SystemCommandExecution_getCommand="executable" +os.spawnlpe(os.P_WAIT, "executable", "", "arg0", env) # $f-:SystemCommandExecution_getCommand="executable" +os.spawnv(os.P_WAIT, "executable", ["", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" +os.spawnve(os.P_WAIT, "executable", ["", "arg0"], env) # $f-:SystemCommandExecution_getCommand="executable" +os.spawnvp(os.P_WAIT, "executable", ["", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" +os.spawnvpe(os.P_WAIT, "executable", ["", "arg0"], env) # $f-:SystemCommandExecution_getCommand="executable" + +# Added in Python 3.8 +os.posix_spawn("executable", ["", "arg0"], env) # $f-:SystemCommandExecution_getCommand="executable" +os.posix_spawnp("executable", ["", "arg0"], env) # $f-:SystemCommandExecution_getCommand="executable" + +######################################## + +import subprocess + +subprocess.Popen("cmd1; cmd2", shell=True) # $f-:SystemCommandExecution_getCommand="cmd1; cmd2" +subprocess.Popen("cmd1; cmd2", shell="truthy string") # $f-:SystemCommandExecution_getCommand="cmd1; cmd2" +subprocess.Popen(["cmd1; cmd2", "shell-arg"], shell=True) # $f-:SystemCommandExecution_getCommand="cmd1; cmd2" +subprocess.Popen("cmd1; cmd2", shell=True, executable="/bin/bash") # $f-:SystemCommandExecution_getCommand="cmd1; cmd2" + +subprocess.Popen("executable") # $f-:SystemCommandExecution_getCommand="executable" +subprocess.Popen(["executable", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" +subprocess.Popen("", executable="executable") # $f-:SystemCommandExecution_getCommand="executable" +subprocess.Popen(["", "arg0"], executable="executable") # $f-:SystemCommandExecution_getCommand="executable" + +# call/check_call/check_output/run all work like Popen from a command execution point of view +subprocess.call(["executable", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" +subprocess.check_call(["executable", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" +subprocess.check_output(["executable", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" +subprocess.run(["executable", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" + + +######################################## +# actively using known shell as the executable + +subprocess.Popen(["/bin/sh", "-c", "vuln"]) # $f-:SystemCommandExecution_getCommand="/bin/sh",$f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["/bin/bash", "-c", "vuln"]) # $f-:SystemCommandExecution_getCommand="/bin/bash",$f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["/bin/dash", "-c", "vuln"]) # $f-:SystemCommandExecution_getCommand="/bin/dash",$f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["/bin/zsh", "-c", "vuln"]) # $f-:SystemCommandExecution_getCommand="/bin/zsh",$f-:SystemCommandExecution_getCommand="vuln" + +subprocess.Popen(["sh", "-c", "vuln"]) # $f-:SystemCommandExecution_getCommand="sh",$f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["bash", "-c", "vuln"]) # $f-:SystemCommandExecution_getCommand="bash",$f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["dash", "-c", "vuln"]) # $f-:SystemCommandExecution_getCommand="dash",$f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["zsh", "-c", "vuln"]) # $f-:SystemCommandExecution_getCommand="zsh",$f-:SystemCommandExecution_getCommand="vuln" + +# Check that we don't consider ANY argument a command injection sink +subprocess.Popen(["sh", "/bin/python"]) # $f-:SystemCommandExecution_getCommand="sh" + +subprocess.Popen(["cmd.exe", "/c", "vuln"]) # $f-:SystemCommandExecution_getCommand="cmd.exe",$f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["cmd.exe", "/C", "vuln"]) # $f-:SystemCommandExecution_getCommand="cmd.exe",$f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["cmd", "/c", "vuln"]) # $f-:SystemCommandExecution_getCommand="cmd",$f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["cmd", "/C", "vuln"]) # $f-:SystemCommandExecution_getCommand="cmd",$f-:SystemCommandExecution_getCommand="vuln" + + +################################################################################ +# Taint related + +import shlex + +cmd = shlex.join(["echo", tainted]) +args = shlex.split(tainted) + +# will handle tainted = 'foo; rm -rf /' +safe_cmd = "ls {}".format(shlex.quote(tainted)) + +# not how you are supposed to use shlex.quote +wrong_use = shlex.quote("ls {}".format(tainted)) +# still dangerous, for example +cmd = "sh -c " + wrong_use diff --git a/python/ql/test/experimental/meta/ConceptsTest.qll b/python/ql/test/experimental/meta/ConceptsTest.qll new file mode 100644 index 00000000000..89b490fb7d4 --- /dev/null +++ b/python/ql/test/experimental/meta/ConceptsTest.qll @@ -0,0 +1,33 @@ +import python +import experimental.dataflow.DataFlow +import experimental.semmle.python.Concepts +import TestUtilities.InlineExpectationsTest + +string value_from_expr(Expr e) { + // TODO: This one is starting to look like `repr` predicate from TestTaintLib + result = + e.(StrConst).getPrefix() + e.(StrConst).getText() + + e.(StrConst).getPrefix().regexpReplaceAll("[a-zA-Z]+", "") + or + result = e.(Name).getId() + or + not e instanceof StrConst and + not e instanceof Name and + result = e.toString() +} + +class SystemCommandExecutionTest extends InlineExpectationsTest { + SystemCommandExecutionTest() { this = "SystemCommandExecutionTest" } + + override string getARelevantTag() { result = "SystemCommandExecution_getCommand" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(SystemCommandExecution sce, DataFlow::Node command | + command = sce.getCommand() and + location = command.getLocation() and + element = command.toString() and + value = value_from_expr(command.asExpr()) and + tag = "SystemCommandExecution_getCommand" + ) + } +} From c440fd0c09eb43d80be492329bc81ae57c773804 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 24 Sep 2020 18:24:03 +0200 Subject: [PATCH 082/411] Python: Adjust expectations for system command executions I mostly did this to show my reviewers that the tests actually run and do something ;) --- .../library-tests/frameworks/stdlib/ConceptsTest.expected | 4 ---- .../frameworks/stdlib/SystemCommandExecution.py | 8 ++++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/ConceptsTest.expected b/python/ql/test/experimental/library-tests/frameworks/stdlib/ConceptsTest.expected index a92521c154c..e69de29bb2d 100644 --- a/python/ql/test/experimental/library-tests/frameworks/stdlib/ConceptsTest.expected +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/ConceptsTest.expected @@ -1,4 +0,0 @@ -| SystemCommandExecution.py:16:10:16:21 | ControlFlowNode for Str | Fixed false negative:SystemCommandExecution_getCommand="cmd1; cmd2" | -| SystemCommandExecution.py:17:11:17:22 | ControlFlowNode for Str | Fixed false negative:SystemCommandExecution_getCommand="cmd1; cmd2" | -| SystemCommandExecution.py:27:11:27:22 | ControlFlowNode for Str | Fixed false negative:SystemCommandExecution_getCommand="cmd1; cmd2" | -| SystemCommandExecution.py:28:12:28:23 | ControlFlowNode for Str | Fixed false negative:SystemCommandExecution_getCommand="cmd1; cmd2" | diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py b/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py index 03f520f2690..93f29787dd2 100644 --- a/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py @@ -13,8 +13,8 @@ import os # can't use a string literal with spaces in the tags of an InlineExpectationsTest, so using variables :| -os.popen("cmd1; cmd2") # $f-:SystemCommandExecution_getCommand="cmd1; cmd2" -os.system("cmd1; cmd2") # $f-:SystemCommandExecution_getCommand="cmd1; cmd2" +os.popen("cmd1; cmd2") # $SystemCommandExecution_getCommand="cmd1; cmd2" +os.system("cmd1; cmd2") # $SystemCommandExecution_getCommand="cmd1; cmd2" def os_members(): @@ -24,8 +24,8 @@ def os_members(): # :| from os import popen, system - popen("cmd1; cmd2") # $f-:SystemCommandExecution_getCommand="cmd1; cmd2" - system("cmd1; cmd2") # $f-:SystemCommandExecution_getCommand="cmd1; cmd2" + popen("cmd1; cmd2") # $SystemCommandExecution_getCommand="cmd1; cmd2" + system("cmd1; cmd2") # $SystemCommandExecution_getCommand="cmd1; cmd2" ######################################## From 62dc0dd2632fad4c5f77225d6fa0e554d1b19073 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 24 Sep 2020 18:40:35 +0200 Subject: [PATCH 083/411] Python: Model os.exec* os.spawn* and os.posix_spawn* I also had to exclude the inline expectation tests from files outside the test repo. --- .../semmle/python/frameworks/Stdlib.qll | 103 +++++++++++++----- .../stdlib/SystemCommandExecution.py | 38 +++---- .../test/experimental/meta/ConceptsTest.qll | 1 + 3 files changed, 97 insertions(+), 45 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 7587e9187b2..2c7444fd08d 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -10,7 +10,7 @@ private import experimental.semmle.python.Concepts private module Stdlib { /** Gets a reference to the `os` module. */ - DataFlow::Node os(DataFlow::TypeTracker t) { + private DataFlow::Node os(DataFlow::TypeTracker t) { t.start() and result = DataFlow::importModule("os") or @@ -20,34 +20,38 @@ private module Stdlib { /** Gets a reference to the `os` module. */ DataFlow::Node os() { result = os(DataFlow::TypeTracker::end()) } - module os { - /** Gets a reference to the `os.system` function. */ - DataFlow::Node system(DataFlow::TypeTracker t) { + /** + * Gets a reference to the attribute `attr_name` of the `os` module. + * WARNING: Only holds for a few predefined attributes. + * + * For example, using `attr_name = "system"` will get all uses of `os.system`. + */ + private DataFlow::Node os_attr(string attr_name, DataFlow::TypeTracker t) { + attr_name in ["system", "popen", + // exec + "execl", "execle", "execlp", "execlpe", "execv", "execve", "execvp", "execvpe", + // spawn + "spawnl", "spawnle", "spawnlp", "spawnlpe", "spawnv", "spawnve", "spawnvp", "spawnvpe", + "posix_spawn", "posix_spawnp"] and + ( t.start() and - result = DataFlow::importMember("os", "system") + result = DataFlow::importMember("os", attr_name) or - t.startInAttr("system") and + t.startInAttr(attr_name) and result = os() or - exists(DataFlow::TypeTracker t2 | result = os::system(t2).track(t2, t)) - } + exists(DataFlow::TypeTracker t2 | result = os_attr(attr_name, t2).track(t2, t)) + ) + } - /** Gets a reference to the `os.system` function. */ - DataFlow::Node system() { result = os::system(DataFlow::TypeTracker::end()) } - - /** Gets a reference to the `os.popen` function. */ - DataFlow::Node popen(DataFlow::TypeTracker t) { - t.start() and - result = DataFlow::importMember("os", "popen") - or - t.startInAttr("popen") and - result = os() - or - exists(DataFlow::TypeTracker t2 | result = os::popen(t2).track(t2, t)) - } - - /** Gets a reference to the `os.popen` function. */ - DataFlow::Node popen() { result = os::popen(DataFlow::TypeTracker::end()) } + /** + * Gets a reference to the attribute `attr_name` of the `os` module. + * WARNING: Only holds for a few predefined attributes. + * + * For example, using `"system"` will get all uses of `os.system`. + */ + private DataFlow::Node os_attr(string attr_name) { + result = os_attr(attr_name, DataFlow::TypeTracker::end()) } /** @@ -55,7 +59,7 @@ private module Stdlib { * See https://docs.python.org/3/library/os.html#os.system */ private class OsSystemCall extends SystemCommandExecution::Range { - OsSystemCall() { this.asCfgNode().(CallNode).getFunction() = os::system().asCfgNode() } + OsSystemCall() { this.asCfgNode().(CallNode).getFunction() = os_attr("system").asCfgNode() } override DataFlow::Node getCommand() { result.asCfgNode() = this.asCfgNode().(CallNode).getArg(0) @@ -67,7 +71,54 @@ private module Stdlib { * See https://docs.python.org/3/library/os.html#os.popen */ private class OsPopenCall extends SystemCommandExecution::Range { - OsPopenCall() { this.asCfgNode().(CallNode).getFunction() = os::popen().asCfgNode() } + OsPopenCall() { this.asCfgNode().(CallNode).getFunction() = os_attr("popen").asCfgNode() } + + override DataFlow::Node getCommand() { + result.asCfgNode() = this.asCfgNode().(CallNode).getArg(0) + } + } + + /** + * A call to any of the `os.exec*` functions + * See https://docs.python.org/3.8/library/os.html#os.execl + */ + private class OsExecCall extends SystemCommandExecution::Range { + OsExecCall() { + this.asCfgNode().(CallNode).getFunction() = + os_attr(["execl", "execle", "execlp", "execlpe", "execv", "execve", "execvp", "execvpe"]) + .asCfgNode() + } + + override DataFlow::Node getCommand() { + result.asCfgNode() = this.asCfgNode().(CallNode).getArg(0) + } + } + + /** + * A call to any of the `os.spawn*` functions + * See https://docs.python.org/3.8/library/os.html#os.spawnl + */ + private class OsSpawnCall extends SystemCommandExecution::Range { + OsSpawnCall() { + this.asCfgNode().(CallNode).getFunction() = + os_attr(["spawnl", "spawnle", "spawnlp", "spawnlpe", "spawnv", "spawnve", "spawnvp", + "spawnvpe"]).asCfgNode() + } + + override DataFlow::Node getCommand() { + result.asCfgNode() = this.asCfgNode().(CallNode).getArg(1) + } + } + + /** + * A call to any of the `os.posix_spawn*` functions + * See https://docs.python.org/3.8/library/os.html#os.posix_spawn + */ + private class OsPosixSpawnCall extends SystemCommandExecution::Range { + OsPosixSpawnCall() { + this.asCfgNode().(CallNode).getFunction() = + os_attr(["posix_spawn", "posix_spawnp"]).asCfgNode() + } override DataFlow::Node getCommand() { result.asCfgNode() = this.asCfgNode().(CallNode).getArg(0) diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py b/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py index 93f29787dd2..458f7dc294e 100644 --- a/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py @@ -29,38 +29,38 @@ def os_members(): ######################################## -# https://docs.python.org/3.8/library/os.html#os.execv +# https://docs.python.org/3.8/library/os.html#os.execl # # VS Code extension will ignore rest of program if encountering one of these, which we # don't want. We could use `if False`, but just to be 100% sure we don't do anything too # clever in our analysis that discards that code, I used `if UNKNOWN` instead if UNKNOWN: env = {"FOO": "foo"} - os.execl("executable", "", "arg0") # $f-:SystemCommandExecution_getCommand="executable" - os.execle("executable", "", "arg0", env) # $f-:SystemCommandExecution_getCommand="executable" - os.execlp("executable", "", "arg0") # $f-:SystemCommandExecution_getCommand="executable" - os.execlpe("executable", "", "arg0", env) # $f-:SystemCommandExecution_getCommand="executable" - os.execv("executable", ["", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" - os.execve("executable", ["", "arg0"], env) # $f-:SystemCommandExecution_getCommand="executable" - os.execvp("executable", ["", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" - os.execvpe("executable", ["", "arg0"], env) # $f-:SystemCommandExecution_getCommand="executable" + os.execl("executable", "", "arg0") # $SystemCommandExecution_getCommand="executable" + os.execle("executable", "", "arg0", env) # $SystemCommandExecution_getCommand="executable" + os.execlp("executable", "", "arg0") # $SystemCommandExecution_getCommand="executable" + os.execlpe("executable", "", "arg0", env) # $SystemCommandExecution_getCommand="executable" + os.execv("executable", ["", "arg0"]) # $SystemCommandExecution_getCommand="executable" + os.execve("executable", ["", "arg0"], env) # $SystemCommandExecution_getCommand="executable" + os.execvp("executable", ["", "arg0"]) # $SystemCommandExecution_getCommand="executable" + os.execvpe("executable", ["", "arg0"], env) # $SystemCommandExecution_getCommand="executable" ######################################## # https://docs.python.org/3.8/library/os.html#os.spawnl env = {"FOO": "foo"} -os.spawnl(os.P_WAIT, "executable", "", "arg0") # $f-:SystemCommandExecution_getCommand="executable" -os.spawnle(os.P_WAIT, "executable", "", "arg0", env) # $f-:SystemCommandExecution_getCommand="executable" -os.spawnlp(os.P_WAIT, "executable", "", "arg0") # $f-:SystemCommandExecution_getCommand="executable" -os.spawnlpe(os.P_WAIT, "executable", "", "arg0", env) # $f-:SystemCommandExecution_getCommand="executable" -os.spawnv(os.P_WAIT, "executable", ["", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" -os.spawnve(os.P_WAIT, "executable", ["", "arg0"], env) # $f-:SystemCommandExecution_getCommand="executable" -os.spawnvp(os.P_WAIT, "executable", ["", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" -os.spawnvpe(os.P_WAIT, "executable", ["", "arg0"], env) # $f-:SystemCommandExecution_getCommand="executable" +os.spawnl(os.P_WAIT, "executable", "", "arg0") # $SystemCommandExecution_getCommand="executable" +os.spawnle(os.P_WAIT, "executable", "", "arg0", env) # $SystemCommandExecution_getCommand="executable" +os.spawnlp(os.P_WAIT, "executable", "", "arg0") # $SystemCommandExecution_getCommand="executable" +os.spawnlpe(os.P_WAIT, "executable", "", "arg0", env) # $SystemCommandExecution_getCommand="executable" +os.spawnv(os.P_WAIT, "executable", ["", "arg0"]) # $SystemCommandExecution_getCommand="executable" +os.spawnve(os.P_WAIT, "executable", ["", "arg0"], env) # $SystemCommandExecution_getCommand="executable" +os.spawnvp(os.P_WAIT, "executable", ["", "arg0"]) # $SystemCommandExecution_getCommand="executable" +os.spawnvpe(os.P_WAIT, "executable", ["", "arg0"], env) # $SystemCommandExecution_getCommand="executable" # Added in Python 3.8 -os.posix_spawn("executable", ["", "arg0"], env) # $f-:SystemCommandExecution_getCommand="executable" -os.posix_spawnp("executable", ["", "arg0"], env) # $f-:SystemCommandExecution_getCommand="executable" +os.posix_spawn("executable", ["", "arg0"], env) # $SystemCommandExecution_getCommand="executable" +os.posix_spawnp("executable", ["", "arg0"], env) # $SystemCommandExecution_getCommand="executable" ######################################## diff --git a/python/ql/test/experimental/meta/ConceptsTest.qll b/python/ql/test/experimental/meta/ConceptsTest.qll index 89b490fb7d4..258cffc694b 100644 --- a/python/ql/test/experimental/meta/ConceptsTest.qll +++ b/python/ql/test/experimental/meta/ConceptsTest.qll @@ -23,6 +23,7 @@ class SystemCommandExecutionTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { exists(SystemCommandExecution sce, DataFlow::Node command | + exists(location.getFile().getRelativePath()) and command = sce.getCommand() and location = command.getLocation() and element = command.toString() and From f7f656418960208d97c25c686466b803e80d0f74 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 28 Sep 2020 11:13:04 +0200 Subject: [PATCH 084/411] Python: Model subprocess.Popen (and helpers) --- .../semmle/python/frameworks/Stdlib.qll | 131 ++++++++++++++++++ .../stdlib/SystemCommandExecution.py | 51 ++++--- 2 files changed, 156 insertions(+), 26 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 2c7444fd08d..a452ecfeb1f 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -9,6 +9,9 @@ private import experimental.dataflow.RemoteFlowSources private import experimental.semmle.python.Concepts private module Stdlib { + // --------------------------------------------------------------------------- + // os + // --------------------------------------------------------------------------- /** Gets a reference to the `os` module. */ private DataFlow::Node os(DataFlow::TypeTracker t) { t.start() and @@ -124,4 +127,132 @@ private module Stdlib { result.asCfgNode() = this.asCfgNode().(CallNode).getArg(0) } } + + // --------------------------------------------------------------------------- + // subprocess + // --------------------------------------------------------------------------- + /** Gets a reference to the `subprocess` module. */ + private DataFlow::Node subprocess(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importModule("subprocess") + or + exists(DataFlow::TypeTracker t2 | result = subprocess(t2).track(t2, t)) + } + + /** Gets a reference to the `subprocess` module. */ + DataFlow::Node subprocess() { result = subprocess(DataFlow::TypeTracker::end()) } + + /** + * Gets a reference to the attribute `attr_name` of the `subprocess` module. + * WARNING: Only holds for a few predefined attributes. + * + * For example, using `attr_name = "Popen"` will get all uses of `subprocess.Popen`. + */ + private DataFlow::Node subprocess_attr(string attr_name, DataFlow::TypeTracker t) { + attr_name in ["Popen", "call", "check_call", "check_output", "run"] and + ( + t.start() and + result = DataFlow::importMember("subprocess", attr_name) + or + t.startInAttr(attr_name) and + result = subprocess() + or + exists(DataFlow::TypeTracker t2 | result = subprocess_attr(attr_name, t2).track(t2, t)) + ) + } + + /** + * Gets a reference to the attribute `attr_name` of the `subprocess` module. + * WARNING: Only holds for a few predefined attributes. + * + * For example, using `attr_name = "Popen"` will get all uses of `subprocess.Popen`. + */ + private DataFlow::Node subprocess_attr(string attr_name) { + result = subprocess_attr(attr_name, DataFlow::TypeTracker::end()) + } + + /** + * A call to `subprocess.Popen` or helper functions (call, check_call, check_output, run) + * See https://docs.python.org/3.8/library/subprocess.html#subprocess.Popen + */ + private class SubprocessPopenCall extends SystemCommandExecution::Range { + CallNode call; + + SubprocessPopenCall() { + call = this.asCfgNode() and + call.getFunction() = + subprocess_attr(["Popen", "call", "check_call", "check_output", "run"]).asCfgNode() + } + + /** Gets the ControlFlowNode for the `args` argument, if any. */ + private ControlFlowNode get_args_arg() { + result = call.getArg(0) + or + result = call.getArgByName("args") + } + + /** Gets the ControlFlowNode for the `shell` argument, if any. */ + private ControlFlowNode get_shell_arg() { + result = call.getArg(8) + or + result = call.getArgByName("shell") + } + + private boolean get_shell_arg_value() { + not exists(this.get_shell_arg()) and + result = false + or + exists(ControlFlowNode shell_arg | shell_arg = this.get_shell_arg() | + result = shell_arg.getNode().(ImmutableLiteral).booleanValue() + or + // TODO: Track the "shell" argument to determine possible values + not shell_arg.getNode() instanceof ImmutableLiteral and + ( + result = true + or + result = false + ) + ) + } + + /** Gets the ControlFlowNode for the `executable` argument, if any. */ + private ControlFlowNode get_executable_arg() { + result = call.getArg(2) + or + result = call.getArgByName("executable") + } + + override DataFlow::Node getCommand() { + // TODO: Track arguments ("args" and "shell") + // TODO: Handle using `args=["sh", "-c", ]` + result.asCfgNode() = this.get_executable_arg() + or + exists(ControlFlowNode arg_args, boolean shell | + arg_args = get_args_arg() and + shell = get_shell_arg_value() + | + // When "executable" argument is set, and "shell" argument is `False`, the + // "args" argument will only be used to set the program name and arguments to + // the program, so we should not consider any of them as command execution. + not ( + exists(this.get_executable_arg()) and + shell = false + ) and + ( + // When the "args" argument is an iterable, first element is the command to + // run, so if we're able to, we only mark the first element as the command + // (and not the arguments to the command). + // + result.asCfgNode() = arg_args.(SequenceNode).getElement(0) + or + // Either the "args" argument is not a sequence (which is valid) or we where + // just not able to figure it out. Simply mark the "args" argument as the + // command. + // + not arg_args instanceof SequenceNode and + result.asCfgNode() = arg_args + ) + ) + } + } } diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py b/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py index 458f7dc294e..ea62564ed9f 100644 --- a/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py @@ -66,44 +66,43 @@ os.posix_spawnp("executable", ["", "arg0"], env) # $SystemCommandExec import subprocess -subprocess.Popen("cmd1; cmd2", shell=True) # $f-:SystemCommandExecution_getCommand="cmd1; cmd2" -subprocess.Popen("cmd1; cmd2", shell="truthy string") # $f-:SystemCommandExecution_getCommand="cmd1; cmd2" -subprocess.Popen(["cmd1; cmd2", "shell-arg"], shell=True) # $f-:SystemCommandExecution_getCommand="cmd1; cmd2" -subprocess.Popen("cmd1; cmd2", shell=True, executable="/bin/bash") # $f-:SystemCommandExecution_getCommand="cmd1; cmd2" +subprocess.Popen("cmd1; cmd2", shell=True) # $SystemCommandExecution_getCommand="cmd1; cmd2" +subprocess.Popen("cmd1; cmd2", shell="truthy string") # $SystemCommandExecution_getCommand="cmd1; cmd2" +subprocess.Popen(["cmd1; cmd2", "shell-arg"], shell=True) # $SystemCommandExecution_getCommand="cmd1; cmd2" +subprocess.Popen("cmd1; cmd2", shell=True, executable="/bin/bash") # $SystemCommandExecution_getCommand="cmd1; cmd2" $SystemCommandExecution_getCommand="/bin/bash" -subprocess.Popen("executable") # $f-:SystemCommandExecution_getCommand="executable" -subprocess.Popen(["executable", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" -subprocess.Popen("", executable="executable") # $f-:SystemCommandExecution_getCommand="executable" -subprocess.Popen(["", "arg0"], executable="executable") # $f-:SystemCommandExecution_getCommand="executable" +subprocess.Popen("executable") # $SystemCommandExecution_getCommand="executable" +subprocess.Popen(["executable", "arg0"]) # $SystemCommandExecution_getCommand="executable" +subprocess.Popen("", executable="executable") # $SystemCommandExecution_getCommand="executable" +subprocess.Popen(["", "arg0"], executable="executable") # $SystemCommandExecution_getCommand="executable" # call/check_call/check_output/run all work like Popen from a command execution point of view -subprocess.call(["executable", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" -subprocess.check_call(["executable", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" -subprocess.check_output(["executable", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" -subprocess.run(["executable", "arg0"]) # $f-:SystemCommandExecution_getCommand="executable" +subprocess.call(["executable", "arg0"]) # $SystemCommandExecution_getCommand="executable" +subprocess.check_call(["executable", "arg0"]) # $SystemCommandExecution_getCommand="executable" +subprocess.check_output(["executable", "arg0"]) # $SystemCommandExecution_getCommand="executable" +subprocess.run(["executable", "arg0"]) # $SystemCommandExecution_getCommand="executable" ######################################## # actively using known shell as the executable -subprocess.Popen(["/bin/sh", "-c", "vuln"]) # $f-:SystemCommandExecution_getCommand="/bin/sh",$f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["/bin/bash", "-c", "vuln"]) # $f-:SystemCommandExecution_getCommand="/bin/bash",$f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["/bin/dash", "-c", "vuln"]) # $f-:SystemCommandExecution_getCommand="/bin/dash",$f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["/bin/zsh", "-c", "vuln"]) # $f-:SystemCommandExecution_getCommand="/bin/zsh",$f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["/bin/sh", "-c", "vuln"]) # $SystemCommandExecution_getCommand="/bin/sh" $f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["/bin/bash", "-c", "vuln"]) # $SystemCommandExecution_getCommand="/bin/bash" $f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["/bin/dash", "-c", "vuln"]) # $SystemCommandExecution_getCommand="/bin/dash" $f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["/bin/zsh", "-c", "vuln"]) # $SystemCommandExecution_getCommand="/bin/zsh" $f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["sh", "-c", "vuln"]) # $f-:SystemCommandExecution_getCommand="sh",$f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["bash", "-c", "vuln"]) # $f-:SystemCommandExecution_getCommand="bash",$f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["dash", "-c", "vuln"]) # $f-:SystemCommandExecution_getCommand="dash",$f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["zsh", "-c", "vuln"]) # $f-:SystemCommandExecution_getCommand="zsh",$f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["sh", "-c", "vuln"]) # $SystemCommandExecution_getCommand="sh" $f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["bash", "-c", "vuln"]) # $SystemCommandExecution_getCommand="bash" $f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["dash", "-c", "vuln"]) # $SystemCommandExecution_getCommand="dash" $f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["zsh", "-c", "vuln"]) # $SystemCommandExecution_getCommand="zsh" $f-:SystemCommandExecution_getCommand="vuln" # Check that we don't consider ANY argument a command injection sink -subprocess.Popen(["sh", "/bin/python"]) # $f-:SystemCommandExecution_getCommand="sh" - -subprocess.Popen(["cmd.exe", "/c", "vuln"]) # $f-:SystemCommandExecution_getCommand="cmd.exe",$f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["cmd.exe", "/C", "vuln"]) # $f-:SystemCommandExecution_getCommand="cmd.exe",$f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["cmd", "/c", "vuln"]) # $f-:SystemCommandExecution_getCommand="cmd",$f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["cmd", "/C", "vuln"]) # $f-:SystemCommandExecution_getCommand="cmd",$f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["sh", "/bin/python"]) # $SystemCommandExecution_getCommand="sh" +subprocess.Popen(["cmd.exe", "/c", "vuln"]) # $SystemCommandExecution_getCommand="cmd.exe" $f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["cmd.exe", "/C", "vuln"]) # $SystemCommandExecution_getCommand="cmd.exe" $f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["cmd", "/c", "vuln"]) # $SystemCommandExecution_getCommand="cmd" $f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["cmd", "/C", "vuln"]) # $SystemCommandExecution_getCommand="cmd" $f-:SystemCommandExecution_getCommand="vuln" ################################################################################ # Taint related From 3af5c720cc552608f1570aeb185dd8be3d39bc2a Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 28 Sep 2020 11:16:34 +0200 Subject: [PATCH 085/411] Python: Add test of more indirect command injection sinks --- .../frameworks/stdlib/SystemCommandExecution.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py b/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py index ea62564ed9f..8e50dcefc6b 100644 --- a/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py @@ -104,6 +104,13 @@ subprocess.Popen(["cmd.exe", "/C", "vuln"]) # $SystemCommandExecution_getComman subprocess.Popen(["cmd", "/c", "vuln"]) # $SystemCommandExecution_getCommand="cmd" $f-:SystemCommandExecution_getCommand="vuln" subprocess.Popen(["cmd", "/C", "vuln"]) # $SystemCommandExecution_getCommand="cmd" $f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["", "-c", "vuln"], executable="/bin/bash") # $SystemCommandExecution_getCommand="/bin/bash" $f-:SystemCommandExecution_getCommand="vuln" + +if UNKNOWN: + os.execl("/bin/sh", "", "-c", "vuln") # $SystemCommandExecution_getCommand="/bin/sh" $f-:SystemCommandExecution_getCommand="vuln" + +os.spawnl(os.P_WAIT, "/bin/sh", "", "-c", "vuln") # $SystemCommandExecution_getCommand="/bin/sh" $f-:SystemCommandExecution_getCommand="vuln" + ################################################################################ # Taint related From 6cb2ca63a6f9e3883c07b1964603e7fa5dd7cf43 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 28 Sep 2020 11:23:06 +0200 Subject: [PATCH 086/411] Python: tests to show modeling is very syntactical --- .../frameworks/stdlib/SystemCommandExecution.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py b/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py index 8e50dcefc6b..8d6b1211614 100644 --- a/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py @@ -111,6 +111,19 @@ if UNKNOWN: os.spawnl(os.P_WAIT, "/bin/sh", "", "-c", "vuln") # $SystemCommandExecution_getCommand="/bin/sh" $f-:SystemCommandExecution_getCommand="vuln" + +######################################## +# Passing arguments by reference + +args = ["/bin/sh", "-c", "vuln"] +subprocess.Popen(args) # $SystemCommandExecution_getCommand=args + +args = "" +use_shell = False +exe = "executable" +subprocess.Popen(args, shell=use_shell, executable=exe) # $f+:SystemCommandExecution_getCommand=args $SystemCommandExecution_getCommand=exe + + ################################################################################ # Taint related From 7609ce2d4718fbfc171e3ddfb4fdcbfb8cbc01c9 Mon Sep 17 00:00:00 2001 From: Nick Rolfe Date: Tue, 4 Aug 2020 18:10:27 +0100 Subject: [PATCH 087/411] C++: accept test changes from extractor frontend upgrade --- .../special_members/generated_copy/functions.expected | 2 -- .../library-tests/syntax-zoo/dataflow-ir-consistency.expected | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/cpp/ql/test/library-tests/special_members/generated_copy/functions.expected b/cpp/ql/test/library-tests/special_members/generated_copy/functions.expected index 2c85514d592..22282641b37 100644 --- a/cpp/ql/test/library-tests/special_members/generated_copy/functions.expected +++ b/cpp/ql/test/library-tests/special_members/generated_copy/functions.expected @@ -78,8 +78,6 @@ | copy.cpp:111:9:111:9 | MoveAssign | deleted | | | copy.cpp:111:9:111:9 | operator= | deleted | | | copy.cpp:113:17:113:25 | operator= | | | -| copy.cpp:120:9:120:9 | OnlyCtor | | | -| copy.cpp:120:9:120:9 | OnlyCtor | | | | copy.cpp:120:9:120:9 | OnlyCtor | deleted | | | copy.cpp:120:9:120:9 | operator= | deleted | | | copy.cpp:126:11:126:19 | operator= | | | diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected index ee50bd638f9..b4175c9e499 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected @@ -539,8 +539,6 @@ uniqueNodeLocation | file://:0:0:0:0 | p#0 | Node should have one location but has 0. | | file://:0:0:0:0 | p#0 | Node should have one location but has 0. | | file://:0:0:0:0 | p#0 | Node should have one location but has 0. | -| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | -| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | | file://:0:0:0:0 | p#1 | Node should have one location but has 0. | | file://:0:0:0:0 | p#1 | Node should have one location but has 0. | | file://:0:0:0:0 | p#1 | Node should have one location but has 0. | @@ -1418,7 +1416,7 @@ uniqueNodeLocation | whilestmt.c:39:6:39:11 | ReturnVoid | Node should have one location but has 4. | | whilestmt.c:39:6:39:11 | SideEffect | Node should have one location but has 4. | missingLocation -| Nodes without location: 36 | +| Nodes without location: 34 | uniqueNodeToString | break_labels.c:2:11:2:11 | i | Node should have one toString but has 2. | | break_labels.c:2:11:2:11 | i | Node should have one toString but has 2. | From c0a67a8d7bff6238805a5a852626d4364d880a2e Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen Date: Mon, 28 Sep 2020 14:27:10 +0200 Subject: [PATCH 088/411] JS: another CWE-20 -> CWE-020 --- .../Security/CWE-020/PostMessageNoOriginCheck.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/experimental/Security/CWE-020/PostMessageNoOriginCheck.qhelp b/javascript/ql/src/experimental/Security/CWE-020/PostMessageNoOriginCheck.qhelp index 742d2824570..b8bcf242b55 100644 --- a/javascript/ql/src/experimental/Security/CWE-020/PostMessageNoOriginCheck.qhelp +++ b/javascript/ql/src/experimental/Security/CWE-020/PostMessageNoOriginCheck.qhelp @@ -31,7 +31,7 @@ Always verify the sender's identity of incoming messages. -
  • CWE-20: Improper Input Validation
  • +
  • CWE-020: Improper Input Validation
  • Window.postMessage()
  • Web-message manipulation
  • The pitfalls of postMessage
  • From 2bbaa4e17374b294f955ae9c895727d9fd5ca352 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 23 Sep 2020 10:40:04 +0200 Subject: [PATCH 089/411] Handle unsigned types in sign analysis (C# and Java) --- .../rangeanalysis/SignAnalysisCommon.qll | 38 +++++++++++-------- .../rangeanalysis/SignAnalysisSpecific.qll | 32 ++++++++++++---- .../dataflow/signanalysis/MissingSign.ql | 1 + .../dataflow/signanalysis/SignAnalysis.cs | 16 +++++++- .../signanalysis/SignAnalysis.expected | 29 ++++++++++++++ .../rangeanalysis/SignAnalysisCommon.qll | 38 +++++++++++-------- .../rangeanalysis/SignAnalysisSpecific.qll | 2 + .../dataflow/sign-analysis/A.java | 5 +++ .../sign-analysis/SignAnalysis.expected | 2 + 9 files changed, 122 insertions(+), 41 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index 66b38433eef..c734e6acb0e 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -245,24 +245,30 @@ Sign ssaDefSign(SsaVariable v) { /** Gets a possible sign for `e`. */ cached Sign exprSign(Expr e) { - result = certainExprSign(e) - or - not exists(certainExprSign(e)) and - ( - unknownSign(e) + exists(Sign s | + s = certainExprSign(e) or - exists(SsaVariable v | getARead(v) = e | result = ssaVariableSign(v, e)) - or - e = - any(VarAccess access | - not exists(SsaVariable v | getARead(v) = access) and - ( - result = fieldSign(getField(access.(FieldAccess))) or - not access instanceof FieldAccess + not exists(certainExprSign(e)) and + ( + unknownSign(e) + or + exists(SsaVariable v | getARead(v) = e | s = ssaVariableSign(v, e)) + or + e = + any(VarAccess access | + not exists(SsaVariable v | getARead(v) = access) and + ( + s = fieldSign(getField(access.(FieldAccess))) or + not access instanceof FieldAccess + ) ) - ) - or - result = specificSubExprSign(e) + or + s = specificSubExprSign(e) + ) + | + if e.getType() instanceof UnsignedNumericType and s = TNeg() + then result = TPos() + else result = s ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index a47434eed0d..813834c3fd8 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -71,14 +71,29 @@ private module Impl { predicate positiveExpression(Expr e) { e instanceof SizeofExpr } - class NumericOrCharType extends Type { - NumericOrCharType() { - this instanceof CharType or - this instanceof IntegralType or - this instanceof FloatingPointType or - this instanceof DecimalType or - this instanceof Enum or - this instanceof PointerType // should be similar to unsigned integers + abstract class NumericOrCharType extends Type { } + + class UnsignedNumericType extends NumericOrCharType { + UnsignedNumericType() { + this instanceof CharType + or + this instanceof UnsignedIntegralType + or + this instanceof PointerType + or + this instanceof Enum and this.(Enum).getUnderlyingType() instanceof UnsignedIntegralType + } + } + + class SignedNumericType extends NumericOrCharType { + SignedNumericType() { + this instanceof SignedIntegralType + or + this instanceof FloatingPointType + or + this instanceof DecimalType + or + this instanceof Enum and this.(Enum).getUnderlyingType() instanceof SignedIntegralType } } @@ -125,6 +140,7 @@ private module Impl { e.getType() instanceof NumericOrCharType and not e = getARead(_) and not e instanceof FieldAccess and + not e instanceof TypeAccess and // The expression types that are listed here are the ones handled in `specificSubExprSign`. // Keep them in sync. not e instanceof AssignExpr and diff --git a/csharp/ql/test/library-tests/dataflow/signanalysis/MissingSign.ql b/csharp/ql/test/library-tests/dataflow/signanalysis/MissingSign.ql index b769f3eff6e..836980829a3 100644 --- a/csharp/ql/test/library-tests/dataflow/signanalysis/MissingSign.ql +++ b/csharp/ql/test/library-tests/dataflow/signanalysis/MissingSign.ql @@ -4,6 +4,7 @@ import semmle.code.csharp.dataflow.SignAnalysis from Expr e where not exists(exprSign(e)) and + not e instanceof TypeAccess and ( e.getType() instanceof CharType or e.getType() instanceof IntegralType or diff --git a/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.cs b/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.cs index 5a2df6428ff..e4f3781b10d 100644 --- a/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.cs +++ b/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.cs @@ -437,7 +437,7 @@ class SignAnalysis unsafe void PointerCast(byte* src, byte* dst) { - var x = (int)(src-dst); + var x = (int)(src - dst); if (x < 0) { System.Console.WriteLine(x); // strictly negative @@ -450,6 +450,20 @@ class SignAnalysis System.Console.WriteLine((int)to); } } + + uint Unsigned() { return 1; } + void UnsignedCheck(int i) + { + long l = Unsigned(); + if (l != 0) + { + System.Console.WriteLine(l); // strictly positive + } + + uint x = (uint)i; + x++; + System.Console.WriteLine(x); // strictly positive + } } // semmle-extractor-options: /r:System.Linq.dll \ No newline at end of file diff --git a/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.expected b/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.expected index 31220df1a3c..ae54331a046 100644 --- a/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.expected +++ b/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.expected @@ -90,6 +90,7 @@ | SignAnalysis.cs:108:13:108:21 | Decimal de = ... | strictlyPositive | | SignAnalysis.cs:108:18:108:21 | 4.2 | strictlyPositive | | SignAnalysis.cs:109:34:109:35 | access to local variable de | strictlyPositive | +| SignAnalysis.cs:110:13:110:13 | access to local variable c | positive | | SignAnalysis.cs:110:13:110:19 | Char c = ... | strictlyPositive | | SignAnalysis.cs:110:17:110:19 | a | strictlyPositive | | SignAnalysis.cs:111:34:111:34 | access to local variable c | strictlyPositive | @@ -162,6 +163,8 @@ | SignAnalysis.cs:306:21:306:22 | -... | strictlyNegative | | SignAnalysis.cs:306:22:306:22 | 1 | strictlyPositive | | SignAnalysis.cs:309:38:309:38 | access to local variable x | strictlyNegative | +| SignAnalysis.cs:315:13:315:15 | access to local variable min | positive | +| SignAnalysis.cs:316:13:316:15 | access to local variable max | positive | | SignAnalysis.cs:316:13:316:31 | Char max = ... | strictlyPositive | | SignAnalysis.cs:316:19:316:31 | access to constant MaxValue | strictlyPositive | | SignAnalysis.cs:317:13:317:23 | Int32 c = ... | strictlyPositive | @@ -193,7 +196,13 @@ | SignAnalysis.cs:342:38:342:38 | access to local variable x | negative | | SignAnalysis.cs:348:62:348:62 | 5 | strictlyPositive | | SignAnalysis.cs:351:38:351:38 | access to local variable i | strictlyNegative | +| SignAnalysis.cs:357:13:357:13 | access to parameter i | positive | +| SignAnalysis.cs:359:38:359:38 | access to parameter i | strictlyPositive | | SignAnalysis.cs:371:38:371:38 | access to local variable y | strictlyNegative | +| SignAnalysis.cs:377:16:377:17 | access to local variable dp | positive | +| SignAnalysis.cs:377:16:377:22 | Single* dp = ... | positive | +| SignAnalysis.cs:377:21:377:22 | &... | positive | +| SignAnalysis.cs:378:18:378:19 | access to local variable dp | positive | | SignAnalysis.cs:381:38:381:38 | access to local variable x | strictlyNegative | | SignAnalysis.cs:385:50:385:99 | access to constant Explicit | strictlyPositive | | SignAnalysis.cs:385:109:385:110 | 15 | strictlyPositive | @@ -212,5 +221,25 @@ | SignAnalysis.cs:415:31:415:31 | access to local variable i | strictlyPositive | | SignAnalysis.cs:424:31:424:31 | access to local variable x | strictlyNegative | | SignAnalysis.cs:434:38:434:38 | access to local variable i | strictlyNegative | +| SignAnalysis.cs:440:23:440:25 | access to parameter src | positive | +| SignAnalysis.cs:440:29:440:31 | access to parameter dst | positive | | SignAnalysis.cs:443:38:443:38 | access to local variable x | strictlyNegative | | SignAnalysis.cs:446:31:446:32 | 10 | strictlyPositive | +| SignAnalysis.cs:448:22:448:23 | access to local variable to | positive | +| SignAnalysis.cs:448:22:448:29 | Byte* to = ... | positive | +| SignAnalysis.cs:448:27:448:29 | (...) ... | positive | +| SignAnalysis.cs:450:38:450:44 | (...) ... | positive | +| SignAnalysis.cs:450:43:450:44 | access to local variable to | positive | +| SignAnalysis.cs:454:30:454:30 | 1 | strictlyPositive | +| SignAnalysis.cs:454:30:454:30 | (...) ... | strictlyPositive | +| SignAnalysis.cs:457:14:457:27 | Int64 l = ... | positive | +| SignAnalysis.cs:457:18:457:27 | (...) ... | positive | +| SignAnalysis.cs:457:18:457:27 | call to method Unsigned | positive | +| SignAnalysis.cs:458:13:458:13 | access to local variable l | positive | +| SignAnalysis.cs:460:38:460:38 | access to local variable l | strictlyPositive | +| SignAnalysis.cs:463:14:463:14 | access to local variable x | positive | +| SignAnalysis.cs:463:14:463:24 | UInt32 x = ... | positive | +| SignAnalysis.cs:463:18:463:24 | (...) ... | positive | +| SignAnalysis.cs:464:9:464:9 | access to local variable x | positive | +| SignAnalysis.cs:464:9:464:11 | ...++ | positive | +| SignAnalysis.cs:465:34:465:34 | access to local variable x | strictlyPositive | diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index 66b38433eef..c734e6acb0e 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -245,24 +245,30 @@ Sign ssaDefSign(SsaVariable v) { /** Gets a possible sign for `e`. */ cached Sign exprSign(Expr e) { - result = certainExprSign(e) - or - not exists(certainExprSign(e)) and - ( - unknownSign(e) + exists(Sign s | + s = certainExprSign(e) or - exists(SsaVariable v | getARead(v) = e | result = ssaVariableSign(v, e)) - or - e = - any(VarAccess access | - not exists(SsaVariable v | getARead(v) = access) and - ( - result = fieldSign(getField(access.(FieldAccess))) or - not access instanceof FieldAccess + not exists(certainExprSign(e)) and + ( + unknownSign(e) + or + exists(SsaVariable v | getARead(v) = e | s = ssaVariableSign(v, e)) + or + e = + any(VarAccess access | + not exists(SsaVariable v | getARead(v) = access) and + ( + s = fieldSign(getField(access.(FieldAccess))) or + not access instanceof FieldAccess + ) ) - ) - or - result = specificSubExprSign(e) + or + s = specificSubExprSign(e) + ) + | + if e.getType() instanceof UnsignedNumericType and s = TNeg() + then result = TPos() + else result = s ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index 16784ccf0ec..8e030c9a53f 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -53,6 +53,8 @@ private module Impl { private import SignAnalysisCommon private import SsaReadPositionCommon + class UnsignedNumericType = CharacterType; + float getNonIntegerValue(Expr e) { result = e.(LongLiteral).getValue().toFloat() or result = e.(FloatingPointLiteral).getValue().toFloat() or diff --git a/java/ql/test/library-tests/dataflow/sign-analysis/A.java b/java/ql/test/library-tests/dataflow/sign-analysis/A.java index 158f4d5a18d..59d7d950334 100644 --- a/java/ql/test/library-tests/dataflow/sign-analysis/A.java +++ b/java/ql/test/library-tests/dataflow/sign-analysis/A.java @@ -9,4 +9,9 @@ public class A { return 0; } + + void unsigned(int x) { + char c = (char)x; + System.out.println(c); // positive + } } diff --git a/java/ql/test/library-tests/dataflow/sign-analysis/SignAnalysis.expected b/java/ql/test/library-tests/dataflow/sign-analysis/SignAnalysis.expected index a1dedfa95b1..4b38711aaa8 100644 --- a/java/ql/test/library-tests/dataflow/sign-analysis/SignAnalysis.expected +++ b/java/ql/test/library-tests/dataflow/sign-analysis/SignAnalysis.expected @@ -1,3 +1,5 @@ | A.java:4:14:4:14 | x | strictlyNegative | | A.java:6:9:6:9 | x | positive | | A.java:7:14:7:14 | y | strictlyPositive | +| A.java:14:14:14:20 | (...)... | positive | +| A.java:15:24:15:24 | c | positive | From bea38fcd074d4e0079f0ee63de1c43bf1e6057f1 Mon Sep 17 00:00:00 2001 From: Joe Date: Mon, 28 Sep 2020 16:25:45 +0100 Subject: [PATCH 090/411] Java: Add taint modelling for string format methods --- .../dataflow/internal/TaintTrackingUtil.qll | 77 ++++++++++++++++++- .../dataflow/taint-format/A.java | 34 ++++++++ .../dataflow/taint-format/options | 1 + .../dataflow/taint-format/test.expected | 24 ++++++ .../dataflow/taint-format/test.ql | 16 ++++ 5 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 java/ql/test/library-tests/dataflow/taint-format/A.java create mode 100644 java/ql/test/library-tests/dataflow/taint-format/options create mode 100644 java/ql/test/library-tests/dataflow/taint-format/test.expected create mode 100644 java/ql/test/library-tests/dataflow/taint-format/test.ql diff --git a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index eaf7c9d26dc..8d551ecdaff 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -13,6 +13,7 @@ private import semmle.code.java.frameworks.spring.SpringHttp private import semmle.code.java.Maps private import semmle.code.java.dataflow.internal.ContainerFlow private import semmle.code.java.frameworks.jackson.JacksonSerializability +private import semmle.code.java.StringFormat /** * Holds if taint can flow from `src` to `sink` in zero or more @@ -124,6 +125,8 @@ private predicate localAdditionalTaintExprStep(Expr src, Expr sink) { stringBuilderStep(src, sink) or serializationStep(src, sink) + or + formatStep(src, sink) } /** @@ -387,6 +390,11 @@ private predicate taintPreservingQualifierToMethod(Method m) { stringlist.getTypeArgument(0) instanceof TypeString ) ) + or + m instanceof StringFormatMethod + or + m.getDeclaringType() instanceof TypeFormatter and + m.hasName("out") } private class StringReplaceMethod extends Method { @@ -446,7 +454,9 @@ private predicate argToMethodStep(Expr tracked, MethodAccess sink) { */ private predicate taintPreservingArgumentToMethod(Method method) { method.getDeclaringType() instanceof TypeString and - (method.hasName("format") or method.hasName("formatted") or method.hasName("join")) + method.hasName("join") + or + method instanceof StringFormatMethod } /** @@ -625,6 +635,21 @@ private predicate argToQualifierStep(Expr tracked, Expr sink) { tracked = ma.getArgument(i) and sink = ma.getQualifier() ) + or + exists(Method m, MethodAccess ma | + taintPreservingArgumentToQualifier(m) and + ma.getMethod() = m and + tracked = ma.getAnArgument() and + sink = ma.getQualifier() + ) +} + +/** + * Holds if `method` is a method that transfers taint from any of its arguments to its qualifier. + */ +private predicate taintPreservingArgumentToQualifier(Method method) { + method instanceof StringFormatMethod and + not method.getDeclaringType() instanceof TypeString } /** @@ -722,6 +747,56 @@ class ObjectOutputStreamVar extends LocalVariableDecl { } } +/** Flow through string formatting. */ +private predicate formatStep(Expr tracked, Expr sink) { + exists(FormatterVar v, VariableAssign def | + def = v.getADef() and + exists(MethodAccess ma, RValue use | + ma.getAnArgument() = tracked and + ma = v.getAFormatMethodAccess() and + use = ma.getQualifier() and + defUsePair(def, use) + ) and + exists(RValue output, ClassInstanceExpr cie | + cie = def.getSource() and + output = cie.getArgument(0) and + adjacentUseUse(output, sink) and + exists(RefType t | output.getType().(RefType).getASourceSupertype*() = t | + t.hasQualifiedName("java.io", "OutputStream") or + t.hasQualifiedName("java.lang", "Appendable") + ) + ) + ) +} + +/** + * A local variable that is assigned a `Formatter`. + * Writing tainted data to such a formatter causes the underlying + * `OutputStream` or `Appenable` to be tainted. + */ +private class FormatterVar extends LocalVariableDecl { + FormatterVar() { + exists(ClassInstanceExpr cie | cie = this.getAnAssignedValue() | + cie.getType() instanceof TypeFormatter + ) + } + + VariableAssign getADef() { + result.getSource().(ClassInstanceExpr).getType() instanceof TypeFormatter and + result.getDestVar() = this + } + + MethodAccess getAFormatMethodAccess() { + result.getQualifier() = getAnAccess() and + result.getMethod().hasName("format") + } +} + +/** The class `java.util.Formatter`. */ +private class TypeFormatter extends Class { + TypeFormatter() { this.hasQualifiedName("java.util", "Formatter") } +} + private import StringBuilderVarModule module StringBuilderVarModule { diff --git a/java/ql/test/library-tests/dataflow/taint-format/A.java b/java/ql/test/library-tests/dataflow/taint-format/A.java new file mode 100644 index 00000000000..c9bb27c8e99 --- /dev/null +++ b/java/ql/test/library-tests/dataflow/taint-format/A.java @@ -0,0 +1,34 @@ +import java.util.Formatter; +import java.lang.StringBuilder; + +class A { + public static String taint() { return "tainted"; } + + public static void test1() { + String bad = taint(); + String good = "hi"; + + bad.formatted(good); + good.formatted("a", bad, "b", good); + String.format("%s%s", bad, good); + } + + public static void test2() { + String bad = taint(); + Formatter f = new Formatter(); + + f.toString(); + f.format("%s", bad); + f.toString(); + } + + public static void test3() { + String bad = taint(); + StringBuilder sb = new StringBuilder(); + Formatter f = new Formatter(sb); + + sb.toString(); // false positive + f.format("%s", bad); + sb.toString(); + } +} \ No newline at end of file diff --git a/java/ql/test/library-tests/dataflow/taint-format/options b/java/ql/test/library-tests/dataflow/taint-format/options new file mode 100644 index 00000000000..814f667417c --- /dev/null +++ b/java/ql/test/library-tests/dataflow/taint-format/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args --enable-preview -source 14 -target 14 \ No newline at end of file diff --git a/java/ql/test/library-tests/dataflow/taint-format/test.expected b/java/ql/test/library-tests/dataflow/taint-format/test.expected new file mode 100644 index 00000000000..9e0e64f695c --- /dev/null +++ b/java/ql/test/library-tests/dataflow/taint-format/test.expected @@ -0,0 +1,24 @@ +| A.java:8:22:8:28 | taint(...) | A.java:8:22:8:28 | taint(...) | +| A.java:8:22:8:28 | taint(...) | A.java:11:9:11:11 | bad | +| A.java:8:22:8:28 | taint(...) | A.java:11:9:11:27 | formatted(...) | +| A.java:8:22:8:28 | taint(...) | A.java:12:9:12:43 | formatted(...) | +| A.java:8:22:8:28 | taint(...) | A.java:12:9:12:43 | new ..[] { .. } | +| A.java:8:22:8:28 | taint(...) | A.java:12:29:12:31 | bad | +| A.java:8:22:8:28 | taint(...) | A.java:13:9:13:40 | format(...) | +| A.java:8:22:8:28 | taint(...) | A.java:13:9:13:40 | new ..[] { .. } | +| A.java:8:22:8:28 | taint(...) | A.java:13:31:13:33 | bad | +| A.java:17:22:17:28 | taint(...) | A.java:17:22:17:28 | taint(...) | +| A.java:17:22:17:28 | taint(...) | A.java:21:9:21:9 | f [post update] | +| A.java:17:22:17:28 | taint(...) | A.java:21:9:21:27 | format(...) | +| A.java:17:22:17:28 | taint(...) | A.java:21:9:21:27 | new ..[] { .. } | +| A.java:17:22:17:28 | taint(...) | A.java:21:24:21:26 | bad | +| A.java:17:22:17:28 | taint(...) | A.java:22:9:22:9 | f | +| A.java:26:22:26:28 | taint(...) | A.java:26:22:26:28 | taint(...) | +| A.java:26:22:26:28 | taint(...) | A.java:30:9:30:10 | sb | +| A.java:26:22:26:28 | taint(...) | A.java:30:9:30:21 | toString(...) | +| A.java:26:22:26:28 | taint(...) | A.java:31:9:31:9 | f [post update] | +| A.java:26:22:26:28 | taint(...) | A.java:31:9:31:27 | format(...) | +| A.java:26:22:26:28 | taint(...) | A.java:31:9:31:27 | new ..[] { .. } | +| A.java:26:22:26:28 | taint(...) | A.java:31:24:31:26 | bad | +| A.java:26:22:26:28 | taint(...) | A.java:32:9:32:10 | sb | +| A.java:26:22:26:28 | taint(...) | A.java:32:9:32:21 | toString(...) | diff --git a/java/ql/test/library-tests/dataflow/taint-format/test.ql b/java/ql/test/library-tests/dataflow/taint-format/test.ql new file mode 100644 index 00000000000..0a877c0c985 --- /dev/null +++ b/java/ql/test/library-tests/dataflow/taint-format/test.ql @@ -0,0 +1,16 @@ +import java +import semmle.code.java.dataflow.TaintTracking + +class Conf extends TaintTracking::Configuration { + Conf() { this = "qltest:dataflow:format" } + + override predicate isSource(DataFlow::Node n) { + n.asExpr().(MethodAccess).getMethod().hasName("taint") + } + + override predicate isSink(DataFlow::Node n) { any() } +} + +from DataFlow::Node src, DataFlow::Node sink, Conf conf +where conf.hasFlow(src, sink) +select src, sink From 759324ca1bb0faa7c0d9f889ee3879730b1f9a6f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 28 Sep 2020 16:51:21 +0100 Subject: [PATCH 091/411] Update cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll Co-authored-by: Jonas Jensen --- cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll index b317713812b..075e2dc4577 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll @@ -8,7 +8,7 @@ import semmle.code.cpp.models.interfaces.Taint * Additional model for `std::pair` constructors. */ class StdPairConstructor extends Constructor, TaintFunction { - StdPairConstructor() { this.getDeclaringType().hasQualifiedName("std", "pair") } + StdPairConstructor() { this.hasQualifiedName("std", "pair", "pair") } /** * Gets the index of a parameter to this function that is a reference to From 773bc48a914e77d1db257d2c72e07f8a419e5b45 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 28 Sep 2020 16:37:29 +0100 Subject: [PATCH 092/411] C++: Use a more modern make_pair. --- .../library-tests/dataflow/taint-tests/localTaint.expected | 6 ------ cpp/ql/test/library-tests/dataflow/taint-tests/stl.h | 2 +- .../library-tests/dataflow/taint-tests/test_diff.expected | 2 ++ .../library-tests/dataflow/taint-tests/test_ir.expected | 2 ++ 4 files changed, 5 insertions(+), 7 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 ca68373079b..e7e08a00763 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -260,7 +260,6 @@ | file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | | | file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | | | file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | | -| file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | | | format.cpp:16:21:16:21 | s | format.cpp:22:22:22:22 | s | | | format.cpp:16:31:16:31 | n | format.cpp:22:25:22:25 | n | | | format.cpp:16:46:16:51 | format | format.cpp:22:28:22:33 | format | | @@ -1989,14 +1988,9 @@ | stl.h:222:30:222:40 | call to allocator | stl.h:222:21:222:41 | noexcept(...) | TAINT | | stl.h:222:53:222:63 | 0 | stl.h:222:46:222:64 | (no string representation) | TAINT | | stl.h:315:9:315:9 | Unknown literal | stl.h:315:9:315:9 | constructor init of field first | TAINT | -| stl.h:315:9:315:9 | Unknown literal | stl.h:315:9:315:9 | constructor init of field first | TAINT | -| stl.h:315:9:315:9 | Unknown literal | stl.h:315:9:315:9 | constructor init of field second | TAINT | | stl.h:315:9:315:9 | Unknown literal | stl.h:315:9:315:9 | constructor init of field second | TAINT | | stl.h:315:9:315:9 | constructor init of field first [post-this] | stl.h:315:9:315:9 | constructor init of field second [pre-this] | | -| stl.h:315:9:315:9 | constructor init of field first [post-this] | stl.h:315:9:315:9 | constructor init of field second [pre-this] | | | stl.h:315:9:315:9 | constructor init of field first [pre-this] | stl.h:315:9:315:9 | constructor init of field second [pre-this] | | -| stl.h:315:9:315:9 | constructor init of field first [pre-this] | stl.h:315:9:315:9 | constructor init of field second [pre-this] | | -| stl.h:315:9:315:9 | this | stl.h:315:9:315:9 | constructor init of field first [pre-this] | | | stl.h:315:9:315:9 | this | stl.h:315:9:315:9 | constructor init of field first [pre-this] | | | string.cpp:24:12:24:17 | call to source | string.cpp:28:7:28:7 | a | | | string.cpp:25:16:25:20 | 123 | string.cpp:25:16:25:21 | call to basic_string | TAINT | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h index 3a112cd0c88..5869e5b8d00 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h @@ -325,7 +325,7 @@ namespace std { void swap(pair& p) /*noexcept(...)*/; }; - template pair make_pair(T1, T2); + template constexpr pair make_pair(T1&&, T2&&); } // --- map --- 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 fb50ba7f29c..27e3b474044 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 @@ -34,7 +34,9 @@ | map.cpp:76:9:76:13 | map.cpp:63:37:63:42 | IR only | | map.cpp:77:9:77:14 | map.cpp:63:37:63:42 | IR only | | map.cpp:84:34:84:38 | map.cpp:84:17:84:22 | IR only | +| map.cpp:85:7:85:39 | map.cpp:85:17:85:22 | IR only | | map.cpp:85:34:85:39 | map.cpp:85:17:85:22 | IR only | +| map.cpp:87:7:87:38 | map.cpp:87:24:87:29 | IR only | | map.cpp:87:34:87:38 | map.cpp:87:24:87:29 | IR only | | map.cpp:88:34:88:39 | map.cpp:88:24:88:29 | IR only | | map.cpp:92:7:92:7 | map.cpp:91:33:91:38 | 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 3536273a806..f47316752f2 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 @@ -70,8 +70,10 @@ | map.cpp:78:7:78:7 | l | map.cpp:63:37:63:42 | call to source | | map.cpp:83:7:83:32 | call to pair | map.cpp:83:17:83:22 | call to source | | map.cpp:84:34:84:38 | first | map.cpp:84:17:84:22 | call to source | +| map.cpp:85:7:85:39 | (reference dereference) | map.cpp:85:17:85:22 | call to source | | map.cpp:85:34:85:39 | second | map.cpp:85:17:85:22 | call to source | | map.cpp:86:7:86:32 | call to pair | map.cpp:86:24:86:29 | call to source | +| map.cpp:87:7:87:38 | (reference dereference) | map.cpp:87:24:87:29 | call to source | | map.cpp:87:34:87:38 | first | map.cpp:87:24:87:29 | call to source | | map.cpp:88:34:88:39 | second | map.cpp:88:24:88:29 | call to source | | map.cpp:93:9:93:13 | first | map.cpp:91:33:91:38 | call to source | From 8059230bbcbf58ccac28e560de41c38e8c5ecb0e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 28 Sep 2020 16:59:28 +0100 Subject: [PATCH 093/411] Update cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll Co-authored-by: Jonas Jensen --- cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll index 075e2dc4577..8b80d9d224d 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll @@ -38,7 +38,7 @@ class StdMakePair extends TaintFunction { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // taint flow from any parameter to the returned object - input.isParameterDeref(_) and + input.isParameterDeref([0, 1]) and output.isReturnValue() } } From 6de29a6dd39874fb22d7accc8749a3fe69849941 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 28 Sep 2020 17:52:10 +0100 Subject: [PATCH 094/411] C++: Provide std::pair constructor initializers. --- .../dataflow/taint-tests/localTaint.expected | 14 ++++++++++++++ .../test/library-tests/dataflow/taint-tests/stl.h | 2 +- .../dataflow/taint-tests/taint.expected | 6 ++++++ .../dataflow/taint-tests/test_diff.expected | 6 ------ 4 files changed, 21 insertions(+), 7 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 e7e08a00763..62505016c41 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -1992,6 +1992,20 @@ | stl.h:315:9:315:9 | constructor init of field first [post-this] | stl.h:315:9:315:9 | constructor init of field second [pre-this] | | | stl.h:315:9:315:9 | constructor init of field first [pre-this] | stl.h:315:9:315:9 | constructor init of field second [pre-this] | | | stl.h:315:9:315:9 | this | stl.h:315:9:315:9 | constructor init of field first [pre-this] | | +| stl.h:322:3:322:3 | this | stl.h:322:36:322:43 | constructor init of field first [pre-this] | | +| stl.h:322:3:322:6 | this | stl.h:322:36:322:43 | constructor init of field first [pre-this] | | +| stl.h:322:18:322:18 | x | stl.h:322:42:322:42 | x | | +| stl.h:322:18:322:18 | x | stl.h:322:42:322:42 | x | | +| stl.h:322:31:322:31 | y | stl.h:322:53:322:53 | y | | +| stl.h:322:31:322:31 | y | stl.h:322:53:322:53 | y | | +| stl.h:322:36:322:43 | call to unknown function | stl.h:322:36:322:43 | constructor init of field first | TAINT | +| stl.h:322:36:322:43 | constructor init of field first [post-this] | stl.h:322:46:322:54 | constructor init of field second [pre-this] | | +| stl.h:322:36:322:43 | constructor init of field first [post-this] | stl.h:322:46:322:54 | constructor init of field second [pre-this] | | +| stl.h:322:36:322:43 | constructor init of field first [pre-this] | stl.h:322:46:322:54 | constructor init of field second [pre-this] | | +| stl.h:322:36:322:43 | constructor init of field first [pre-this] | stl.h:322:46:322:54 | constructor init of field second [pre-this] | | +| stl.h:322:42:322:42 | x | stl.h:322:36:322:43 | constructor init of field first | TAINT | +| stl.h:322:46:322:54 | call to unknown function | stl.h:322:46:322:54 | constructor init of field second | TAINT | +| stl.h:322:53:322:53 | y | stl.h:322:46:322:54 | constructor init of field second | TAINT | | string.cpp:24:12:24:17 | call to source | string.cpp:28:7:28:7 | a | | | string.cpp:25:16:25:20 | 123 | string.cpp:25:16:25:21 | call to basic_string | TAINT | | string.cpp:25:16:25:21 | call to basic_string | string.cpp:29:7:29:7 | b | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h index 5869e5b8d00..78ecd7340b9 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h @@ -319,7 +319,7 @@ namespace std { T1 first; T2 second; pair(); - pair(const T1& x, const T2& y); + pair(const T1& x, const T2& y) : first(x), second(y) {}; template pair(const pair &p); void swap(pair& p) /*noexcept(...)*/; 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 ca407a2fd15..2293eb4edf4 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -35,12 +35,18 @@ | format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source | | map.cpp:26:9:26:13 | first | map.cpp:25:12:25:17 | call to source | | map.cpp:32:9:32:14 | second | map.cpp:30:13:30:18 | call to source | +| map.cpp:41:9:41:13 | first | map.cpp:40:30:40:35 | call to source | | map.cpp:43:7:43:7 | e | map.cpp:40:30:40:35 | call to source | +| map.cpp:47:9:47:14 | second | map.cpp:45:37:45:42 | call to source | | map.cpp:48:7:48:7 | f | map.cpp:45:37:45:42 | call to source | +| map.cpp:52:9:52:14 | second | map.cpp:45:37:45:42 | call to source | | map.cpp:53:7:53:7 | g | map.cpp:45:37:45:42 | call to source | +| map.cpp:58:9:58:14 | second | map.cpp:45:37:45:42 | call to source | | map.cpp:59:7:59:7 | h | map.cpp:45:37:45:42 | call to source | | map.cpp:69:7:69:7 | i | map.cpp:62:37:62:42 | call to source | +| map.cpp:71:9:71:14 | second | map.cpp:62:37:62:42 | call to source | | map.cpp:72:7:72:7 | j | map.cpp:62:37:62:42 | call to source | +| map.cpp:74:9:74:14 | second | map.cpp:63:37:63:42 | call to source | | map.cpp:75:7:75:7 | k | map.cpp:63:37:63:42 | call to source | | map.cpp:78:7:78:7 | l | map.cpp:63:37:63:42 | call to source | | map.cpp:83:7:83:32 | call to pair | map.cpp:83:17:83:22 | 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 27e3b474044..e604e787231 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 @@ -17,20 +17,14 @@ | copyableclass.cpp:67:11:67:21 | copyableclass.cpp:67:13:67:18 | IR only | | copyableclass_declonly.cpp:42:8:42:9 | copyableclass_declonly.cpp:34:30:34:35 | AST only | | copyableclass_declonly.cpp:67:11:67:11 | copyableclass_declonly.cpp:67:13:67:18 | AST only | -| map.cpp:41:9:41:13 | map.cpp:40:30:40:35 | IR only | | map.cpp:42:9:42:14 | map.cpp:40:30:40:35 | IR only | | map.cpp:46:9:46:13 | map.cpp:45:37:45:42 | IR only | -| map.cpp:47:9:47:14 | map.cpp:45:37:45:42 | IR only | | map.cpp:51:9:51:13 | map.cpp:45:37:45:42 | IR only | -| map.cpp:52:9:52:14 | map.cpp:45:37:45:42 | IR only | | map.cpp:57:9:57:13 | map.cpp:45:37:45:42 | IR only | -| map.cpp:58:9:58:14 | map.cpp:45:37:45:42 | IR only | | map.cpp:67:9:67:13 | map.cpp:62:37:62:42 | IR only | | map.cpp:68:9:68:14 | map.cpp:62:37:62:42 | IR only | | map.cpp:70:9:70:13 | map.cpp:62:37:62:42 | IR only | -| map.cpp:71:9:71:14 | map.cpp:62:37:62:42 | IR only | | map.cpp:73:9:73:13 | map.cpp:63:37:63:42 | IR only | -| map.cpp:74:9:74:14 | map.cpp:63:37:63:42 | IR only | | map.cpp:76:9:76:13 | map.cpp:63:37:63:42 | IR only | | map.cpp:77:9:77:14 | map.cpp:63:37:63:42 | IR only | | map.cpp:84:34:84:38 | map.cpp:84:17:84:22 | IR only | From dfc44360129cb268330cccbdd84273b5883dcf7e Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Mon, 28 Sep 2020 15:34:47 +0100 Subject: [PATCH 095/411] JavaScript: Teach API graphs to recognise arguments supplied in partial function applications. --- .../ql/src/semmle/javascript/ApiGraphs.qll | 45 ++++++++++++++----- .../partial-invoke/VerifyAssertions.expected | 0 .../partial-invoke/VerifyAssertions.ql | 1 + .../ql/test/ApiGraphs/partial-invoke/index.js | 8 ++++ .../ApiGraphs/partial-invoke/package.json | 3 ++ 5 files changed, 45 insertions(+), 12 deletions(-) create mode 100644 javascript/ql/test/ApiGraphs/partial-invoke/VerifyAssertions.expected create mode 100644 javascript/ql/test/ApiGraphs/partial-invoke/VerifyAssertions.ql create mode 100644 javascript/ql/test/ApiGraphs/partial-invoke/index.js create mode 100644 javascript/ql/test/ApiGraphs/partial-invoke/package.json diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 160ff9e47a2..beae51fedcb 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -412,16 +412,9 @@ module API { rhs = f.getAReturn() ) or - exists(DataFlow::SourceNode src, DataFlow::InvokeNode invk | - use(base, src) and invk = trackUseNode(src).getAnInvocation() - | - exists(int i | - lbl = Label::parameter(i) and - rhs = invk.getArgument(i) - ) - or - lbl = Label::receiver() and - rhs = invk.(DataFlow::CallNode).getReceiver() + exists(int i | + lbl = Label::parameter(i) and + argumentPassing(base, i, rhs) ) or exists(DataFlow::SourceNode src, DataFlow::PropWrite pw | @@ -432,6 +425,30 @@ module API { ) } + /** + * Holds if `arg` is passed as the `i`th argument to a use of `base`, either by means of a + * full invocation, or in a partial function application. + * + * The receiver is considered to be argument -1. + */ + private predicate argumentPassing(TApiNode base, int i, DataFlow::Node arg) { + exists(DataFlow::SourceNode use, DataFlow::SourceNode pred | + use(base, use) and pred = trackUseNode(use) + | + arg = pred.getAnInvocation().getArgument(i) + or + arg = pred.getACall().getReceiver() and + i = -1 + or + exists(DataFlow::PartialInvokeNode pin, DataFlow::Node callback | pred.flowsTo(callback) | + pin.isPartialArgument(callback, arg, i) + or + arg = pin.getBoundReceiver(callback) and + i = -1 + ) + ) + } + /** * Holds if `rhs` is the right-hand side of a definition of node `nd`. */ @@ -719,10 +736,14 @@ private module Label { bindingset[s] string parameterByStringIndex(string s) { result = "parameter " + s and - s.toInt() >= 0 + s.toInt() >= -1 } - /** Gets the `parameter` edge label for the `i`th parameter. */ + /** + * Gets the `parameter` edge label for the `i`th parameter. + * + * The receiver is considered to be parameter -1. + */ bindingset[i] string parameter(int i) { result = parameterByStringIndex(i.toString()) } diff --git a/javascript/ql/test/ApiGraphs/partial-invoke/VerifyAssertions.expected b/javascript/ql/test/ApiGraphs/partial-invoke/VerifyAssertions.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/javascript/ql/test/ApiGraphs/partial-invoke/VerifyAssertions.ql b/javascript/ql/test/ApiGraphs/partial-invoke/VerifyAssertions.ql new file mode 100644 index 00000000000..b9c54e26072 --- /dev/null +++ b/javascript/ql/test/ApiGraphs/partial-invoke/VerifyAssertions.ql @@ -0,0 +1 @@ +import ApiGraphs.VerifyAssertions diff --git a/javascript/ql/test/ApiGraphs/partial-invoke/index.js b/javascript/ql/test/ApiGraphs/partial-invoke/index.js new file mode 100644 index 00000000000..1642e1454f3 --- /dev/null +++ b/javascript/ql/test/ApiGraphs/partial-invoke/index.js @@ -0,0 +1,8 @@ +const cp = require('child_process'); + +module.exports = function () { + return cp.spawn.bind( + cp, // def (parameter -1 (member spawn (member exports (module child_process)))) + "cat" // def (parameter 0 (member spawn (member exports (module child_process)))) + ); +}; \ No newline at end of file diff --git a/javascript/ql/test/ApiGraphs/partial-invoke/package.json b/javascript/ql/test/ApiGraphs/partial-invoke/package.json new file mode 100644 index 00000000000..279f51b6a5e --- /dev/null +++ b/javascript/ql/test/ApiGraphs/partial-invoke/package.json @@ -0,0 +1,3 @@ +{ + "name": "partial-invoke" +} \ No newline at end of file From e04404b713487c0876d4331384e538fba938bb49 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 28 Sep 2020 21:17:25 +0200 Subject: [PATCH 096/411] also recognize cookie writes are leading to cookie access --- javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql | 4 ++-- .../Security/CWE-352/MissingCsrfMiddleware.expected | 1 + .../query-tests/Security/CWE-352/MissingCsrfMiddlewareBad.js | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql b/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql index ca09a09f3a8..d63786ba08d 100644 --- a/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql +++ b/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql @@ -18,8 +18,8 @@ string cookieProperty() { result = "session" or result = "cookies" or result = " /** Gets a data flow node that flows to the base of an access to `cookies`, `session`, or `user`. */ private DataFlow::SourceNode nodeLeadingToCookieAccess(DataFlow::TypeBackTracker t) { t.start() and - exists(DataFlow::PropRead value | - value = result.getAPropertyRead(cookieProperty()).getAPropertyRead() and + exists(DataFlow::PropRef value | + value = result.getAPropertyRead(cookieProperty()).getAPropertyReference() and // Ignore accesses to values that are part of a CSRF or captcha check not value.getPropertyName().regexpMatch("(?i).*(csrf|xsrf|captcha).*") and // Ignore calls like `req.session.save()` diff --git a/javascript/ql/test/query-tests/Security/CWE-352/MissingCsrfMiddleware.expected b/javascript/ql/test/query-tests/Security/CWE-352/MissingCsrfMiddleware.expected index 6cf61160de1..bc6087f4354 100644 --- a/javascript/ql/test/query-tests/Security/CWE-352/MissingCsrfMiddleware.expected +++ b/javascript/ql/test/query-tests/Security/CWE-352/MissingCsrfMiddleware.expected @@ -1,6 +1,7 @@ | MissingCsrfMiddlewareBad.js:7:9:7:22 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | MissingCsrfMiddlewareBad.js:10:26:12:1 | functio ... il"];\\n} | here | | MissingCsrfMiddlewareBad.js:17:13:17:26 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | MissingCsrfMiddlewareBad.js:25:30:27:6 | errorCa ... \\n }) | here | | MissingCsrfMiddlewareBad.js:33:13:33:26 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | MissingCsrfMiddlewareBad.js:41:30:43:6 | errorCa ... \\n }) | here | +| MissingCsrfMiddlewareBad.js:33:13:33:26 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | MissingCsrfMiddlewareBad.js:45:31:47:6 | errorCa ... \\n }) | here | | csurf_api_example.js:42:37:42:50 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | csurf_api_example.js:42:53:45:3 | functio ... e')\\n } | here | | csurf_example.js:18:9:18:22 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | csurf_example.js:31:40:34:1 | functio ... sed')\\n} | here | | lusca_example.js:9:9:9:22 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | lusca_example.js:26:42:29:1 | functio ... sed')\\n} | here | diff --git a/javascript/ql/test/query-tests/Security/CWE-352/MissingCsrfMiddlewareBad.js b/javascript/ql/test/query-tests/Security/CWE-352/MissingCsrfMiddlewareBad.js index fdcaf739451..d2d9b8bd4a1 100644 --- a/javascript/ql/test/query-tests/Security/CWE-352/MissingCsrfMiddlewareBad.js +++ b/javascript/ql/test/query-tests/Security/CWE-352/MissingCsrfMiddlewareBad.js @@ -41,4 +41,8 @@ app.post('/changeEmail', function (req, res) { app.post('/changeEmail', errorCatch(async function (req, res) { let newEmail = req.cookies["newEmail"]; })); + + app.post('/doLoginStuff', errorCatch(async function (req, res) { + req.session.user = loginStuff(req); + })); }) From 52d94f61770936720321554f17eb7b773d602e47 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 29 Sep 2020 10:12:46 +0200 Subject: [PATCH 097/411] use `getABoundCallbackParameter` instead of `getCallback` and `getParameter`. --- .../ql/src/semmle/javascript/frameworks/ClientRequests.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll index fa9fb550330..830d0faeb8a 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll @@ -396,11 +396,11 @@ module ClientRequest { override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) { promise = false and - result = this.getCallback(this.getNumArgument() - 1).getParameter(1) and + result = this.getABoundCallbackParameter(this.getNumArgument() - 1, 1) and responseType = "fetch.response" or promise = false and - result = this.getCallback(this.getNumArgument() - 1).getParameter(2) and + result = this.getABoundCallbackParameter(this.getNumArgument() - 1, 2) and responseType = "json" } } From 89195d7ada85c2ce74eae884e1fd372efb538c0f Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 29 Sep 2020 10:13:48 +0200 Subject: [PATCH 098/411] add change note for needle --- change-notes/1.26/analysis-javascript.md | 1 + 1 file changed, 1 insertion(+) diff --git a/change-notes/1.26/analysis-javascript.md b/change-notes/1.26/analysis-javascript.md index bcd727fba07..ad2ff09d9c0 100644 --- a/change-notes/1.26/analysis-javascript.md +++ b/change-notes/1.26/analysis-javascript.md @@ -14,6 +14,7 @@ - [json-stringify-safe](https://www.npmjs.com/package/json-stringify-safe) - [json3](https://www.npmjs.com/package/json3) - [lodash](https://www.npmjs.com/package/lodash) + - [needle](https://www.npmjs.com/package/needle) - [object-inspect](https://www.npmjs.com/package/object-inspect) - [pretty-format](https://www.npmjs.com/package/pretty-format) - [stringify-object](https://www.npmjs.com/package/stringify-object) From fee279f952297a39723bace5735f9c1220c2887d Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 29 Sep 2020 10:47:32 +0200 Subject: [PATCH 099/411] Python: Hotfix performance problem with flask methods This improves runtime for command injection query on https://lgtm.com/projects/g/alibaba/funcraft from +200 seconds (I did not care to wait more) down to ~55 seconds on my machine. This type of tracking predicate with string as additional argument apparently causes trouble :| --- .../semmle/python/frameworks/Flask.qll | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Flask.qll b/python/ql/src/experimental/semmle/python/frameworks/Flask.qll index de72eb9128f..5b4079331d7 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Flask.qll @@ -52,16 +52,35 @@ private module Flask { } private module FlaskRequestTracking { - private DataFlow::Node tainted_methods(string attr_name, DataFlow::TypeTracker t) { - attr_name in ["get_data", "get_json"] and - t.startInAttr(attr_name) and + /** Gets a reference to the `get_data` attribute of a Flask request. */ + private DataFlow::Node get_data(DataFlow::TypeTracker t) { + t.startInAttr("get_data") and result = flask::request() or - exists(DataFlow::TypeTracker t2 | result = tainted_methods(attr_name, t2).track(t2, t)) + exists(DataFlow::TypeTracker t2 | result = get_data(t2).track(t2, t)) } + /** Gets a reference to the `get_data` attribute of a Flask request. */ + DataFlow::Node get_data() { result = get_data(DataFlow::TypeTracker::end()) } + + /** Gets a reference to the `get_json` attribute of a Flask request. */ + private DataFlow::Node get_json(DataFlow::TypeTracker t) { + t.startInAttr("get_json") and + result = flask::request() + or + exists(DataFlow::TypeTracker t2 | result = get_json(t2).track(t2, t)) + } + + /** Gets a reference to the `get_json` attribute of a Flask request. */ + DataFlow::Node get_json() { result = get_json(DataFlow::TypeTracker::end()) } + + /** Gets a reference to either of the `get_json` or `get_data` attributes of a Flask request. */ DataFlow::Node tainted_methods(string attr_name) { - result = tainted_methods(attr_name, DataFlow::TypeTracker::end()) + result = get_data() and + attr_name = "get_data" + or + result = get_json() and + attr_name = "get_json" } } From 51f1f03f5ffc440ca8da5d491a8bc9190b3281d7 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 29 Sep 2020 11:56:10 +0200 Subject: [PATCH 100/411] add change note for js/missing-token-validation --- change-notes/1.26/analysis-javascript.md | 1 + 1 file changed, 1 insertion(+) diff --git a/change-notes/1.26/analysis-javascript.md b/change-notes/1.26/analysis-javascript.md index bcd727fba07..674667c6b7b 100644 --- a/change-notes/1.26/analysis-javascript.md +++ b/change-notes/1.26/analysis-javascript.md @@ -39,6 +39,7 @@ | Unsafe shell command constructed from library input (`js/shell-command-constructed-from-input`) | More results | This query now recognizes more commands where colon, dash, and underscore are used. | | Unsafe jQuery plugin (`js/unsafe-jquery-plugin`) | More results | This query now detects more unsafe uses of nested option properties. | | Client-side URL redirect (`js/client-side-unvalidated-url-redirection`) | More results | This query now recognizes some unsafe uses of `importScripts()` inside WebWorkers. | +| Missing CSRF middleware (`js/missing-token-validation`) | More results | This query now recognizes writes to cookie and session variables as potentially vulnerable to CSRF attacks. | ## Changes to libraries From d184aa7c06910096b51bfd3baa773ae90b937fe4 Mon Sep 17 00:00:00 2001 From: Joe Date: Tue, 29 Sep 2020 15:24:51 +0100 Subject: [PATCH 101/411] Make `FieldRead` and `FieldWrite` extend `LValue` and `RValue` --- java/ql/src/semmle/code/java/Expr.qll | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/java/ql/src/semmle/code/java/Expr.qll b/java/ql/src/semmle/code/java/Expr.qll index d79a82acbad..50f4a210d60 100755 --- a/java/ql/src/semmle/code/java/Expr.qll +++ b/java/ql/src/semmle/code/java/Expr.qll @@ -1912,14 +1912,10 @@ private module Qualifier { } /** An expression that assigns a value to a field. */ -class FieldWrite extends FieldAccess { - FieldWrite() { exists(Field f | f = getVariable() and isLValue()) } -} +class FieldWrite extends FieldAccess, LValue { } /** An expression that reads a field. */ -class FieldRead extends FieldAccess { - FieldRead() { exists(Field f | f = getVariable() and isRValue()) } -} +class FieldRead extends FieldAccess, RValue { } private predicate hasInstantiation(RefType t) { t instanceof TypeVariable or From eccfa5d26a0041c8c30967829a1092925cca4202 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 29 Sep 2020 15:34:05 +0100 Subject: [PATCH 102/411] Fix documentation typo Co-authored-by: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com> --- .../semmle/code/java/dataflow/internal/TaintTrackingUtil.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index 8d551ecdaff..02ba42fc2fa 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -772,7 +772,7 @@ private predicate formatStep(Expr tracked, Expr sink) { /** * A local variable that is assigned a `Formatter`. * Writing tainted data to such a formatter causes the underlying - * `OutputStream` or `Appenable` to be tainted. + * `OutputStream` or `Appendable` to be tainted. */ private class FormatterVar extends LocalVariableDecl { FormatterVar() { From efc3a2523790d1c2c8ab739645e543686a5ad873 Mon Sep 17 00:00:00 2001 From: Joe Date: Tue, 29 Sep 2020 16:02:51 +0100 Subject: [PATCH 103/411] Java: Don't pass taint through the format methods of `Console` --- .../code/java/dataflow/internal/TaintTrackingUtil.qll | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index 02ba42fc2fa..f9da6342b35 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -456,7 +456,8 @@ private predicate taintPreservingArgumentToMethod(Method method) { method.getDeclaringType() instanceof TypeString and method.hasName("join") or - method instanceof StringFormatMethod + method instanceof StringFormatMethod and + not method.getDeclaringType().hasQualifiedName("java.io", "Console") } /** @@ -649,7 +650,8 @@ private predicate argToQualifierStep(Expr tracked, Expr sink) { */ private predicate taintPreservingArgumentToQualifier(Method method) { method instanceof StringFormatMethod and - not method.getDeclaringType() instanceof TypeString + not method.getDeclaringType() instanceof TypeString and + not method.getDeclaringType().hasQualifiedName("java.io", "Console") } /** From deae9256ddbcbf2e47ed22a1d5df26e906bfd519 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 29 Sep 2020 15:50:28 +0200 Subject: [PATCH 104/411] add convenience method to API graphs --- javascript/ql/src/semmle/javascript/ApiGraphs.qll | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 160ff9e47a2..c5264a8d062 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -35,6 +35,17 @@ module API { ) } + /** + * Gets a source-node corresponding to a use of the API component represented by this node. + * + * For example, `require('fs').readFileSync` is a use of the function `readFileSync` from the + * `fs` module, and `require('fs').readFileSync(file)` is a use of the result of that function. + * + * As another example, in the assignment `exports.plusOne = (x) => x+1` the two references to + * `x` are uses of the first parameter of `plusOne`. + */ + DataFlow::SourceNode getASourceUse() { Impl::use(this, result) } + /** * Gets a data-flow node corresponding to the right-hand side of a definition of the API * component represented by this node. From 38573316571092993a0e5e9b3804903087014b77 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 29 Sep 2020 16:19:32 +0200 Subject: [PATCH 105/411] avoid .getReturn().getAUse().(DataFlow::InvokeNode) in the SQL model --- .../src/semmle/javascript/frameworks/SQL.qll | 74 ++++++++++++------- .../frameworks/SQL/SqlString.expected | 1 + .../library-tests/frameworks/SQL/mssql2.js | 13 +++- 3 files changed, 58 insertions(+), 30 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/SQL.qll b/javascript/ql/src/semmle/javascript/frameworks/SQL.qll index 19eaf168c08..25d50462b5e 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/SQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/SQL.qll @@ -31,11 +31,17 @@ private module MySql { /** Gets the package name `mysql` or `mysql2`. */ API::Node mysql() { result = API::moduleImport(["mysql", "mysql2"]) } + /** Gets a reference to `mysql.createConnection`. */ + API::Node createConnectionCallee() { result = mysql().getMember("createConnection") } + /** Gets a call to `mysql.createConnection`. */ - API::Node createConnection() { result = mysql().getMember("createConnection").getReturn() } + API::Node createConnection() { result = createConnectionCallee().getReturn() } + + /** Gets a reference to `mysql.createPool`. */ + API::Node createPoolCallee() { result = mysql().getMember("createPool") } /** Gets a call to `mysql.createPool`. */ - API::Node createPool() { result = mysql().getMember("createPool").getReturn() } + API::Node createPool() { result = createPoolCallee().getReturn() } /** Gets a data flow node that contains a freshly created MySQL connection instance. */ API::Node connection() { @@ -48,7 +54,7 @@ private module MySql { private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { QueryCall() { exists(API::Node recv | recv = createPool() or recv = connection() | - this = recv.getMember("query").getReturn().getAUse() + this = recv.getMember("query").getASourceUse().getACall() ) } @@ -66,8 +72,8 @@ private module MySql { this = [mysql(), createPool(), connection()] .getMember(["escape", "escapeId"]) - .getReturn() - .getAUse() + .getASourceUse() + .getACall() .asExpr() and input = this.getArgument(0) and output = this @@ -79,9 +85,9 @@ private module MySql { string kind; Credentials() { - exists(API::Node call, string prop | - call in [createConnection(), createPool()] and - call.getAUse().asExpr().(CallExpr).hasOptionArgument(0, prop, this) and + exists(API::Node callee, string prop | + callee in [createConnectionCallee(), createPoolCallee()] and + this = callee.getParameter(0).getMember(prop).getARhs().asExpr() and ( prop = "user" and kind = "user name" or @@ -98,8 +104,11 @@ private module MySql { * Provides classes modelling the `pg` package. */ private module Postgres { + /** Gets an expression of the form `require('pg').Client`. */ + API::Node newClientCallee() { result = API::moduleImport("pg").getMember("Client") } + /** Gets an expression of the form `new require('pg').Client()`. */ - API::Node newClient() { result = API::moduleImport("pg").getMember("Client").getInstance() } + API::Node newClient() { result = newClientCallee().getInstance() } /** Gets a data flow node that holds a freshly created Postgres client instance. */ API::Node client() { @@ -109,18 +118,21 @@ private module Postgres { result = newPool().getMember("connect").getParameter(0).getParameter(1) } - /** Gets an expression that constructs a new connection pool. */ - API::Node newPool() { + /** Gets a constructor that when invoked constructs a new connection pool. */ + API::Node newPoolCallee() { // new require('pg').Pool() - result = API::moduleImport("pg").getMember("Pool").getInstance() + result = API::moduleImport("pg").getMember("Pool") or // new require('pg-pool') - result = API::moduleImport("pg-pool").getInstance() + result = API::moduleImport("pg-pool") } + /** Gets an expression that constructs a new connection pool. */ + API::Node newPool() { result = newPoolCallee().getInstance() } + /** A call to the Postgres `query` method. */ private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { - QueryCall() { this = [client(), newPool()].getMember("query").getReturn().getAUse() } + QueryCall() { this = [client(), newPool()].getMember("query").getASourceUse().getACall() } override DataFlow::Node getAQueryArgument() { result = getArgument(0) } } @@ -135,9 +147,9 @@ private module Postgres { string kind; Credentials() { - exists(DataFlow::InvokeNode call, string prop | - call = [client(), newPool()].getAUse() and - this = call.getOptionArgument(0, prop).asExpr() and + exists(string prop | + this = + [newClientCallee(), newPoolCallee()].getParameter(0).getMember(prop).getARhs().asExpr() and ( prop = "user" and kind = "user name" or @@ -178,7 +190,7 @@ private module Sqlite { meth = "prepare" or meth = "run" | - this = newDb().getMember(meth).getReturn().getAUse() + this = newDb().getMember(meth).getASourceUse().getACall() ) } @@ -222,7 +234,7 @@ private module MsSql { /** A call to a MsSql query method. */ private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { - QueryCall() { this = request().getMember(["query", "batch"]).getReturn().getAUse() } + QueryCall() { this = request().getMember(["query", "batch"]).getASourceUse().getACall() } override DataFlow::Node getAQueryArgument() { result = getArgument(0) } } @@ -250,13 +262,13 @@ private module MsSql { string kind; Credentials() { - exists(DataFlow::InvokeNode call, string prop | + exists(API::Node callee, string prop | ( - call = mssql().getMember("connect").getReturn().getAUse() + callee = mssql().getMember("connect") or - call = mssql().getMember("ConnectionPool").getInstance().getAUse() + callee = mssql().getMember("ConnectionPool") ) and - this = call.getOptionArgument(0, prop).asExpr() and + this = callee.getParameter(0).getMember(prop).getARhs().asExpr() and ( prop = "user" and kind = "user name" or @@ -281,7 +293,7 @@ private module Sequelize { /** A call to `Sequelize.query`. */ private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { - QueryCall() { this = newSequelize().getMember("query").getReturn().getAUse() } + QueryCall() { this = newSequelize().getMember("query").getASourceUse().getACall() } override DataFlow::Node getAQueryArgument() { result = getArgument(0) } } @@ -300,7 +312,7 @@ private module Sequelize { Credentials() { exists(NewExpr ne, string prop | - ne = newSequelize().getAUse().asExpr() and + ne = sequelize().getASourceUse().getAnInstantiation().asExpr() and ( this = ne.getArgument(1) and prop = "username" or @@ -379,7 +391,10 @@ private module Spanner { class DatabaseRunCall extends SqlExecution { DatabaseRunCall() { this = - database().getMember(["run", "runPartitionedUpdate", "runStream"]).getReturn().getAUse() + database() + .getMember(["run", "runPartitionedUpdate", "runStream"]) + .getASourceUse() + .getACall() } } @@ -388,7 +403,7 @@ private module Spanner { */ class TransactionRunCall extends SqlExecution { TransactionRunCall() { - this = transaction().getMember(["run", "runStream", "runUpdate"]).getReturn().getAUse() + this = transaction().getMember(["run", "runStream", "runUpdate"]).getASourceUse().getACall() } } @@ -398,7 +413,10 @@ private module Spanner { class ExecuteSqlCall extends SqlExecution { ExecuteSqlCall() { this = - v1SpannerClient().getMember(["executeSql", "executeStreamingSql"]).getReturn().getAUse() + v1SpannerClient() + .getMember(["executeSql", "executeStreamingSql"]) + .getASourceUse() + .getACall() } override DataFlow::Node getAQueryArgument() { diff --git a/javascript/ql/test/library-tests/frameworks/SQL/SqlString.expected b/javascript/ql/test/library-tests/frameworks/SQL/SqlString.expected index b3e9e240944..b2e0cc4b046 100644 --- a/javascript/ql/test/library-tests/frameworks/SQL/SqlString.expected +++ b/javascript/ql/test/library-tests/frameworks/SQL/SqlString.expected @@ -3,6 +3,7 @@ | mssql2.js:5:15:5:34 | 'select 1 as number' | | mssql2.js:13:15:13:66 | 'create ... table' | | mssql2.js:22:24:22:43 | 'select 1 as number' | +| mssql2.js:29:30:29:81 | 'create ... table' | | mysql1.js:13:18:13:43 | 'SELECT ... lution' | | mysql1.js:18:18:22:1 | {\\n s ... vid']\\n} | | mysql1a.js:17:18:17:43 | 'SELECT ... lution' | diff --git a/javascript/ql/test/library-tests/frameworks/SQL/mssql2.js b/javascript/ql/test/library-tests/frameworks/SQL/mssql2.js index 9b64f06068a..f6a38828c5c 100644 --- a/javascript/ql/test/library-tests/frameworks/SQL/mssql2.js +++ b/javascript/ql/test/library-tests/frameworks/SQL/mssql2.js @@ -1,6 +1,6 @@ // Adapted from https://github.com/tediousjs/node-mssql#readme const sql = require('mssql') - + const request = new sql.Request() request.query('select 1 as number', (err, result) => { // ... error checks @@ -19,7 +19,16 @@ class C { this.req = req; } send() { - this.req.query('select 1 as number', (err, result) => {}) + this.req.query('select 1 as number', (err, result) => { }) } } new C(new sql.Request()); + +var obj = { + foo: function () { + return request.batch('create procedure #temporary as select * from table', (err, result) => { + // ... error checks + }) + } +} +obj.foo("foo", "bar", "baz"); // A API-graphs gotcha. \ No newline at end of file From be07d27a4c3594d5de4f77c17de8e6a7d874f4ef Mon Sep 17 00:00:00 2001 From: Joe Date: Tue, 29 Sep 2020 16:36:34 +0100 Subject: [PATCH 106/411] Java: Improve tests --- .../dataflow/taint-format/A.java | 11 ++++ .../dataflow/taint-format/test.expected | 52 ++++++++++--------- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/java/ql/test/library-tests/dataflow/taint-format/A.java b/java/ql/test/library-tests/dataflow/taint-format/A.java index c9bb27c8e99..3612c23f950 100644 --- a/java/ql/test/library-tests/dataflow/taint-format/A.java +++ b/java/ql/test/library-tests/dataflow/taint-format/A.java @@ -1,5 +1,7 @@ import java.util.Formatter; import java.lang.StringBuilder; +import java.lang.System; +import java.io.Console; class A { public static String taint() { return "tainted"; } @@ -11,6 +13,7 @@ class A { bad.formatted(good); good.formatted("a", bad, "b", good); String.format("%s%s", bad, good); + String.format("%s", good); } public static void test2() { @@ -31,4 +34,12 @@ class A { f.format("%s", bad); sb.toString(); } + + public static void test4() { + String bad = taint(); + Console c = System.console(); + + c.format(bad); + c.readLine("Enter something: %s", bad); + } } \ No newline at end of file diff --git a/java/ql/test/library-tests/dataflow/taint-format/test.expected b/java/ql/test/library-tests/dataflow/taint-format/test.expected index 9e0e64f695c..c52918fadc5 100644 --- a/java/ql/test/library-tests/dataflow/taint-format/test.expected +++ b/java/ql/test/library-tests/dataflow/taint-format/test.expected @@ -1,24 +1,28 @@ -| A.java:8:22:8:28 | taint(...) | A.java:8:22:8:28 | taint(...) | -| A.java:8:22:8:28 | taint(...) | A.java:11:9:11:11 | bad | -| A.java:8:22:8:28 | taint(...) | A.java:11:9:11:27 | formatted(...) | -| A.java:8:22:8:28 | taint(...) | A.java:12:9:12:43 | formatted(...) | -| A.java:8:22:8:28 | taint(...) | A.java:12:9:12:43 | new ..[] { .. } | -| A.java:8:22:8:28 | taint(...) | A.java:12:29:12:31 | bad | -| A.java:8:22:8:28 | taint(...) | A.java:13:9:13:40 | format(...) | -| A.java:8:22:8:28 | taint(...) | A.java:13:9:13:40 | new ..[] { .. } | -| A.java:8:22:8:28 | taint(...) | A.java:13:31:13:33 | bad | -| A.java:17:22:17:28 | taint(...) | A.java:17:22:17:28 | taint(...) | -| A.java:17:22:17:28 | taint(...) | A.java:21:9:21:9 | f [post update] | -| A.java:17:22:17:28 | taint(...) | A.java:21:9:21:27 | format(...) | -| A.java:17:22:17:28 | taint(...) | A.java:21:9:21:27 | new ..[] { .. } | -| A.java:17:22:17:28 | taint(...) | A.java:21:24:21:26 | bad | -| A.java:17:22:17:28 | taint(...) | A.java:22:9:22:9 | f | -| A.java:26:22:26:28 | taint(...) | A.java:26:22:26:28 | taint(...) | -| A.java:26:22:26:28 | taint(...) | A.java:30:9:30:10 | sb | -| A.java:26:22:26:28 | taint(...) | A.java:30:9:30:21 | toString(...) | -| A.java:26:22:26:28 | taint(...) | A.java:31:9:31:9 | f [post update] | -| A.java:26:22:26:28 | taint(...) | A.java:31:9:31:27 | format(...) | -| A.java:26:22:26:28 | taint(...) | A.java:31:9:31:27 | new ..[] { .. } | -| A.java:26:22:26:28 | taint(...) | A.java:31:24:31:26 | bad | -| A.java:26:22:26:28 | taint(...) | A.java:32:9:32:10 | sb | -| A.java:26:22:26:28 | taint(...) | A.java:32:9:32:21 | toString(...) | +| A.java:10:22:10:28 | taint(...) | A.java:10:22:10:28 | taint(...) | +| A.java:10:22:10:28 | taint(...) | A.java:13:9:13:11 | bad | +| A.java:10:22:10:28 | taint(...) | A.java:13:9:13:27 | formatted(...) | +| A.java:10:22:10:28 | taint(...) | A.java:14:9:14:43 | formatted(...) | +| A.java:10:22:10:28 | taint(...) | A.java:14:9:14:43 | new ..[] { .. } | +| A.java:10:22:10:28 | taint(...) | A.java:14:29:14:31 | bad | +| A.java:10:22:10:28 | taint(...) | A.java:15:9:15:40 | format(...) | +| A.java:10:22:10:28 | taint(...) | A.java:15:9:15:40 | new ..[] { .. } | +| A.java:10:22:10:28 | taint(...) | A.java:15:31:15:33 | bad | +| A.java:20:22:20:28 | taint(...) | A.java:20:22:20:28 | taint(...) | +| A.java:20:22:20:28 | taint(...) | A.java:24:9:24:9 | f [post update] | +| A.java:20:22:20:28 | taint(...) | A.java:24:9:24:27 | format(...) | +| A.java:20:22:20:28 | taint(...) | A.java:24:9:24:27 | new ..[] { .. } | +| A.java:20:22:20:28 | taint(...) | A.java:24:24:24:26 | bad | +| A.java:20:22:20:28 | taint(...) | A.java:25:9:25:9 | f | +| A.java:29:22:29:28 | taint(...) | A.java:29:22:29:28 | taint(...) | +| A.java:29:22:29:28 | taint(...) | A.java:33:9:33:10 | sb | +| A.java:29:22:29:28 | taint(...) | A.java:33:9:33:21 | toString(...) | +| A.java:29:22:29:28 | taint(...) | A.java:34:9:34:9 | f [post update] | +| A.java:29:22:29:28 | taint(...) | A.java:34:9:34:27 | format(...) | +| A.java:29:22:29:28 | taint(...) | A.java:34:9:34:27 | new ..[] { .. } | +| A.java:29:22:29:28 | taint(...) | A.java:34:24:34:26 | bad | +| A.java:29:22:29:28 | taint(...) | A.java:35:9:35:10 | sb | +| A.java:29:22:29:28 | taint(...) | A.java:35:9:35:21 | toString(...) | +| A.java:39:22:39:28 | taint(...) | A.java:39:22:39:28 | taint(...) | +| A.java:39:22:39:28 | taint(...) | A.java:42:18:42:20 | bad | +| A.java:39:22:39:28 | taint(...) | A.java:43:9:43:46 | new ..[] { .. } | +| A.java:39:22:39:28 | taint(...) | A.java:43:43:43:45 | bad | From adc05022f380f222c25be7f1875181a6b3ab3e4e Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 29 Sep 2020 18:21:41 +0200 Subject: [PATCH 107/411] update comment in test case Co-authored-by: Max Schaefer <54907921+max-schaefer@users.noreply.github.com> --- javascript/ql/test/library-tests/frameworks/SQL/mssql2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/test/library-tests/frameworks/SQL/mssql2.js b/javascript/ql/test/library-tests/frameworks/SQL/mssql2.js index f6a38828c5c..23eb7148a2c 100644 --- a/javascript/ql/test/library-tests/frameworks/SQL/mssql2.js +++ b/javascript/ql/test/library-tests/frameworks/SQL/mssql2.js @@ -31,4 +31,4 @@ var obj = { }) } } -obj.foo("foo", "bar", "baz"); // A API-graphs gotcha. \ No newline at end of file +obj.foo("foo", "bar", "baz"); // An API-graphs gotcha: "baz" should not be considered a `SqlString` From 1596436f7e52070880cb404b9a9b0cc96e71bd36 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 29 Sep 2020 18:05:50 +0200 Subject: [PATCH 108/411] rename getASourceUse to getAReference --- .../ql/src/semmle/javascript/ApiGraphs.qll | 23 +++++++++---------- .../src/semmle/javascript/frameworks/SQL.qll | 20 ++++++++-------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index c5264a8d062..7688df124f2 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -21,30 +21,29 @@ module API { */ class Node extends Impl::TApiNode { /** - * Gets a data-flow node corresponding to a use of the API component represented by this node. + * Gets a `SourceNode` corresponding to a use of the API component represented by this node. * * For example, `require('fs').readFileSync` is a use of the function `readFileSync` from the * `fs` module, and `require('fs').readFileSync(file)` is a use of the result of that function. * * As another example, in the assignment `exports.plusOne = (x) => x+1` the two references to * `x` are uses of the first parameter of `plusOne`. + * + * Note: The result from this predicate is always a `DataFlow::SourceǸode`, use `getAUse()` if + * you want to follow purely local data-flow and get all `DataFlow::Node`s that corrospond to a + * use of this API node. */ - DataFlow::Node getAUse() { - exists(DataFlow::SourceNode src | Impl::use(this, src) | - Impl::trackUseNode(src).flowsTo(result) - ) + DataFlow::SourceNode getAReference() { + exists(DataFlow::SourceNode src | Impl::use(this, src) | result = Impl::trackUseNode(src)) } /** - * Gets a source-node corresponding to a use of the API component represented by this node. + * Gets a data-flow node corresponding to a use of the API component represented by this node. * - * For example, `require('fs').readFileSync` is a use of the function `readFileSync` from the - * `fs` module, and `require('fs').readFileSync(file)` is a use of the result of that function. - * - * As another example, in the assignment `exports.plusOne = (x) => x+1` the two references to - * `x` are uses of the first parameter of `plusOne`. + * This predicate is similar to `getAReference`, except this prediate also follows purely local + * data-flow. */ - DataFlow::SourceNode getASourceUse() { Impl::use(this, result) } + DataFlow::Node getAUse() { getAReference().flowsTo(result) } /** * Gets a data-flow node corresponding to the right-hand side of a definition of the API diff --git a/javascript/ql/src/semmle/javascript/frameworks/SQL.qll b/javascript/ql/src/semmle/javascript/frameworks/SQL.qll index 25d50462b5e..232307cc014 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/SQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/SQL.qll @@ -54,7 +54,7 @@ private module MySql { private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { QueryCall() { exists(API::Node recv | recv = createPool() or recv = connection() | - this = recv.getMember("query").getASourceUse().getACall() + this = recv.getMember("query").getAReference().getACall() ) } @@ -72,7 +72,7 @@ private module MySql { this = [mysql(), createPool(), connection()] .getMember(["escape", "escapeId"]) - .getASourceUse() + .getAReference() .getACall() .asExpr() and input = this.getArgument(0) and @@ -132,7 +132,7 @@ private module Postgres { /** A call to the Postgres `query` method. */ private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { - QueryCall() { this = [client(), newPool()].getMember("query").getASourceUse().getACall() } + QueryCall() { this = [client(), newPool()].getMember("query").getAReference().getACall() } override DataFlow::Node getAQueryArgument() { result = getArgument(0) } } @@ -190,7 +190,7 @@ private module Sqlite { meth = "prepare" or meth = "run" | - this = newDb().getMember(meth).getASourceUse().getACall() + this = newDb().getMember(meth).getAReference().getACall() ) } @@ -234,7 +234,7 @@ private module MsSql { /** A call to a MsSql query method. */ private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { - QueryCall() { this = request().getMember(["query", "batch"]).getASourceUse().getACall() } + QueryCall() { this = request().getMember(["query", "batch"]).getAReference().getACall() } override DataFlow::Node getAQueryArgument() { result = getArgument(0) } } @@ -293,7 +293,7 @@ private module Sequelize { /** A call to `Sequelize.query`. */ private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { - QueryCall() { this = newSequelize().getMember("query").getASourceUse().getACall() } + QueryCall() { this = newSequelize().getMember("query").getAReference().getACall() } override DataFlow::Node getAQueryArgument() { result = getArgument(0) } } @@ -312,7 +312,7 @@ private module Sequelize { Credentials() { exists(NewExpr ne, string prop | - ne = sequelize().getASourceUse().getAnInstantiation().asExpr() and + ne = sequelize().getAReference().getAnInstantiation().asExpr() and ( this = ne.getArgument(1) and prop = "username" or @@ -393,7 +393,7 @@ private module Spanner { this = database() .getMember(["run", "runPartitionedUpdate", "runStream"]) - .getASourceUse() + .getAReference() .getACall() } } @@ -403,7 +403,7 @@ private module Spanner { */ class TransactionRunCall extends SqlExecution { TransactionRunCall() { - this = transaction().getMember(["run", "runStream", "runUpdate"]).getASourceUse().getACall() + this = transaction().getMember(["run", "runStream", "runUpdate"]).getAReference().getACall() } } @@ -415,7 +415,7 @@ private module Spanner { this = v1SpannerClient() .getMember(["executeSql", "executeStreamingSql"]) - .getASourceUse() + .getAReference() .getACall() } From 69f4ac25c4885bc478e8c34b65785f287affd221 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 29 Sep 2020 18:11:31 +0200 Subject: [PATCH 109/411] renamings based on review --- .../src/semmle/javascript/frameworks/SQL.qll | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/SQL.qll b/javascript/ql/src/semmle/javascript/frameworks/SQL.qll index 232307cc014..3d74dbdae3e 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/SQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/SQL.qll @@ -32,28 +32,25 @@ private module MySql { API::Node mysql() { result = API::moduleImport(["mysql", "mysql2"]) } /** Gets a reference to `mysql.createConnection`. */ - API::Node createConnectionCallee() { result = mysql().getMember("createConnection") } - - /** Gets a call to `mysql.createConnection`. */ - API::Node createConnection() { result = createConnectionCallee().getReturn() } + API::Node createConnection() { result = mysql().getMember("createConnection") } /** Gets a reference to `mysql.createPool`. */ - API::Node createPoolCallee() { result = mysql().getMember("createPool") } + API::Node createPool() { result = mysql().getMember("createPool") } - /** Gets a call to `mysql.createPool`. */ - API::Node createPool() { result = createPoolCallee().getReturn() } + /** Gets a node that contains a MySQL pool created using `mysql.createPool()`. */ + API::Node pool() { result = createPool().getReturn() } /** Gets a data flow node that contains a freshly created MySQL connection instance. */ API::Node connection() { - result = createConnection() + result = createConnection().getReturn() or - result = createPool().getMember("getConnection").getParameter(0).getParameter(1) + result = pool().getMember("getConnection").getParameter(0).getParameter(1) } /** A call to the MySql `query` method. */ private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { QueryCall() { - exists(API::Node recv | recv = createPool() or recv = connection() | + exists(API::Node recv | recv = pool() or recv = connection() | this = recv.getMember("query").getAReference().getACall() ) } @@ -70,7 +67,7 @@ private module MySql { class EscapingSanitizer extends SQL::SqlSanitizer, MethodCallExpr { EscapingSanitizer() { this = - [mysql(), createPool(), connection()] + [mysql(), pool(), connection()] .getMember(["escape", "escapeId"]) .getAReference() .getACall() @@ -86,7 +83,7 @@ private module MySql { Credentials() { exists(API::Node callee, string prop | - callee in [createConnectionCallee(), createPoolCallee()] and + callee in [createConnection(), createPool()] and this = callee.getParameter(0).getMember(prop).getARhs().asExpr() and ( prop = "user" and kind = "user name" From c3f5a6dcac88dc9cf459858a80a42aecee0c49cf Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 29 Sep 2020 18:17:36 +0200 Subject: [PATCH 110/411] introduce API::Node::getACall() --- javascript/ql/src/semmle/javascript/ApiGraphs.qll | 5 +++++ .../ql/src/semmle/javascript/frameworks/SQL.qll | 15 ++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 7688df124f2..4cb1f4cb8e0 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -45,6 +45,11 @@ module API { */ DataFlow::Node getAUse() { getAReference().flowsTo(result) } + /** + * Gets a call to a use of the API component represented by this node. + */ + DataFlow::CallNode getACall() { result = getAReference().getACall() } + /** * Gets a data-flow node corresponding to the right-hand side of a definition of the API * component represented by this node. diff --git a/javascript/ql/src/semmle/javascript/frameworks/SQL.qll b/javascript/ql/src/semmle/javascript/frameworks/SQL.qll index 3d74dbdae3e..28ff91c0380 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/SQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/SQL.qll @@ -51,7 +51,7 @@ private module MySql { private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { QueryCall() { exists(API::Node recv | recv = pool() or recv = connection() | - this = recv.getMember("query").getAReference().getACall() + this = recv.getMember("query").getACall() ) } @@ -69,7 +69,6 @@ private module MySql { this = [mysql(), pool(), connection()] .getMember(["escape", "escapeId"]) - .getAReference() .getACall() .asExpr() and input = this.getArgument(0) and @@ -129,7 +128,7 @@ private module Postgres { /** A call to the Postgres `query` method. */ private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { - QueryCall() { this = [client(), newPool()].getMember("query").getAReference().getACall() } + QueryCall() { this = [client(), newPool()].getMember("query").getACall() } override DataFlow::Node getAQueryArgument() { result = getArgument(0) } } @@ -187,7 +186,7 @@ private module Sqlite { meth = "prepare" or meth = "run" | - this = newDb().getMember(meth).getAReference().getACall() + this = newDb().getMember(meth).getACall() ) } @@ -231,7 +230,7 @@ private module MsSql { /** A call to a MsSql query method. */ private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { - QueryCall() { this = request().getMember(["query", "batch"]).getAReference().getACall() } + QueryCall() { this = request().getMember(["query", "batch"]).getACall() } override DataFlow::Node getAQueryArgument() { result = getArgument(0) } } @@ -290,7 +289,7 @@ private module Sequelize { /** A call to `Sequelize.query`. */ private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { - QueryCall() { this = newSequelize().getMember("query").getAReference().getACall() } + QueryCall() { this = newSequelize().getMember("query").getACall() } override DataFlow::Node getAQueryArgument() { result = getArgument(0) } } @@ -390,7 +389,6 @@ private module Spanner { this = database() .getMember(["run", "runPartitionedUpdate", "runStream"]) - .getAReference() .getACall() } } @@ -400,7 +398,7 @@ private module Spanner { */ class TransactionRunCall extends SqlExecution { TransactionRunCall() { - this = transaction().getMember(["run", "runStream", "runUpdate"]).getAReference().getACall() + this = transaction().getMember(["run", "runStream", "runUpdate"]).getACall() } } @@ -412,7 +410,6 @@ private module Spanner { this = v1SpannerClient() .getMember(["executeSql", "executeStreamingSql"]) - .getAReference() .getACall() } From 65441705ef9025149b2f39d12f4b6ac62f6aa344 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 29 Sep 2020 18:22:48 +0200 Subject: [PATCH 111/411] renamings based on review --- .../src/semmle/javascript/frameworks/SQL.qll | 38 ++++++------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/SQL.qll b/javascript/ql/src/semmle/javascript/frameworks/SQL.qll index 28ff91c0380..9089848b42f 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/SQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/SQL.qll @@ -66,11 +66,7 @@ private module MySql { /** A call to the `escape` or `escapeId` method that performs SQL sanitization. */ class EscapingSanitizer extends SQL::SqlSanitizer, MethodCallExpr { EscapingSanitizer() { - this = - [mysql(), pool(), connection()] - .getMember(["escape", "escapeId"]) - .getACall() - .asExpr() and + this = [mysql(), pool(), connection()].getMember(["escape", "escapeId"]).getACall().asExpr() and input = this.getArgument(0) and output = this } @@ -100,22 +96,19 @@ private module MySql { * Provides classes modelling the `pg` package. */ private module Postgres { - /** Gets an expression of the form `require('pg').Client`. */ - API::Node newClientCallee() { result = API::moduleImport("pg").getMember("Client") } + /** Gets a reference to the `Client` constructor in the `pg` package. E.g: `require('pg').Client`. */ + API::Node newClient() { result = API::moduleImport("pg").getMember("Client") } - /** Gets an expression of the form `new require('pg').Client()`. */ - API::Node newClient() { result = newClientCallee().getInstance() } - - /** Gets a data flow node that holds a freshly created Postgres client instance. */ + /** Gets a freshly created Postgres client instance. */ API::Node client() { - result = newClient() + result = newClient().getInstance() or // pool.connect(function(err, client) { ... }) - result = newPool().getMember("connect").getParameter(0).getParameter(1) + result = pool().getMember("connect").getParameter(0).getParameter(1) } /** Gets a constructor that when invoked constructs a new connection pool. */ - API::Node newPoolCallee() { + API::Node newPool() { // new require('pg').Pool() result = API::moduleImport("pg").getMember("Pool") or @@ -124,11 +117,11 @@ private module Postgres { } /** Gets an expression that constructs a new connection pool. */ - API::Node newPool() { result = newPoolCallee().getInstance() } + API::Node pool() { result = newPool().getInstance() } /** A call to the Postgres `query` method. */ private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { - QueryCall() { this = [client(), newPool()].getMember("query").getACall() } + QueryCall() { this = [client(), pool()].getMember("query").getACall() } override DataFlow::Node getAQueryArgument() { result = getArgument(0) } } @@ -144,8 +137,7 @@ private module Postgres { Credentials() { exists(string prop | - this = - [newClientCallee(), newPoolCallee()].getParameter(0).getMember(prop).getARhs().asExpr() and + this = [newClient(), newPool()].getParameter(0).getMember(prop).getARhs().asExpr() and ( prop = "user" and kind = "user name" or @@ -386,10 +378,7 @@ private module Spanner { */ class DatabaseRunCall extends SqlExecution { DatabaseRunCall() { - this = - database() - .getMember(["run", "runPartitionedUpdate", "runStream"]) - .getACall() + this = database().getMember(["run", "runPartitionedUpdate", "runStream"]).getACall() } } @@ -407,10 +396,7 @@ private module Spanner { */ class ExecuteSqlCall extends SqlExecution { ExecuteSqlCall() { - this = - v1SpannerClient() - .getMember(["executeSql", "executeStreamingSql"]) - .getACall() + this = v1SpannerClient().getMember(["executeSql", "executeStreamingSql"]).getACall() } override DataFlow::Node getAQueryArgument() { From d5f8cbc50c55e5a63e36e6c8111b49f0f6901d63 Mon Sep 17 00:00:00 2001 From: Ian Lynagh Date: Tue, 29 Sep 2020 14:24:04 +0100 Subject: [PATCH 112/411] C++: Accept test changes in unnamed entity naming --- .../lambdas/captures/elements.expected | 30 +++++++++---------- .../copy_from_prototype.expected | 12 ++++---- .../templates/CPP-202/template_args.expected | 4 +-- .../templates/decls/decls.expected | 2 +- .../library-tests/unnamed/elements.expected | 6 ++-- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/cpp/ql/test/library-tests/lambdas/captures/elements.expected b/cpp/ql/test/library-tests/lambdas/captures/elements.expected index 25bb695ea97..8ba9cad4009 100644 --- a/cpp/ql/test/library-tests/lambdas/captures/elements.expected +++ b/cpp/ql/test/library-tests/lambdas/captures/elements.expected @@ -13,9 +13,9 @@ | captures.cpp:3:5:3:5 | (constructor) | | captures.cpp:3:5:3:5 | (constructor) | | captures.cpp:3:5:3:5 | (constructor) | -| captures.cpp:3:5:3:5 | declaration of (null) | -| captures.cpp:3:5:3:5 | declaration of (null) | -| captures.cpp:3:5:3:5 | definition of (null) | +| captures.cpp:3:5:3:5 | declaration of (constructor) | +| captures.cpp:3:5:3:5 | declaration of (constructor) | +| captures.cpp:3:5:3:5 | definition of (constructor) | | captures.cpp:3:5:3:5 | definition of operator= | | captures.cpp:3:5:3:5 | operator= | | captures.cpp:3:5:5:5 | [...](...){...} | @@ -50,9 +50,9 @@ | captures.cpp:9:5:9:5 | (constructor) | | captures.cpp:9:5:9:5 | (constructor) | | captures.cpp:9:5:9:5 | (constructor) | -| captures.cpp:9:5:9:5 | declaration of (null) | -| captures.cpp:9:5:9:5 | declaration of (null) | -| captures.cpp:9:5:9:5 | definition of (null) | +| captures.cpp:9:5:9:5 | declaration of (constructor) | +| captures.cpp:9:5:9:5 | declaration of (constructor) | +| captures.cpp:9:5:9:5 | definition of (constructor) | | captures.cpp:9:5:9:5 | definition of operator= | | captures.cpp:9:5:9:5 | operator= | | captures.cpp:9:5:11:5 | [...](...){...} | @@ -87,9 +87,9 @@ | captures.cpp:15:5:15:5 | (constructor) | | captures.cpp:15:5:15:5 | (constructor) | | captures.cpp:15:5:15:5 | (constructor) | -| captures.cpp:15:5:15:5 | declaration of (null) | -| captures.cpp:15:5:15:5 | declaration of (null) | -| captures.cpp:15:5:15:5 | definition of (null) | +| captures.cpp:15:5:15:5 | declaration of (constructor) | +| captures.cpp:15:5:15:5 | declaration of (constructor) | +| captures.cpp:15:5:15:5 | definition of (constructor) | | captures.cpp:15:5:15:5 | definition of operator= | | captures.cpp:15:5:15:5 | operator= | | captures.cpp:15:5:17:5 | [...](...){...} | @@ -129,9 +129,9 @@ | captures.cpp:22:19:22:19 | Unknown literal | | captures.cpp:22:19:22:19 | constructor init of field x | | captures.cpp:22:19:22:19 | constructor init of field y | -| captures.cpp:22:19:22:19 | declaration of (null) | -| captures.cpp:22:19:22:19 | definition of (null) | -| captures.cpp:22:19:22:19 | definition of (null) | +| captures.cpp:22:19:22:19 | declaration of (constructor) | +| captures.cpp:22:19:22:19 | definition of (constructor) | +| captures.cpp:22:19:22:19 | definition of (constructor) | | captures.cpp:22:19:22:19 | definition of operator= | | captures.cpp:22:19:22:19 | operator= | | captures.cpp:22:19:22:19 | return ... | @@ -187,9 +187,9 @@ | end_pos.cpp:9:15:9:15 | (constructor) | | end_pos.cpp:9:15:9:15 | Unknown literal | | end_pos.cpp:9:15:9:15 | constructor init of field ii | -| end_pos.cpp:9:15:9:15 | declaration of (null) | -| end_pos.cpp:9:15:9:15 | definition of (null) | -| end_pos.cpp:9:15:9:15 | definition of (null) | +| end_pos.cpp:9:15:9:15 | declaration of (constructor) | +| end_pos.cpp:9:15:9:15 | definition of (constructor) | +| end_pos.cpp:9:15:9:15 | definition of (constructor) | | end_pos.cpp:9:15:9:15 | definition of operator= | | end_pos.cpp:9:15:9:15 | operator= | | end_pos.cpp:9:15:9:15 | return ... | diff --git a/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected b/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected index f5ef2d77c98..5488cf803e6 100644 --- a/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected +++ b/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected @@ -2,8 +2,8 @@ | copy_from_prototype.cpp:3:7:3:7 | a | a::a(const a &) -> void | copy_from_prototype.cpp:3:7:3:7 | a | | | copy_from_prototype.cpp:3:7:3:7 | operator= | a::operator=(a &&) -> a & | copy_from_prototype.cpp:3:7:3:7 | a | | | copy_from_prototype.cpp:3:7:3:7 | operator= | a::operator=(const a &) -> a & | copy_from_prototype.cpp:3:7:3:7 | a | | -| copy_from_prototype.cpp:4:26:4:26 | a | a<>::a<(unnamed)>() -> void | copy_from_prototype.cpp:3:7:3:7 | a<> | 123 | -| copy_from_prototype.cpp:4:26:4:26 | a | a::a<(unnamed)>() -> void | copy_from_prototype.cpp:3:7:3:7 | a | | +| copy_from_prototype.cpp:4:26:4:26 | a | a<>::a<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:3:7:3:7 | a<> | 123 | +| copy_from_prototype.cpp:4:26:4:26 | a | a::a<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:3:7:3:7 | a | | | copy_from_prototype.cpp:7:7:7:7 | b | b::b() -> void | copy_from_prototype.cpp:7:7:7:7 | b | | | copy_from_prototype.cpp:7:7:7:7 | b | b::b(b &&) -> void | copy_from_prototype.cpp:7:7:7:7 | b | | | copy_from_prototype.cpp:7:7:7:7 | b | b::b(const b &) -> void | copy_from_prototype.cpp:7:7:7:7 | b | | @@ -13,8 +13,8 @@ | copy_from_prototype.cpp:13:7:13:7 | c | c::c(const c &) -> void | copy_from_prototype.cpp:13:7:13:7 | c | | | copy_from_prototype.cpp:13:7:13:7 | operator= | c::operator=(c &&) -> c & | copy_from_prototype.cpp:13:7:13:7 | c | | | copy_from_prototype.cpp:13:7:13:7 | operator= | c::operator=(const c &) -> c & | copy_from_prototype.cpp:13:7:13:7 | c | | -| copy_from_prototype.cpp:14:26:14:26 | c | c::c<(unnamed)>() -> void | copy_from_prototype.cpp:13:7:13:7 | c | X | -| copy_from_prototype.cpp:14:26:14:26 | c | c::c<(unnamed)>() -> void | copy_from_prototype.cpp:13:7:13:7 | c | | +| copy_from_prototype.cpp:14:26:14:26 | c | c::c<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:13:7:13:7 | c | X | +| copy_from_prototype.cpp:14:26:14:26 | c | c::c<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:13:7:13:7 | c | | | copy_from_prototype.cpp:17:7:17:7 | d | d::d() -> void | copy_from_prototype.cpp:17:7:17:7 | d | | | copy_from_prototype.cpp:17:7:17:7 | d | d::d(const d &) -> void | copy_from_prototype.cpp:17:7:17:7 | d | | | copy_from_prototype.cpp:17:7:17:7 | d | d::d(d &&) -> void | copy_from_prototype.cpp:17:7:17:7 | d | | @@ -24,7 +24,7 @@ | copy_from_prototype.cpp:22:8:22:8 | e | e::e(e &&) -> void | copy_from_prototype.cpp:22:8:22:8 | e | | | copy_from_prototype.cpp:22:8:22:8 | operator= | e::operator=(const e &) -> e & | copy_from_prototype.cpp:22:8:22:8 | e | | | copy_from_prototype.cpp:22:8:22:8 | operator= | e::operator=(e &&) -> e & | copy_from_prototype.cpp:22:8:22:8 | e | | -| copy_from_prototype.cpp:23:26:23:26 | e | e::e<(unnamed)>() -> void | copy_from_prototype.cpp:22:8:22:8 | e | 456 | -| copy_from_prototype.cpp:26:35:26:43 | e | e::e<(unnamed)>() -> void | copy_from_prototype.cpp:22:8:22:8 | e | 456 | +| copy_from_prototype.cpp:23:26:23:26 | e | e::e<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:22:8:22:8 | e | 456 | +| copy_from_prototype.cpp:26:35:26:43 | e | e::e<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:22:8:22:8 | e | 456 | | file://:0:0:0:0 | operator= | __va_list_tag::operator=(__va_list_tag &&) -> __va_list_tag & | file://:0:0:0:0 | __va_list_tag | | | file://:0:0:0:0 | operator= | __va_list_tag::operator=(const __va_list_tag &) -> __va_list_tag & | file://:0:0:0:0 | __va_list_tag | | diff --git a/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected b/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected index f38eef610e4..c1d6e7fe9fa 100644 --- a/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected +++ b/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected @@ -1,7 +1,7 @@ | file://:0:0:0:0 | __va_list_tag | | | test.cpp:3:8:3:9 | s1<> | {...} | -| test.cpp:3:8:3:9 | s1<> | (null) | +| test.cpp:3:8:3:9 | s1<> | (unnamed template parameter constant) | | test.cpp:5:8:5:9 | s2 | T | | test.cpp:5:8:5:9 | s2 | T | -| test.cpp:7:8:7:9 | s3> | (unnamed) | +| test.cpp:7:8:7:9 | s3> | (unnamed template parameter) | | test.cpp:7:8:7:9 | s3> | T | diff --git a/cpp/ql/test/library-tests/templates/decls/decls.expected b/cpp/ql/test/library-tests/templates/decls/decls.expected index 43a691e53c9..cfb16b63828 100644 --- a/cpp/ql/test/library-tests/templates/decls/decls.expected +++ b/cpp/ql/test/library-tests/templates/decls/decls.expected @@ -7,7 +7,7 @@ | decls.cpp:4:30:4:34 | p#0 | | decls.cpp:4:30:4:34 | p#0 | | decls.cpp:6:17:6:17 | f | -| decls.cpp:8:18:8:18 | (unnamed) | +| decls.cpp:8:18:8:18 | (unnamed template parameter) | | decls.cpp:8:25:8:25 | g | | file://:0:0:0:0 | __va_list_tag | | file://:0:0:0:0 | auto | diff --git a/cpp/ql/test/library-tests/unnamed/elements.expected b/cpp/ql/test/library-tests/unnamed/elements.expected index 8df7d4578a2..52176aa66df 100644 --- a/cpp/ql/test/library-tests/unnamed/elements.expected +++ b/cpp/ql/test/library-tests/unnamed/elements.expected @@ -1,6 +1,6 @@ | file://:0:0:0:0 | | Other | | file://:0:0:0:0 | (global namespace) | Other | -| file://:0:0:0:0 | | Other | +| file://:0:0:0:0 | (unnamed global/namespace variable) | Other | | file://:0:0:0:0 | _Complex __float128 | Other | | file://:0:0:0:0 | _Complex double | Other | | file://:0:0:0:0 | _Complex float | Other | @@ -111,8 +111,8 @@ | test.c:0:0:0:0 | test.c | Other | | test.c:2:6:2:6 | a | Other | | test.c:2:6:2:6 | definition of a | Other | -| test.c:2:10:2:18 | | Variable access | +| test.c:2:10:2:18 | (unnamed global/namespace variable) | Variable access | | test.c:2:10:2:18 | array to pointer conversion | Other | | test.c:2:10:2:18 | initializer for a | Other | -| test.c:2:17:2:18 | initializer for | Other | +| test.c:2:17:2:18 | initializer for (unnamed global/namespace variable) | Other | | test.c:2:17:2:18 | {...} | Other | From 68f6d9332523df633415e8550818a760c57f985b Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 30 Sep 2020 09:49:56 +0200 Subject: [PATCH 113/411] C++: Autoformat fixup --- cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 9bbedfc16a8..09409eb30f2 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -184,7 +184,7 @@ class ImplicitParameterNode extends ParameterNode, TInstanceParameterNode { /** * INTERNAL: do not use. - * + * * A node that represents the value of a variable after a function call that * may have changed the variable because it's passed by reference or because an * iterator for it was passed by value or by reference. From e0b25798ff46378de19b717b995f5fcc60b02293 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 30 Sep 2020 10:36:08 +0200 Subject: [PATCH 114/411] remove type-tracking from `getAReference`, and rewrite qldocs --- .../ql/src/semmle/javascript/ApiGraphs.qll | 38 ++++++++++++------- .../src/semmle/javascript/frameworks/SQL.qll | 2 +- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 4cb1f4cb8e0..8d8e124259e 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -21,34 +21,44 @@ module API { */ class Node extends Impl::TApiNode { /** - * Gets a `SourceNode` corresponding to a use of the API component represented by this node. + * Gets a data-flow corresponding to a use of the API component represented by this node. * * For example, `require('fs').readFileSync` is a use of the function `readFileSync` from the - * `fs` module, and `require('fs').readFileSync(file)` is a use of the result of that function. + * `fs` module, and `require('fs').readFileSync(file)` is a use of the return of that function. + * + * The use is type-tracked, meaning that in `f(obj.foo); function f(x) {};` both `obj.foo` and + * `x` are uses of the `foo` member from `obj`. * * As another example, in the assignment `exports.plusOne = (x) => x+1` the two references to * `x` are uses of the first parameter of `plusOne`. - * - * Note: The result from this predicate is always a `DataFlow::SourceǸode`, use `getAUse()` if - * you want to follow purely local data-flow and get all `DataFlow::Node`s that corrospond to a - * use of this API node. */ - DataFlow::SourceNode getAReference() { - exists(DataFlow::SourceNode src | Impl::use(this, src) | result = Impl::trackUseNode(src)) + DataFlow::Node getAUse() { + exists(DataFlow::SourceNode src | Impl::use(this, src) | + Impl::trackUseNode(src).flowsTo(result) + ) } /** - * Gets a data-flow node corresponding to a use of the API component represented by this node. + * Gets a reference to the API component represented by this node. * - * This predicate is similar to `getAReference`, except this prediate also follows purely local - * data-flow. + * For example, `require('fs').readFileSync` is a reference to the `readFileSync` member from the + * `fs` module. + * + * No local data-flow or type-tracking happens on the result, which means that in + * `const x = fs.readFile` only `fs.readFile` is a reference to the `readFile` member of `fs`, + * neither `x` nor any node that `x` flows to is a reference to this API component. */ - DataFlow::Node getAUse() { getAReference().flowsTo(result) } + DataFlow::SourceNode getAReference() { Impl::use(this, result) } /** - * Gets a call to a use of the API component represented by this node. + * Gets a call to the function represented by this API component. */ - DataFlow::CallNode getACall() { result = getAReference().getACall() } + DataFlow::CallNode getACall() { result = getReturn().getAReference() } + + /** + * Gets an instantiation of the function represented by this API component. + */ + DataFlow::NewNode getAnInstantiation() { result = getInstance().getAReference() } /** * Gets a data-flow node corresponding to the right-hand side of a definition of the API diff --git a/javascript/ql/src/semmle/javascript/frameworks/SQL.qll b/javascript/ql/src/semmle/javascript/frameworks/SQL.qll index 9089848b42f..86393cf5d58 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/SQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/SQL.qll @@ -300,7 +300,7 @@ private module Sequelize { Credentials() { exists(NewExpr ne, string prop | - ne = sequelize().getAReference().getAnInstantiation().asExpr() and + ne = sequelize().getAnInstantiation().asExpr() and ( this = ne.getArgument(1) and prop = "username" or From aa6fad558cfa863c24cc2857c3e57414a8391261 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 30 Sep 2020 11:15:53 +0200 Subject: [PATCH 115/411] Python: Minor cleanup in taint-step tests --- .../defaultAdditionalTaintStep-py3/test_string.py | 4 ++-- .../tainttracking/defaultAdditionalTaintStep/test_string.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/test_string.py b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/test_string.py index 530d33a24c5..2f63f8af460 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/test_string.py +++ b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/test_string.py @@ -22,7 +22,7 @@ def str_methods(): def binary_decode_encode(): - print("\n#percent_fmt") + print("\n# binary_decode_encode") tb = TAINTED_BYTES import base64 @@ -42,7 +42,7 @@ def binary_decode_encode(): def f_strings(): - print("\n#f_strings") + print("\n# f_strings") ts = TAINTED_STRING ensure_tainted(f"foo {ts} bar") diff --git a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_string.py b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_string.py index 4ede960d2f8..91f69904a97 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_string.py +++ b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_string.py @@ -107,7 +107,7 @@ def non_syntactic(): def percent_fmt(): - print("\n#percent_fmt") + print("\n# percent_fmt") ts = TAINTED_STRING tainted_fmt = ts + " %s %s" ensure_tainted( @@ -118,7 +118,7 @@ def percent_fmt(): def binary_decode_encode(): - print("\n#percent_fmt") + print("\n# binary_decode_encode") tb = TAINTED_BYTES import base64 From efa248471831fe521f88a781d7f61ee9ea7f2b13 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 30 Sep 2020 11:16:15 +0200 Subject: [PATCH 116/411] Python: Add taint test for os.path.join Surprisingly the first two just worked, due to our very general handling of any `join` methods :D --- .../dataflow/internal/TaintTrackingPrivate.qll | 2 +- .../defaultAdditionalTaintStep/TestTaint.expected | 3 +++ .../defaultAdditionalTaintStep/test_string.py | 12 ++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/python/ql/src/experimental/dataflow/internal/TaintTrackingPrivate.qll b/python/ql/src/experimental/dataflow/internal/TaintTrackingPrivate.qll index 68e1e9fc283..4087ab1b964 100644 --- a/python/ql/src/experimental/dataflow/internal/TaintTrackingPrivate.qll +++ b/python/ql/src/experimental/dataflow/internal/TaintTrackingPrivate.qll @@ -101,7 +101,7 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT nodeFrom.getNode() = object and method_name in ["partition", "rpartition", "rsplit", "split", "splitlines"] or - // List[str] -> str + // Iterable[str] -> str // TODO: check if these should be handled differently in regards to content method_name = "join" and nodeFrom.getNode() = call.getArg(0) diff --git a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/TestTaint.expected b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/TestTaint.expected index c1a903382df..83424353c41 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/TestTaint.expected +++ b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/TestTaint.expected @@ -137,6 +137,9 @@ | test_string.py:143 | fail | binary_decode_encode | base64.decodestring(..) | | test_string.py:148 | fail | binary_decode_encode | quopri.encodestring(..) | | test_string.py:149 | fail | binary_decode_encode | quopri.decodestring(..) | +| test_string.py:158 | ok | test_os_path_join | os.path.join(..) | +| test_string.py:159 | ok | test_os_path_join | os.path.join(..) | +| test_string.py:160 | fail | test_os_path_join | os.path.join(..) | | test_unpacking.py:16 | ok | unpacking | a | | test_unpacking.py:16 | ok | unpacking | b | | test_unpacking.py:16 | ok | unpacking | c | diff --git a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_string.py b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_string.py index 91f69904a97..a7422f0ad4c 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_string.py +++ b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_string.py @@ -150,6 +150,17 @@ def binary_decode_encode(): ) +def test_os_path_join(): + import os + print("\n# test_os_path_join") + ts = TAINTED_STRING + ensure_tainted( + os.path.join(ts, "foo", "bar"), + os.path.join(ts), + os.path.join("foo", "bar", ts), + ) + + # Make tests runable str_operations() @@ -157,3 +168,4 @@ str_methods() non_syntactic() percent_fmt() binary_decode_encode() +test_os_path_join() From 0542c3b91e299f6d2efdff9e624106ddb63cd522 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 30 Sep 2020 11:42:36 +0200 Subject: [PATCH 117/411] Python: Model os.path.join and add taint-step --- .../internal/TaintTrackingPrivate.qll | 1 - .../semmle/python/frameworks/Stdlib.qll | 50 +++++++++++++++++++ .../TestTaint.expected | 2 +- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/python/ql/src/experimental/dataflow/internal/TaintTrackingPrivate.qll b/python/ql/src/experimental/dataflow/internal/TaintTrackingPrivate.qll index 4087ab1b964..d49ff207370 100644 --- a/python/ql/src/experimental/dataflow/internal/TaintTrackingPrivate.qll +++ b/python/ql/src/experimental/dataflow/internal/TaintTrackingPrivate.qll @@ -130,7 +130,6 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT // f-strings nodeTo.asExpr().(Fstring).getAValue() = nodeFrom.asExpr() // TODO: Handle encode/decode from base64/quopri - // TODO: Handle os.path.join // TODO: Handle functions in https://docs.python.org/3/library/binascii.html } diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 7587e9187b2..05ea6763bd8 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -5,9 +5,11 @@ private import python private import experimental.dataflow.DataFlow +private import experimental.dataflow.TaintTracking private import experimental.dataflow.RemoteFlowSources private import experimental.semmle.python.Concepts +/** Provides models for the Python standard library. */ private module Stdlib { /** Gets a reference to the `os` module. */ DataFlow::Node os(DataFlow::TypeTracker t) { @@ -20,6 +22,7 @@ private module Stdlib { /** Gets a reference to the `os` module. */ DataFlow::Node os() { result = os(DataFlow::TypeTracker::end()) } + /** Provides models for the `os` module. */ module os { /** Gets a reference to the `os.system` function. */ DataFlow::Node system(DataFlow::TypeTracker t) { @@ -48,6 +51,41 @@ private module Stdlib { /** Gets a reference to the `os.popen` function. */ DataFlow::Node popen() { result = os::popen(DataFlow::TypeTracker::end()) } + + /** Gets a reference to the `os.path` module. */ + private DataFlow::Node path(DataFlow::TypeTracker t) { + t.start() and + ( + result = DataFlow::importMember("os", "path") + or + result = DataFlow::importModule("os.path") + ) + or + t.startInAttr("path") and + result = os() + or + exists(DataFlow::TypeTracker t2 | result = path(t2).track(t2, t)) + } + + /** Gets a reference to the `os.path` module. */ + DataFlow::Node path() { result = path(DataFlow::TypeTracker::end()) } + + /** Provides models for the `os.path` module */ + module path { + /** Gets a reference to the `os.path.join` function. */ + private DataFlow::Node join(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importMember("os.path", "join") + or + t.startInAttr("join") and + result = os::path() + or + exists(DataFlow::TypeTracker t2 | result = join(t2).track(t2, t)) + } + + /** Gets a reference to the `os.join` module. */ + DataFlow::Node join() { result = join(DataFlow::TypeTracker::end()) } + } } /** @@ -73,4 +111,16 @@ private module Stdlib { result.asCfgNode() = this.asCfgNode().(CallNode).getArg(0) } } + + /** An additional taint step for calls to `os.path.join` */ + private class OsPathJoinCallAdditionalTaintStep extends TaintTracking::AdditionalTaintStep { + override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + exists(CallNode call | + nodeTo.asCfgNode() = call and + call.getFunction() = os::path::join().asCfgNode() and + call.getAnArg() = nodeFrom.asCfgNode() + ) + // TODO: Handle pathlib (like we do for os.path.join) + } + } } diff --git a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/TestTaint.expected b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/TestTaint.expected index 83424353c41..28dea1f3851 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/TestTaint.expected +++ b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/TestTaint.expected @@ -139,7 +139,7 @@ | test_string.py:149 | fail | binary_decode_encode | quopri.decodestring(..) | | test_string.py:158 | ok | test_os_path_join | os.path.join(..) | | test_string.py:159 | ok | test_os_path_join | os.path.join(..) | -| test_string.py:160 | fail | test_os_path_join | os.path.join(..) | +| test_string.py:160 | ok | test_os_path_join | os.path.join(..) | | test_unpacking.py:16 | ok | unpacking | a | | test_unpacking.py:16 | ok | unpacking | b | | test_unpacking.py:16 | ok | unpacking | c | From 1595fed2d6760b11953238c946796f918ba0f613 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 30 Sep 2020 11:44:37 +0200 Subject: [PATCH 118/411] Python: Add preliminary taint tests for pathlib --- .../TestTaint.expected | 12 ++++ .../test_pathlib.py | 60 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/test_pathlib.py diff --git a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/TestTaint.expected b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/TestTaint.expected index 7bca8bd1604..ec24283300f 100644 --- a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/TestTaint.expected +++ b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/TestTaint.expected @@ -1,6 +1,18 @@ | test_collections.py:16 | ok | test_access | tainted_list.copy() | | test_collections.py:24 | ok | list_clear | tainted_list | | test_collections.py:27 | fail | list_clear | tainted_list | +| test_pathlib.py:26 | fail | test_basic | tainted_path | +| test_pathlib.py:28 | fail | test_basic | tainted_pure_path | +| test_pathlib.py:29 | fail | test_basic | tainted_pure_posix_path | +| test_pathlib.py:30 | fail | test_basic | tainted_pure_windows_path | +| test_pathlib.py:32 | fail | test_basic | BinaryExpr | +| test_pathlib.py:33 | fail | test_basic | BinaryExpr | +| test_pathlib.py:35 | fail | test_basic | tainted_path.joinpath(..) | +| test_pathlib.py:36 | fail | test_basic | pathlib.Path(..).joinpath(..) | +| test_pathlib.py:37 | fail | test_basic | pathlib.Path(..).joinpath(..) | +| test_pathlib.py:39 | fail | test_basic | str(..) | +| test_pathlib.py:49 | fail | test_basic | tainted_posix_path | +| test_pathlib.py:55 | fail | test_basic | tainted_windows_path | | test_string.py:17 | ok | str_methods | ts.casefold() | | test_string.py:19 | ok | str_methods | ts.format_map(..) | | test_string.py:20 | ok | str_methods | "{unsafe}".format_map(..) | diff --git a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/test_pathlib.py b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/test_pathlib.py new file mode 100644 index 00000000000..802bfd98b12 --- /dev/null +++ b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/test_pathlib.py @@ -0,0 +1,60 @@ +# Add taintlib to PATH so it can be imported during runtime without any hassle +import sys; import os; sys.path.append(os.path.dirname(os.path.dirname((__file__)))) +from taintlib import * + +# This has no runtime impact, but allows autocomplete to work +from typing import Iterable, TYPE_CHECKING +if TYPE_CHECKING: + from ..taintlib import * + +# Actual tests + +import pathlib +# pathlib was added in 3.4 + +def test_basic(): + print("\n# test_basic") + ts = TAINTED_STRING + + tainted_path = pathlib.Path(ts) + + tainted_pure_path = pathlib.PurePath(ts) + tainted_pure_posix_path = pathlib.PurePosixPath(ts) + tainted_pure_windows_path = pathlib.PureWindowsPath(ts) + + ensure_tainted( + tainted_path, + + tainted_pure_path, + tainted_pure_posix_path, + tainted_pure_windows_path, + + pathlib.Path("foo") / ts, + ts / pathlib.Path("foo"), + + tainted_path.joinpath("foo", "bar"), + pathlib.Path("foo").joinpath(tainted_path, "bar"), + pathlib.Path("foo").joinpath("bar", tainted_path), + + str(tainted_path), + + # TODO: Tainted methods and attributes + # https://docs.python.org/3.8/library/pathlib.html#methods-and-properties + ) + + if os.name == "posix": + tainted_posix_path = pathlib.PosixPath(ts) + + ensure_tainted( + tainted_posix_path, + ) + + if os.name == "nt": + tainted_windows_path = pathlib.WindowsPath(ts) + ensure_tainted( + tainted_windows_path, + ) + +# Make tests runable + +test_basic() From 6db4f839cbd769870d0f610e1c11c85f96e8e202 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Wed, 23 Sep 2020 18:07:16 +0200 Subject: [PATCH 119/411] Java: add Android database taint and SQL injection sinks --- .../dataflow/internal/TaintTrackingUtil.qll | 54 ++++++++ .../code/java/security/QueryInjection.qll | 124 ++++++++++++++++++ 2 files changed, 178 insertions(+) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index eaf7c9d26dc..7e27ab1a04b 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -387,6 +387,17 @@ private predicate taintPreservingQualifierToMethod(Method m) { stringlist.getTypeArgument(0) instanceof TypeString ) ) + or + m + .getDeclaringType() + .getASourceSupertype*() + .hasQualifiedName("android.database.sqlite", "SQLiteQueryBuilder") and + // buildQuery(String[] projectionIn, String selection, String groupBy, String having, String sortOrder, String limit) + // buildQuery(String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit) + // buildUnionQuery(String[] subQueries, String sortOrder, String limit) + // buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, Set columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, String selection, String[] selectionArgs, String groupBy, String having) + // buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, Set columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, String selection, String groupBy, String having) + m.hasName(["buildQuery", "buildUnionQuery", "buildUnionSubQuery"]) } private class StringReplaceMethod extends Method { @@ -447,6 +458,20 @@ private predicate argToMethodStep(Expr tracked, MethodAccess sink) { private predicate taintPreservingArgumentToMethod(Method method) { method.getDeclaringType() instanceof TypeString and (method.hasName("format") or method.hasName("formatted") or method.hasName("join")) + or + method.getDeclaringType().hasQualifiedName("android.database", "DatabaseUtils") and + // String[] appendSelectionArgs(String[] originalValues, String[] newValues) + // String concatenateWhere(String a, String b) + method.hasName(["appendSelectionArgs", "concatenateWhere"]) + or + method + .getDeclaringType() + .getASourceSupertype*() + .hasQualifiedName("android.database.sqlite", "SQLiteQueryBuilder") and + // buildQuery(String[] projectionIn, String selection, String groupBy, String having, String sortOrder, String limit) + // buildQuery(String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit) + // buildUnionQuery(String[] subQueries, String sortOrder, String limit) + method.hasName(["buildQuery", "buildUnionQuery"]) } /** @@ -560,6 +585,18 @@ private predicate taintPreservingArgumentToMethod(Method method, int arg) { method.getDeclaringType().hasQualifiedName("java.io", "StringWriter") and method.hasName("append") and arg = 0 + or + method.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and + ( + // static buildQueryString(boolean distinct, String tables, String[] columns, String where, String groupBy, String having, String orderBy, String limit) + method.hasName("buildQueryString") and arg = [1 .. method.getNumberOfParameters()] + or + // buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, Set columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, String selection, String[] selectionArgs, String groupBy, String having) + // buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, Set columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, String selection, String groupBy, String having) + method.hasName("buildUnionSubQuery") and + arg = [0 .. method.getNumberOfParameters()] and + arg != 3 + ) } /** @@ -612,6 +649,12 @@ private predicate taintPreservingArgToArg(Method method, int input, int output) method.getNumberOfParameters() > 1 and input = method.getNumberOfParameters() - 1 and output = 0 + or + method.getDeclaringType().hasQualifiedName("android.database.sqlite", "SQLiteQueryBuilder") and + // static appendColumns(StringBuilder s, String[] columns) + method.hasName("appendColumns") and + input = 1 and + output = 0 } /** @@ -649,6 +692,17 @@ private predicate taintPreservingArgumentToQualifier(Method method, int arg) { arg = 0 and append.getDeclaringType().hasQualifiedName("java.io", "StringWriter") ) + or + method + .getDeclaringType() + .getASourceSupertype*() + .hasQualifiedName("android.database.sqlite", "SQLiteQueryBuilder") and + // setProjectionMap(Map columnMap) + // setTables(String inTables) + // appendWhere(CharSequence inWhere) + // appendWhereStandalone(CharSequence inWhere) + method.hasName(["setProjectionMap", "setTables", "appendWhere", "appendWhereStandalone"]) and + arg = 0 } /** A comparison or equality test with a constant. */ diff --git a/java/ql/src/semmle/code/java/security/QueryInjection.qll b/java/ql/src/semmle/code/java/security/QueryInjection.qll index 574229a5ae4..10dfa8bc4e8 100644 --- a/java/ql/src/semmle/code/java/security/QueryInjection.qll +++ b/java/ql/src/semmle/code/java/security/QueryInjection.qll @@ -90,3 +90,127 @@ private class MongoJsonStep extends AdditionalQueryInjectionTaintStep { ) } } + +/** A sink for Android database injection vulnerabilities. */ +private class AndroidDatabaseUtils extends QueryInjectionSink { + AndroidDatabaseUtils() { + exists(MethodAccess call, Method method | + method = call.getMethod() and + method.getDeclaringType().hasQualifiedName("android.database", "DatabaseUtils") and + ( + // (blobFileDescriptor|long|string)ForQuery(SQLiteDatabase db, String query, String[] selectionArgs) + method.hasName(["blobFileDescriptorForQuery", "longForQuery", "stringForQuery"]) and + method.getNumberOfParameters() = 3 and + this.asExpr() = call.getArgument(1) + or + // createDbFromSqlStatements(Context context, String dbName, int dbVersion, String sqlStatements) + method.hasName("createDbFromSqlStatements") and + this.asExpr() = call.getArgument(3) + or + // queryNumEntries(SQLiteDatabase db, String table, String selection) + // queryNumEntries(SQLiteDatabase db, String table, String selection, String[] selectionArgs) + method.hasName("queryNumEntries") and + this.asExpr() = call.getArgument(2) + ) + or + method + .getDeclaringType() + .getASourceSupertype*() + .hasQualifiedName("android.database.sqlite", "SQLiteDatabase") and + ( + // compileStatement(String sql) + method.hasName("compileStatement") and + this.asExpr() = call.getArgument(0) + or + // delete(String table, String whereClause, String[] whereArgs) + method.hasName("delete") and + this.asExpr() = call.getArgument(1) + or + // execPerConnectionSQL(String sql, Object[] bindArgs) + // execSQL(String sql) + // execSQL(String sql, Object[] bindArgs) + method.hasName(["execPerConnectionSQL", "execSQL"]) and + this.asExpr() = call.getArgument(0) + or + // query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) + // query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal) + // query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) + // query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) + method.hasName("query") and + ( + this.asExpr() = call.getArgument([3, 5, 6, 7, 8]) and + method.getNumberOfParameters() = [9, 10] + or + this.asExpr() = call.getArgument([2, 4, 5, 6, 7]) and + method.getNumberOfParameters() = [7, 8] + ) + or + // queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal) + // queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) + method.hasName("queryWithFactory") and + this.asExpr() = call.getArgument([4, 6, 7, 8, 9]) + or + // rawQuery(String sql, String[] selectionArgs, CancellationSignal cancellationSignal) + // rawQuery(String sql, String[] selectionArgs) + method.hasName("rawQuery") and + this.asExpr() = call.getArgument(0) + or + // rawQueryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable, CancellationSignal cancellationSignal) + // rawQueryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable) + method.hasName("rawQueryWithFactory") and + this.asExpr() = call.getArgument(1) + or + // update(String table, ContentValues values, String whereClause, String[] whereArgs) + // updateWithOnConflict(String table, ContentValues values, String whereClause, String[] whereArgs, int conflictAlgorithm) + method.hasName(["update", "updateWithOnConflict"]) and + this.asExpr() = call.getArgument(2) + ) + or + method + .getDeclaringType() + .getASourceSupertype*() + .hasQualifiedName("android.content", "ContentProvider") and + ( + // delete(Uri uri, String selection, String[] selectionArgs) + method.hasName("delete") and + this.asExpr() = call.getArgument(1) and + method.getNumberOfParameters() = 3 + or + // query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) + // query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) + method.hasName("query") and + method.getNumberOfParameters() = [5, 6] and + this.asExpr() = call.getArgument(2) + or + // update(Uri uri, ContentValues values, String selection, String[] selectionArgs) + method.hasName("update") and + this.asExpr() = call.getArgument(2) and + method.getNumberOfParameters() = 4 + ) + or + method + .getDeclaringType() + .getASourceSupertype*() + .hasQualifiedName("android.database.sqlite", "SQLiteQueryBuilder") and + ( + // delete(SQLiteDatabase db, String selection, String[] selectionArgs) + method.hasName("delete") and + (this.asExpr() = call.getArgument(1) or this.asExpr() = call.getQualifier()) + or + // insert(SQLiteDatabase db, ContentValues values) + method.hasName("update") and + this.asExpr() = call.getQualifier() + or + // query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder) + // query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit) + // query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit, CancellationSignal cancellationSignal) + method.hasName("query") and + (this.asExpr() = call.getArgument([3, 5, 6, 7, 8]) or this.asExpr() = call.getQualifier()) + or + // update(SQLiteDatabase db, ContentValues values, String selection, String[] selectionArgs) + method.hasName("update") and + (this.asExpr() = call.getArgument(2) or this.asExpr() = call.getQualifier()) + ) + ) + } +} From b3aae276baf5fbf633ad6dbd0b229badb49ef352 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Mon, 28 Sep 2020 18:22:12 +0200 Subject: [PATCH 120/411] Add types to SQLite.qll --- .../dataflow/internal/TaintTrackingUtil.qll | 20 ++++++------------- .../code/java/frameworks/android/SQLite.qll | 17 ++++++++++++++++ 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index 7e27ab1a04b..c31f6f3d940 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -6,6 +6,7 @@ private import semmle.code.java.dataflow.DefUse private import semmle.code.java.security.SecurityTests private import semmle.code.java.security.Validation private import semmle.code.java.frameworks.android.Intent +private import semmle.code.java.frameworks.android.SQLite private import semmle.code.java.frameworks.Guice private import semmle.code.java.frameworks.Protobuf private import semmle.code.java.frameworks.spring.SpringController @@ -388,10 +389,7 @@ private predicate taintPreservingQualifierToMethod(Method m) { ) ) or - m - .getDeclaringType() - .getASourceSupertype*() - .hasQualifiedName("android.database.sqlite", "SQLiteQueryBuilder") and + m.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and // buildQuery(String[] projectionIn, String selection, String groupBy, String having, String sortOrder, String limit) // buildQuery(String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit) // buildUnionQuery(String[] subQueries, String sortOrder, String limit) @@ -459,15 +457,12 @@ private predicate taintPreservingArgumentToMethod(Method method) { method.getDeclaringType() instanceof TypeString and (method.hasName("format") or method.hasName("formatted") or method.hasName("join")) or - method.getDeclaringType().hasQualifiedName("android.database", "DatabaseUtils") and + method.getDeclaringType() instanceof TypeDatabaseUtils and // String[] appendSelectionArgs(String[] originalValues, String[] newValues) // String concatenateWhere(String a, String b) method.hasName(["appendSelectionArgs", "concatenateWhere"]) or - method - .getDeclaringType() - .getASourceSupertype*() - .hasQualifiedName("android.database.sqlite", "SQLiteQueryBuilder") and + method.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and // buildQuery(String[] projectionIn, String selection, String groupBy, String having, String sortOrder, String limit) // buildQuery(String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit) // buildUnionQuery(String[] subQueries, String sortOrder, String limit) @@ -650,7 +645,7 @@ private predicate taintPreservingArgToArg(Method method, int input, int output) input = method.getNumberOfParameters() - 1 and output = 0 or - method.getDeclaringType().hasQualifiedName("android.database.sqlite", "SQLiteQueryBuilder") and + method.getDeclaringType() instanceof TypeSQLiteQueryBuilder and // static appendColumns(StringBuilder s, String[] columns) method.hasName("appendColumns") and input = 1 and @@ -693,10 +688,7 @@ private predicate taintPreservingArgumentToQualifier(Method method, int arg) { append.getDeclaringType().hasQualifiedName("java.io", "StringWriter") ) or - method - .getDeclaringType() - .getASourceSupertype*() - .hasQualifiedName("android.database.sqlite", "SQLiteQueryBuilder") and + method.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and // setProjectionMap(Map columnMap) // setTables(String inTables) // appendWhere(CharSequence inWhere) diff --git a/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll b/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll index aabe31fdeec..3f67db24c4d 100644 --- a/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll +++ b/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll @@ -1,9 +1,26 @@ import java +/** + * The class `android.database.sqlite.SQLiteDatabase`. + */ class TypeSQLiteDatabase extends Class { TypeSQLiteDatabase() { hasQualifiedName("android.database.sqlite", "SQLiteDatabase") } } +/** + * The class `android.database.sqlite.SQLiteQueryBuilder`. + */ +class TypeSQLiteQueryBuilder extends Class { + TypeSQLiteQueryBuilder() { hasQualifiedName("android.database.sqlite", "SQLiteQueryBuilder") } +} + +/** + * The class `android.database.DatabaseUtils`. + */ +class TypeDatabaseUtils extends Class { + TypeDatabaseUtils() { hasQualifiedName("android.database", "DatabaseUtils") } +} + abstract class SQLiteRunner extends Method { abstract int sqlIndex(); } From 28c965765b93bcfba39e272e4a0ee7e81c7b13fa Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Mon, 28 Sep 2020 19:28:43 +0200 Subject: [PATCH 121/411] Move query sinks into SQLite.qll --- .../code/java/frameworks/android/SQLite.qll | 167 +++++++++++++++++- .../code/java/security/QueryInjection.qll | 128 +------------- 2 files changed, 165 insertions(+), 130 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll b/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll index 3f67db24c4d..30465a1e84e 100644 --- a/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll +++ b/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll @@ -1,4 +1,5 @@ import java +import Android /** * The class `android.database.sqlite.SQLiteDatabase`. @@ -28,7 +29,10 @@ abstract class SQLiteRunner extends Method { class ExecSqlMethod extends SQLiteRunner { ExecSqlMethod() { this.getDeclaringType() instanceof TypeSQLiteDatabase and - this.getName() = "execSql" + // execPerConnectionSQL(String sql, Object[] bindArgs) + // execSQL(String sql) + // execSQL(String sql, Object[] bindArgs) + this.hasName(["execPerConnectionSQL", "execSQL"]) } override int sqlIndex() { result = 0 } @@ -37,26 +41,179 @@ class ExecSqlMethod extends SQLiteRunner { class QueryMethod extends SQLiteRunner { QueryMethod() { this.getDeclaringType() instanceof TypeSQLiteDatabase and - this.getName().matches("rawQuery%") + this.hasName(["query", "queryWithFactory"]) } override int sqlIndex() { + // query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) + // query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal) + // query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) + // query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) this.getName() = "query" and - (if this.getParameter(0).getType() instanceof TypeString then result = 2 else result = 3) + ( + if this.getParameter(0).getType() instanceof TypeString + then result = [2, 4, 5, 6, 7] + else result = [3, 5, 6, 7, 8] + ) or - this.getName() = "queryWithFactory" and result = 4 + // queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal) + // queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) + this.getName() = "queryWithFactory" and result = [4, 6, 7, 8, 9] } } class RawQueryMethod extends SQLiteRunner { RawQueryMethod() { this.getDeclaringType() instanceof TypeSQLiteDatabase and - this.getName().matches("rawQuery%") + this.hasName(["rawQuery", "rawQueryWithFactory"]) } override int sqlIndex() { + // rawQuery(String sql, String[] selectionArgs, CancellationSignal cancellationSignal) + // rawQuery(String sql, String[] selectionArgs) this.getName() = "rawQuery" and result = 0 or + // rawQueryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable, CancellationSignal cancellationSignal) + // rawQueryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable) this.getName() = "rawQueryWithFactory" and result = 1 } } + +class CompileStatementMethod extends SQLiteRunner { + CompileStatementMethod() { + this.getDeclaringType() instanceof TypeSQLiteDatabase and + // compileStatement(String sql) + this.hasName("compileStatement") + } + + override int sqlIndex() { result = 0 } +} + +class DeleteMethod extends SQLiteRunner { + DeleteMethod() { + this.getDeclaringType() instanceof TypeSQLiteDatabase and + // delete(String table, String whereClause, String[] whereArgs) + this.hasName("delete") + } + + override int sqlIndex() { result = 1 } +} + +class UpdateMethod extends SQLiteRunner { + UpdateMethod() { + this.getDeclaringType() instanceof TypeSQLiteDatabase and + // update(String table, ContentValues values, String whereClause, String[] whereArgs) + // updateWithOnConflict(String table, ContentValues values, String whereClause, String[] whereArgs, int conflictAlgorithm) + this.hasName(["update", "updateWithOnConflict"]) + } + + override int sqlIndex() { result = 2 } +} + +class ForQueryMethod extends SQLiteRunner { + ForQueryMethod() { + // (blobFileDescriptor|long|string)ForQuery(SQLiteDatabase db, String query, String[] selectionArgs) + this.getDeclaringType() instanceof TypeDatabaseUtils and + this.hasName(["blobFileDescriptorForQuery", "longForQuery", "stringForQuery"]) and + this.getNumberOfParameters() = 3 + } + + override int sqlIndex() { result = 1 } +} + +class CreateDbFromSqlStatementsMethod extends SQLiteRunner { + CreateDbFromSqlStatementsMethod() { + // createDbFromSqlStatements(Context context, String dbName, int dbVersion, String sqlStatements) + this.getDeclaringType() instanceof TypeDatabaseUtils and + this.hasName("createDbFromSqlStatements") + } + + override int sqlIndex() { result = 3 } +} + +class QueryNumEntriesMethod extends SQLiteRunner { + QueryNumEntriesMethod() { + // queryNumEntries(SQLiteDatabase db, String table, String selection) + // queryNumEntries(SQLiteDatabase db, String table, String selection, String[] selectionArgs) + this.getDeclaringType() instanceof TypeDatabaseUtils and + this.hasName("queryNumEntries") + } + + override int sqlIndex() { result = 2 } +} + +class QueryBuilderDeleteMethod extends SQLiteRunner { + QueryBuilderDeleteMethod() { + // delete(SQLiteDatabase db, String selection, String[] selectionArgs) + this.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and + this.hasName("delete") + } + + override int sqlIndex() { result = [-1, 1] } +} + +class QueryBuilderInsertMethod extends SQLiteRunner { + QueryBuilderInsertMethod() { + // insert(SQLiteDatabase db, ContentValues values) + this.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and + this.hasName("insert") + } + + override int sqlIndex() { result = -1 } +} + +class QueryBuilderQueryMethod extends SQLiteRunner { + QueryBuilderQueryMethod() { + // query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder) + // query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit) + // query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit, CancellationSignal cancellationSignal) + this.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and + this.hasName("query") + } + + override int sqlIndex() { result = [-1, 3, 5, 6, 7, 8] } +} + +class QueryBuilderUpdateMethod extends SQLiteRunner { + QueryBuilderUpdateMethod() { + // update(SQLiteDatabase db, ContentValues values, String selection, String[] selectionArgs) + this.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and + this.hasName("update") + } + + override int sqlIndex() { result = [-1, 2] } +} + +class ContentProviderDeleteMethod extends SQLiteRunner { + ContentProviderDeleteMethod() { + // delete(Uri uri, String selection, String[] selectionArgs) + this.getDeclaringType() instanceof AndroidContentProvider and + this.hasName("delete") and + this.getNumberOfParameters() = 3 + } + + override int sqlIndex() { result = 1 } +} + +class ContentProviderQueryMethod extends SQLiteRunner { + ContentProviderQueryMethod() { + // query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) + // query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) + this.getDeclaringType() instanceof AndroidContentProvider and + this.hasName("query") and + this.getNumberOfParameters() = [5, 6] + } + + override int sqlIndex() { result = 2 } +} + +class ContentProviderUpdateMethod extends SQLiteRunner { + ContentProviderUpdateMethod() { + // update(Uri uri, ContentValues values, String selection, String[] selectionArgs) + this.getDeclaringType() instanceof AndroidContentProvider and + this.hasName("update") and + this.getNumberOfParameters() = 4 + } + + override int sqlIndex() { result = 2 } +} diff --git a/java/ql/src/semmle/code/java/security/QueryInjection.qll b/java/ql/src/semmle/code/java/security/QueryInjection.qll index 10dfa8bc4e8..604a5bacc12 100644 --- a/java/ql/src/semmle/code/java/security/QueryInjection.qll +++ b/java/ql/src/semmle/code/java/security/QueryInjection.qll @@ -34,7 +34,9 @@ private class SqlInjectionSink extends QueryInjectionSink { or exists(MethodAccess ma, Method m, int index | ma.getMethod() = m and - ma.getArgument(index) = this.asExpr() + if index = -1 + then this.asExpr() = ma.getQualifier() + else ma.getArgument(index) = this.asExpr() | index = m.(SQLiteRunner).sqlIndex() or @@ -90,127 +92,3 @@ private class MongoJsonStep extends AdditionalQueryInjectionTaintStep { ) } } - -/** A sink for Android database injection vulnerabilities. */ -private class AndroidDatabaseUtils extends QueryInjectionSink { - AndroidDatabaseUtils() { - exists(MethodAccess call, Method method | - method = call.getMethod() and - method.getDeclaringType().hasQualifiedName("android.database", "DatabaseUtils") and - ( - // (blobFileDescriptor|long|string)ForQuery(SQLiteDatabase db, String query, String[] selectionArgs) - method.hasName(["blobFileDescriptorForQuery", "longForQuery", "stringForQuery"]) and - method.getNumberOfParameters() = 3 and - this.asExpr() = call.getArgument(1) - or - // createDbFromSqlStatements(Context context, String dbName, int dbVersion, String sqlStatements) - method.hasName("createDbFromSqlStatements") and - this.asExpr() = call.getArgument(3) - or - // queryNumEntries(SQLiteDatabase db, String table, String selection) - // queryNumEntries(SQLiteDatabase db, String table, String selection, String[] selectionArgs) - method.hasName("queryNumEntries") and - this.asExpr() = call.getArgument(2) - ) - or - method - .getDeclaringType() - .getASourceSupertype*() - .hasQualifiedName("android.database.sqlite", "SQLiteDatabase") and - ( - // compileStatement(String sql) - method.hasName("compileStatement") and - this.asExpr() = call.getArgument(0) - or - // delete(String table, String whereClause, String[] whereArgs) - method.hasName("delete") and - this.asExpr() = call.getArgument(1) - or - // execPerConnectionSQL(String sql, Object[] bindArgs) - // execSQL(String sql) - // execSQL(String sql, Object[] bindArgs) - method.hasName(["execPerConnectionSQL", "execSQL"]) and - this.asExpr() = call.getArgument(0) - or - // query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) - // query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal) - // query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) - // query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) - method.hasName("query") and - ( - this.asExpr() = call.getArgument([3, 5, 6, 7, 8]) and - method.getNumberOfParameters() = [9, 10] - or - this.asExpr() = call.getArgument([2, 4, 5, 6, 7]) and - method.getNumberOfParameters() = [7, 8] - ) - or - // queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal) - // queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) - method.hasName("queryWithFactory") and - this.asExpr() = call.getArgument([4, 6, 7, 8, 9]) - or - // rawQuery(String sql, String[] selectionArgs, CancellationSignal cancellationSignal) - // rawQuery(String sql, String[] selectionArgs) - method.hasName("rawQuery") and - this.asExpr() = call.getArgument(0) - or - // rawQueryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable, CancellationSignal cancellationSignal) - // rawQueryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable) - method.hasName("rawQueryWithFactory") and - this.asExpr() = call.getArgument(1) - or - // update(String table, ContentValues values, String whereClause, String[] whereArgs) - // updateWithOnConflict(String table, ContentValues values, String whereClause, String[] whereArgs, int conflictAlgorithm) - method.hasName(["update", "updateWithOnConflict"]) and - this.asExpr() = call.getArgument(2) - ) - or - method - .getDeclaringType() - .getASourceSupertype*() - .hasQualifiedName("android.content", "ContentProvider") and - ( - // delete(Uri uri, String selection, String[] selectionArgs) - method.hasName("delete") and - this.asExpr() = call.getArgument(1) and - method.getNumberOfParameters() = 3 - or - // query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) - // query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) - method.hasName("query") and - method.getNumberOfParameters() = [5, 6] and - this.asExpr() = call.getArgument(2) - or - // update(Uri uri, ContentValues values, String selection, String[] selectionArgs) - method.hasName("update") and - this.asExpr() = call.getArgument(2) and - method.getNumberOfParameters() = 4 - ) - or - method - .getDeclaringType() - .getASourceSupertype*() - .hasQualifiedName("android.database.sqlite", "SQLiteQueryBuilder") and - ( - // delete(SQLiteDatabase db, String selection, String[] selectionArgs) - method.hasName("delete") and - (this.asExpr() = call.getArgument(1) or this.asExpr() = call.getQualifier()) - or - // insert(SQLiteDatabase db, ContentValues values) - method.hasName("update") and - this.asExpr() = call.getQualifier() - or - // query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder) - // query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit) - // query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit, CancellationSignal cancellationSignal) - method.hasName("query") and - (this.asExpr() = call.getArgument([3, 5, 6, 7, 8]) or this.asExpr() = call.getQualifier()) - or - // update(SQLiteDatabase db, ContentValues values, String selection, String[] selectionArgs) - method.hasName("update") and - (this.asExpr() = call.getArgument(2) or this.asExpr() = call.getQualifier()) - ) - ) - } -} From efd5b6ff66208d237d619d04b12ff8df8f273dea Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Mon, 28 Sep 2020 19:48:21 +0200 Subject: [PATCH 122/411] Java: SQLite: make classes private --- .../code/java/frameworks/android/SQLite.qll | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll b/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll index 30465a1e84e..86679b0307e 100644 --- a/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll +++ b/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll @@ -26,7 +26,7 @@ abstract class SQLiteRunner extends Method { abstract int sqlIndex(); } -class ExecSqlMethod extends SQLiteRunner { +private class ExecSqlMethod extends SQLiteRunner { ExecSqlMethod() { this.getDeclaringType() instanceof TypeSQLiteDatabase and // execPerConnectionSQL(String sql, Object[] bindArgs) @@ -38,7 +38,7 @@ class ExecSqlMethod extends SQLiteRunner { override int sqlIndex() { result = 0 } } -class QueryMethod extends SQLiteRunner { +private class QueryMethod extends SQLiteRunner { QueryMethod() { this.getDeclaringType() instanceof TypeSQLiteDatabase and this.hasName(["query", "queryWithFactory"]) @@ -62,7 +62,7 @@ class QueryMethod extends SQLiteRunner { } } -class RawQueryMethod extends SQLiteRunner { +private class RawQueryMethod extends SQLiteRunner { RawQueryMethod() { this.getDeclaringType() instanceof TypeSQLiteDatabase and this.hasName(["rawQuery", "rawQueryWithFactory"]) @@ -79,7 +79,7 @@ class RawQueryMethod extends SQLiteRunner { } } -class CompileStatementMethod extends SQLiteRunner { +private class CompileStatementMethod extends SQLiteRunner { CompileStatementMethod() { this.getDeclaringType() instanceof TypeSQLiteDatabase and // compileStatement(String sql) @@ -89,7 +89,7 @@ class CompileStatementMethod extends SQLiteRunner { override int sqlIndex() { result = 0 } } -class DeleteMethod extends SQLiteRunner { +private class DeleteMethod extends SQLiteRunner { DeleteMethod() { this.getDeclaringType() instanceof TypeSQLiteDatabase and // delete(String table, String whereClause, String[] whereArgs) @@ -99,7 +99,7 @@ class DeleteMethod extends SQLiteRunner { override int sqlIndex() { result = 1 } } -class UpdateMethod extends SQLiteRunner { +private class UpdateMethod extends SQLiteRunner { UpdateMethod() { this.getDeclaringType() instanceof TypeSQLiteDatabase and // update(String table, ContentValues values, String whereClause, String[] whereArgs) @@ -110,7 +110,7 @@ class UpdateMethod extends SQLiteRunner { override int sqlIndex() { result = 2 } } -class ForQueryMethod extends SQLiteRunner { +private class ForQueryMethod extends SQLiteRunner { ForQueryMethod() { // (blobFileDescriptor|long|string)ForQuery(SQLiteDatabase db, String query, String[] selectionArgs) this.getDeclaringType() instanceof TypeDatabaseUtils and @@ -121,7 +121,7 @@ class ForQueryMethod extends SQLiteRunner { override int sqlIndex() { result = 1 } } -class CreateDbFromSqlStatementsMethod extends SQLiteRunner { +private class CreateDbFromSqlStatementsMethod extends SQLiteRunner { CreateDbFromSqlStatementsMethod() { // createDbFromSqlStatements(Context context, String dbName, int dbVersion, String sqlStatements) this.getDeclaringType() instanceof TypeDatabaseUtils and @@ -131,7 +131,7 @@ class CreateDbFromSqlStatementsMethod extends SQLiteRunner { override int sqlIndex() { result = 3 } } -class QueryNumEntriesMethod extends SQLiteRunner { +private class QueryNumEntriesMethod extends SQLiteRunner { QueryNumEntriesMethod() { // queryNumEntries(SQLiteDatabase db, String table, String selection) // queryNumEntries(SQLiteDatabase db, String table, String selection, String[] selectionArgs) @@ -142,7 +142,7 @@ class QueryNumEntriesMethod extends SQLiteRunner { override int sqlIndex() { result = 2 } } -class QueryBuilderDeleteMethod extends SQLiteRunner { +private class QueryBuilderDeleteMethod extends SQLiteRunner { QueryBuilderDeleteMethod() { // delete(SQLiteDatabase db, String selection, String[] selectionArgs) this.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and @@ -152,7 +152,7 @@ class QueryBuilderDeleteMethod extends SQLiteRunner { override int sqlIndex() { result = [-1, 1] } } -class QueryBuilderInsertMethod extends SQLiteRunner { +private class QueryBuilderInsertMethod extends SQLiteRunner { QueryBuilderInsertMethod() { // insert(SQLiteDatabase db, ContentValues values) this.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and @@ -162,7 +162,7 @@ class QueryBuilderInsertMethod extends SQLiteRunner { override int sqlIndex() { result = -1 } } -class QueryBuilderQueryMethod extends SQLiteRunner { +private class QueryBuilderQueryMethod extends SQLiteRunner { QueryBuilderQueryMethod() { // query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder) // query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder, String limit) @@ -174,7 +174,7 @@ class QueryBuilderQueryMethod extends SQLiteRunner { override int sqlIndex() { result = [-1, 3, 5, 6, 7, 8] } } -class QueryBuilderUpdateMethod extends SQLiteRunner { +private class QueryBuilderUpdateMethod extends SQLiteRunner { QueryBuilderUpdateMethod() { // update(SQLiteDatabase db, ContentValues values, String selection, String[] selectionArgs) this.getDeclaringType().getASourceSupertype*() instanceof TypeSQLiteQueryBuilder and @@ -184,7 +184,7 @@ class QueryBuilderUpdateMethod extends SQLiteRunner { override int sqlIndex() { result = [-1, 2] } } -class ContentProviderDeleteMethod extends SQLiteRunner { +private class ContentProviderDeleteMethod extends SQLiteRunner { ContentProviderDeleteMethod() { // delete(Uri uri, String selection, String[] selectionArgs) this.getDeclaringType() instanceof AndroidContentProvider and @@ -195,7 +195,7 @@ class ContentProviderDeleteMethod extends SQLiteRunner { override int sqlIndex() { result = 1 } } -class ContentProviderQueryMethod extends SQLiteRunner { +private class ContentProviderQueryMethod extends SQLiteRunner { ContentProviderQueryMethod() { // query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) // query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) @@ -207,7 +207,7 @@ class ContentProviderQueryMethod extends SQLiteRunner { override int sqlIndex() { result = 2 } } -class ContentProviderUpdateMethod extends SQLiteRunner { +private class ContentProviderUpdateMethod extends SQLiteRunner { ContentProviderUpdateMethod() { // update(Uri uri, ContentValues values, String selection, String[] selectionArgs) this.getDeclaringType() instanceof AndroidContentProvider and From 449fb24ef6cbae61a0e6bce36c2930691620b8b1 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Tue, 29 Sep 2020 18:10:05 +0200 Subject: [PATCH 123/411] Java: android add taint and SQL sink for ContentProvider/Resolver --- .../java/dataflow/internal/TaintTrackingUtil.qll | 9 +++++++++ .../code/java/frameworks/android/Android.qll | 10 +++++++++- .../code/java/frameworks/android/SQLite.qll | 15 ++++++++++++--- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index c31f6f3d940..2c99b08948c 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -592,6 +592,15 @@ private predicate taintPreservingArgumentToMethod(Method method, int arg) { arg = [0 .. method.getNumberOfParameters()] and arg != 3 ) + or + ( + method.getDeclaringType() instanceof AndroidContentProvider or + method.getDeclaringType() instanceof AndroidContentResolver + ) and + // Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) + // Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) + method.hasName("query") and + arg = 0 } /** diff --git a/java/ql/src/semmle/code/java/frameworks/android/Android.qll b/java/ql/src/semmle/code/java/frameworks/android/Android.qll index a16c43ddfc5..da500afbe6e 100644 --- a/java/ql/src/semmle/code/java/frameworks/android/Android.qll +++ b/java/ql/src/semmle/code/java/frameworks/android/Android.qll @@ -14,7 +14,8 @@ class AndroidComponent extends Class { this.getASupertype*().hasQualifiedName("android.app", "Activity") or this.getASupertype*().hasQualifiedName("android.app", "Service") or this.getASupertype*().hasQualifiedName("android.content", "BroadcastReceiver") or - this.getASupertype*().hasQualifiedName("android.content", "ContentProvider") + this.getASupertype*().hasQualifiedName("android.content", "ContentProvider") or + this.getASupertype*().hasQualifiedName("android.content", "ContentResolver") } /** The XML element corresponding to this Android component. */ @@ -52,3 +53,10 @@ class AndroidContentProvider extends AndroidComponent { this.getASupertype*().hasQualifiedName("android.content", "ContentProvider") } } + +/** An Android content resolver. */ +class AndroidContentResolver extends AndroidComponent { + AndroidContentResolver() { + this.getASupertype*().hasQualifiedName("android.content", "ContentResolver") + } +} diff --git a/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll b/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll index 86679b0307e..fdf7a67d1e5 100644 --- a/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll +++ b/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll @@ -187,7 +187,10 @@ private class QueryBuilderUpdateMethod extends SQLiteRunner { private class ContentProviderDeleteMethod extends SQLiteRunner { ContentProviderDeleteMethod() { // delete(Uri uri, String selection, String[] selectionArgs) - this.getDeclaringType() instanceof AndroidContentProvider and + ( + this.getDeclaringType() instanceof AndroidContentProvider or + this.getDeclaringType() instanceof AndroidContentResolver + ) and this.hasName("delete") and this.getNumberOfParameters() = 3 } @@ -199,7 +202,10 @@ private class ContentProviderQueryMethod extends SQLiteRunner { ContentProviderQueryMethod() { // query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) // query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) - this.getDeclaringType() instanceof AndroidContentProvider and + ( + this.getDeclaringType() instanceof AndroidContentProvider or + this.getDeclaringType() instanceof AndroidContentResolver + ) and this.hasName("query") and this.getNumberOfParameters() = [5, 6] } @@ -210,7 +216,10 @@ private class ContentProviderQueryMethod extends SQLiteRunner { private class ContentProviderUpdateMethod extends SQLiteRunner { ContentProviderUpdateMethod() { // update(Uri uri, ContentValues values, String selection, String[] selectionArgs) - this.getDeclaringType() instanceof AndroidContentProvider and + ( + this.getDeclaringType() instanceof AndroidContentProvider or + this.getDeclaringType() instanceof AndroidContentResolver + ) and this.hasName("update") and this.getNumberOfParameters() = 4 } From 39f5284dccd0a13f982f0026a4248fe6eb5d3933 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Tue, 29 Sep 2020 14:12:53 +0200 Subject: [PATCH 124/411] Java: add stubs for some android database classes --- .../android/content/ContentProvider.java | 17 ++++++ .../android/content/ContentResolver.java | 17 ++++++ .../android/content/ContentValues.java | 5 ++ .../android/android/content/Context.java | 5 ++ .../android/android/database/Cursor.java | 5 ++ .../android/database/DatabaseUtils.java | 46 +++++++++++++++ .../database/sqlite/SQLiteDatabase.java | 56 ++++++++++++++++++ .../database/sqlite/SQLiteQueryBuilder.java | 57 +++++++++++++++++++ .../test/stubs/android/android/net/Uri.java | 5 ++ .../android/os/CancellationSignal.java | 5 ++ .../android/os/ParcelFileDescriptor.java | 5 ++ 11 files changed, 223 insertions(+) create mode 100644 java/ql/test/stubs/android/android/content/ContentProvider.java create mode 100644 java/ql/test/stubs/android/android/content/ContentResolver.java create mode 100644 java/ql/test/stubs/android/android/content/ContentValues.java create mode 100644 java/ql/test/stubs/android/android/content/Context.java create mode 100644 java/ql/test/stubs/android/android/database/Cursor.java create mode 100644 java/ql/test/stubs/android/android/database/DatabaseUtils.java create mode 100644 java/ql/test/stubs/android/android/database/sqlite/SQLiteDatabase.java create mode 100644 java/ql/test/stubs/android/android/database/sqlite/SQLiteQueryBuilder.java create mode 100644 java/ql/test/stubs/android/android/net/Uri.java create mode 100644 java/ql/test/stubs/android/android/os/CancellationSignal.java create mode 100644 java/ql/test/stubs/android/android/os/ParcelFileDescriptor.java diff --git a/java/ql/test/stubs/android/android/content/ContentProvider.java b/java/ql/test/stubs/android/android/content/ContentProvider.java new file mode 100644 index 00000000000..dfbd61f2ae6 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/ContentProvider.java @@ -0,0 +1,17 @@ +package android.content; + +import android.database.Cursor; +import android.net.Uri; +import android.os.CancellationSignal; + +public abstract class ContentProvider { + public abstract int delete(Uri uri, String selection, String[] selectionArgs); + + public abstract Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, + CancellationSignal cancellationSignal); + + public abstract Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder); + + public abstract int update(Uri uri, ContentValues values, String selection, String[] selectionArgs); + +} diff --git a/java/ql/test/stubs/android/android/content/ContentResolver.java b/java/ql/test/stubs/android/android/content/ContentResolver.java new file mode 100644 index 00000000000..27308ee87be --- /dev/null +++ b/java/ql/test/stubs/android/android/content/ContentResolver.java @@ -0,0 +1,17 @@ +package android.content; + +import android.database.Cursor; +import android.net.Uri; +import android.os.CancellationSignal; + +public abstract class ContentResolver { + public abstract int delete(Uri uri, String selection, String[] selectionArgs); + + public abstract Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, + CancellationSignal cancellationSignal); + + public abstract Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder); + + public abstract int update(Uri uri, ContentValues values, String selection, String[] selectionArgs); + +} diff --git a/java/ql/test/stubs/android/android/content/ContentValues.java b/java/ql/test/stubs/android/android/content/ContentValues.java new file mode 100644 index 00000000000..105c3092d79 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/ContentValues.java @@ -0,0 +1,5 @@ +package android.content; + +public class ContentValues { + +} diff --git a/java/ql/test/stubs/android/android/content/Context.java b/java/ql/test/stubs/android/android/content/Context.java new file mode 100644 index 00000000000..118e170d788 --- /dev/null +++ b/java/ql/test/stubs/android/android/content/Context.java @@ -0,0 +1,5 @@ +package android.content; + +public class Context { + +} diff --git a/java/ql/test/stubs/android/android/database/Cursor.java b/java/ql/test/stubs/android/android/database/Cursor.java new file mode 100644 index 00000000000..cc432b1ad06 --- /dev/null +++ b/java/ql/test/stubs/android/android/database/Cursor.java @@ -0,0 +1,5 @@ +package android.database; + +public interface Cursor { + +} diff --git a/java/ql/test/stubs/android/android/database/DatabaseUtils.java b/java/ql/test/stubs/android/android/database/DatabaseUtils.java new file mode 100644 index 00000000000..0d0414c9fdf --- /dev/null +++ b/java/ql/test/stubs/android/android/database/DatabaseUtils.java @@ -0,0 +1,46 @@ +package android.database; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.os.ParcelFileDescriptor; + +public class DatabaseUtils { + + public static ParcelFileDescriptor blobFileDescriptorForQuery(SQLiteDatabase db, String query, + String[] selectionArgs) { + return null; + } + + public static long longForQuery(SQLiteDatabase db, String query, String[] selectionArgs) { + return 0; + + } + + public static String stringForQuery(SQLiteDatabase db, String query, String[] selectionArgs) { + return null; + + } + + public static void createDbFromSqlStatements(Context context, String dbName, int dbVersion, String sqlStatements) { + + } + + public static int queryNumEntries(SQLiteDatabase db, String table, String selection) { + return 0; + + } + + public static int queryNumEntries(SQLiteDatabase db, String table, String selection, String[] selectionArgs) { + return 0; + + } + + public static String[] appendSelectionArgs(String[] originalValues, String[] newValues) { + return null; + } + + public static String concatenateWhere(String a, String b) { + return null; + } + +} diff --git a/java/ql/test/stubs/android/android/database/sqlite/SQLiteDatabase.java b/java/ql/test/stubs/android/android/database/sqlite/SQLiteDatabase.java new file mode 100644 index 00000000000..6f5b6bd2eea --- /dev/null +++ b/java/ql/test/stubs/android/android/database/sqlite/SQLiteDatabase.java @@ -0,0 +1,56 @@ +package android.database.sqlite; + +import android.content.ContentValues; +import android.os.CancellationSignal; + +public abstract class SQLiteDatabase { + public class CursorFactory { + + } + + public abstract void execPerConnectionSQL(String sql, Object[] bindArgs); + + public abstract void execSQL(String sql); + + public abstract void execSQL(String sql, Object[] bindArgs); + + public abstract void query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, + String groupBy, String having, String orderBy, String limit); + + public abstract void query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, + String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal); + + public abstract void query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, + String having, String orderBy, String limit); + + public abstract void query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, + String having, String orderBy); + + public abstract void queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, + String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, + String limit, CancellationSignal cancellationSignal); + + public abstract void queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, + String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, + String limit); + + public abstract void rawQuery(String sql, String[] selectionArgs, CancellationSignal cancellationSignal); + + public abstract void rawQuery(String sql, String[] selectionArgs); + + public abstract void rawQueryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, String sql, String[] selectionArgs, + String editTable, CancellationSignal cancellationSignal); + + public abstract void rawQueryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, String sql, String[] selectionArgs, + String editTable); + + public abstract void compileStatement(String sql); + + public abstract void delete(String table, String whereClause, String[] whereArgs); + + public abstract void update(String table, ContentValues values, String whereClause, String[] whereArgs); + + public abstract void updateWithOnConflict(String table, ContentValues values, String whereClause, String[] whereArgs, + int conflictAlgorithm); + +} diff --git a/java/ql/test/stubs/android/android/database/sqlite/SQLiteQueryBuilder.java b/java/ql/test/stubs/android/android/database/sqlite/SQLiteQueryBuilder.java new file mode 100644 index 00000000000..01b8942c6d7 --- /dev/null +++ b/java/ql/test/stubs/android/android/database/sqlite/SQLiteQueryBuilder.java @@ -0,0 +1,57 @@ +package android.database.sqlite; + +import java.util.Map; +import java.util.Set; + +import android.content.ContentValues; +import android.os.CancellationSignal; + +public abstract class SQLiteQueryBuilder { + public abstract void delete(SQLiteDatabase db, String selection, String[] selectionArgs); + + public abstract void insert(SQLiteDatabase db, ContentValues values); + + public abstract void query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, + String groupBy, String having, String sortOrder); + + public abstract void query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, + String groupBy, String having, String sortOrder, String limit); + + public abstract void query(SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, + String groupBy, String having, String sortOrder, String limit, CancellationSignal cancellationSignal); + + public abstract void update(SQLiteDatabase db, ContentValues values, String selection, String[] selectionArgs); + + public static String buildQueryString(boolean distinct, String tables, String[] columns, String where, + String groupBy, String having, String orderBy, String limit) { + return null; + } + + public abstract String buildQuery(String[] projectionIn, String selection, String groupBy, String having, String sortOrder, + String limit); + + public abstract String buildQuery(String[] projectionIn, String selection, String[] selectionArgs, String groupBy, + String having, String sortOrder, String limit); + + public abstract String buildUnionQuery(String[] subQueries, String sortOrder, String limit); + + public abstract String buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, + Set columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, + String selection, String[] selectionArgs, String groupBy, String having); + + public abstract String buildUnionSubQuery(String typeDiscriminatorColumn, String[] unionColumns, + Set columnsPresentInTable, int computedColumnsOffset, String typeDiscriminatorValue, + String selection, String groupBy, String having); + + public static void appendColumns(StringBuilder s, String[] columns) { + } + + public abstract void setProjectionMap(Map columnMap); + + public abstract void setTables(String inTables); + + public abstract void appendWhere(CharSequence inWhere); + + public abstract void appendWhereStandalone(CharSequence inWhere); + +} diff --git a/java/ql/test/stubs/android/android/net/Uri.java b/java/ql/test/stubs/android/android/net/Uri.java new file mode 100644 index 00000000000..371dab3cc97 --- /dev/null +++ b/java/ql/test/stubs/android/android/net/Uri.java @@ -0,0 +1,5 @@ +package android.net; + +public class Uri { + +} diff --git a/java/ql/test/stubs/android/android/os/CancellationSignal.java b/java/ql/test/stubs/android/android/os/CancellationSignal.java new file mode 100644 index 00000000000..212e605a819 --- /dev/null +++ b/java/ql/test/stubs/android/android/os/CancellationSignal.java @@ -0,0 +1,5 @@ +package android.os; + +public class CancellationSignal { + +} diff --git a/java/ql/test/stubs/android/android/os/ParcelFileDescriptor.java b/java/ql/test/stubs/android/android/os/ParcelFileDescriptor.java new file mode 100644 index 00000000000..757872bb457 --- /dev/null +++ b/java/ql/test/stubs/android/android/os/ParcelFileDescriptor.java @@ -0,0 +1,5 @@ +package android.os; + +public class ParcelFileDescriptor { + +} From a13e845127f4e7a2cc8cd8d8581bf12c0d296306 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Wed, 30 Sep 2020 10:30:33 +0200 Subject: [PATCH 125/411] Java: tests for android database sinks --- .../android/taint-database/Sinks.java | 359 ++++++++++++++++++ .../frameworks/android/taint-database/options | 1 + .../android/taint-database/sinks.expected | 74 ++++ .../android/taint-database/sinks.ql | 5 + 4 files changed, 439 insertions(+) create mode 100644 java/ql/test/library-tests/frameworks/android/taint-database/Sinks.java create mode 100644 java/ql/test/library-tests/frameworks/android/taint-database/options create mode 100644 java/ql/test/library-tests/frameworks/android/taint-database/sinks.expected create mode 100644 java/ql/test/library-tests/frameworks/android/taint-database/sinks.ql diff --git a/java/ql/test/library-tests/frameworks/android/taint-database/Sinks.java b/java/ql/test/library-tests/frameworks/android/taint-database/Sinks.java new file mode 100644 index 00000000000..5cf8426e2a0 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/taint-database/Sinks.java @@ -0,0 +1,359 @@ +import android.content.ContentProvider; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.database.DatabaseUtils; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteQueryBuilder; +import android.net.Uri; +import android.os.CancellationSignal; + +public class Sinks { + public static T taint() { + return null; + } + + private static abstract class MyContentProvider extends ContentProvider { + // Dummy class to test for sub classes + } + + private static abstract class MyContentResolver extends ContentResolver { + // Dummy class to test for sub classes + } + private static abstract class MySQLiteQueryBuilder extends SQLiteQueryBuilder { + // Dummy class to test for sub classes + } + + public static void compileStatement(SQLiteDatabase target) { + String sql = taint(); + target.compileStatement(sql); + } + + public static void delete1(MySQLiteQueryBuilder target) { + target = taint();; + SQLiteDatabase db = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + target.delete(db, selection, selectionArgs); + } + + public static void delete(SQLiteDatabase target) { + String table = taint(); + String whereClause = taint(); + String[] whereArgs = taint(); + target.delete(table, whereClause, whereArgs); + } + + public static void delete(MyContentResolver target) { + Uri uri = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + target.delete(uri, selection, selectionArgs); + } + + public static void delete(MyContentProvider target) { + Uri uri = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + target.delete(uri, selection, selectionArgs); + } + + public static void execPerConnectionSQL(SQLiteDatabase target) { + String sql = taint(); + Object[] bindArgs = taint(); + target.execPerConnectionSQL(sql, bindArgs); + } + + public static void execSQL(SQLiteDatabase target) { + String sql = taint(); + target.execSQL(sql); + } + + public static void execSQL2(SQLiteDatabase target) { + String sql = taint(); + Object[] bindArgs = taint(); + target.execSQL(sql, bindArgs); + } + + public static void insert(MySQLiteQueryBuilder target) { + target = taint();; + SQLiteDatabase db = taint(); + ContentValues values = taint(); + target.insert(db, values); + } + + public static void query(SQLiteDatabase target) { + boolean distinct = taint(); + String table = taint(); + String[] columns = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String groupBy = taint(); + String having = taint(); + String orderBy = taint(); + String limit = taint(); + target.query(distinct, table, columns, selection, selectionArgs, groupBy, having, orderBy, limit); + } + + public static void query2(SQLiteDatabase target) { + boolean distinct = taint(); + String table = taint(); + String[] columns = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String groupBy = taint(); + String having = taint(); + String orderBy = taint(); + String limit = taint(); + CancellationSignal cancellationSignal = taint(); + target.query(distinct, table, columns, selection, selectionArgs, groupBy, having, orderBy, limit, + cancellationSignal); + } + + public static void query3(SQLiteDatabase target) { + String table = taint(); + String[] columns = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String groupBy = taint(); + String having = taint(); + String orderBy = taint(); + target.query(table, columns, selection, selectionArgs, groupBy, having, orderBy); + } + + public static void query4(SQLiteDatabase target) { + String table = taint(); + String[] columns = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String groupBy = taint(); + String having = taint(); + String orderBy = taint(); + String limit = taint(); + target.query(table, columns, selection, selectionArgs, groupBy, having, orderBy, limit); + } + + public static void query(MySQLiteQueryBuilder target) { + target = taint();; + SQLiteDatabase db = taint(); + String[] projectionIn = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String groupBy = taint(); + String having = taint(); + String sortOrder = taint(); + target.query(db, projectionIn, selection, selectionArgs, groupBy, having, sortOrder); + } + + public static void query2(MySQLiteQueryBuilder target) { + target = taint();; + SQLiteDatabase db = taint(); + String[] projectionIn = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String groupBy = taint(); + String having = taint(); + String sortOrder = taint(); + String limit = taint(); + target.query(db, projectionIn, selection, selectionArgs, groupBy, having, sortOrder, limit); + } + + public static void query3(MySQLiteQueryBuilder target) { + target = taint();; + SQLiteDatabase db = taint(); + String[] projectionIn = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String groupBy = taint(); + String having = taint(); + String sortOrder = taint(); + String limit = taint(); + CancellationSignal cancellationSignal = taint(); + target.query(db, projectionIn, selection, selectionArgs, groupBy, having, sortOrder, limit, cancellationSignal); + } + + public static void query3(MyContentProvider target) { + Uri uri = taint(); + String[] projection = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String sortOrder = taint(); + target.query(uri, projection, selection, selectionArgs, sortOrder); + } + + public static void query(MyContentProvider target) { + Uri uri = taint(); + String[] projection = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String sortOrder = taint(); + CancellationSignal cancellationSignal = taint(); + target.query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal); + } + + public static void query3(MyContentResolver target) { + Uri uri = taint(); + String[] projection = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String sortOrder = taint(); + target.query(uri, projection, selection, selectionArgs, sortOrder); + } + + public static void query(MyContentResolver target) { + Uri uri = taint(); + String[] projection = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String sortOrder = taint(); + CancellationSignal cancellationSignal = taint(); + target.query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal); + } + + public static void queryWithFactory(SQLiteDatabase target) { + SQLiteDatabase.CursorFactory cursorFactory = taint(); + boolean distinct = taint(); + String table = taint(); + String[] columns = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String groupBy = taint(); + String having = taint(); + String orderBy = taint(); + String limit = taint(); + target.queryWithFactory(cursorFactory, distinct, table, columns, selection, selectionArgs, groupBy, having, + orderBy, limit); + } + + public static void queryWithFactory2(SQLiteDatabase target) { + SQLiteDatabase.CursorFactory cursorFactory = taint(); + boolean distinct = taint(); + String table = taint(); + String[] columns = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String groupBy = taint(); + String having = taint(); + String orderBy = taint(); + String limit = taint(); + CancellationSignal cancellationSignal = taint(); + target.queryWithFactory(cursorFactory, distinct, table, columns, selection, selectionArgs, groupBy, having, + orderBy, limit, cancellationSignal); + } + + public static void rawQuery(SQLiteDatabase target) { + String sql = taint(); + String[] selectionArgs = taint(); + target.rawQuery(sql, selectionArgs); + } + + public static void rawQuery2(SQLiteDatabase target) { + String sql = taint(); + String[] selectionArgs = taint(); + CancellationSignal cancellationSignal = taint(); + target.rawQuery(sql, selectionArgs, cancellationSignal); + } + + public static void rawQueryWithFactory(SQLiteDatabase target) { + SQLiteDatabase.CursorFactory cursorFactory = taint(); + String sql = taint(); + String[] selectionArgs = taint(); + String editTable = taint(); + target.rawQueryWithFactory(cursorFactory, sql, selectionArgs, editTable); + } + + public static void rawQueryWithFactory2(SQLiteDatabase target) { + SQLiteDatabase.CursorFactory cursorFactory = taint(); + String sql = taint(); + String[] selectionArgs = taint(); + String editTable = taint(); + CancellationSignal cancellationSignal = taint(); + target.rawQueryWithFactory(cursorFactory, sql, selectionArgs, editTable, cancellationSignal); + } + + public static void update(MySQLiteQueryBuilder target) { + target = taint();; + SQLiteDatabase db = taint(); + ContentValues values = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + target.update(db, values, selection, selectionArgs); + } + + public static void update(SQLiteDatabase target) { + String table = taint(); + ContentValues values = taint(); + String whereClause = taint(); + String[] whereArgs = taint(); + target.update(table, values, whereClause, whereArgs); + } + + public static void update(MyContentResolver target) { + Uri uri = taint(); + ContentValues values = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + target.update(uri, values, selection, selectionArgs); + } + + public static void update(MyContentProvider target) { + Uri uri = taint(); + ContentValues values = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + target.update(uri, values, selection, selectionArgs); + } + + public static void updateWithOnConflict(SQLiteDatabase target) { + String table = taint(); + ContentValues values = taint(); + String whereClause = taint(); + String[] whereArgs = taint(); + int conflictAlgorithm = taint(); + target.updateWithOnConflict(table, values, whereClause, whereArgs, conflictAlgorithm); + } + + public static void queryNumEntries() { + SQLiteDatabase db = taint(); + String table = taint(); + String selection = taint(); + DatabaseUtils.queryNumEntries(db, table, selection); + } + + public static void queryNumEntries2() { + SQLiteDatabase db = taint(); + String table = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + DatabaseUtils.queryNumEntries(db, table, selection, selectionArgs); + } + + public static void createDbFromSqlStatements() { + Context context = taint(); + String dbName = taint(); + int dbVersion = taint(); + String sqlStatements = taint(); + DatabaseUtils.createDbFromSqlStatements(context, dbName, dbVersion, sqlStatements); + } + + public static void blobFileDescriptorForQuery() { + SQLiteDatabase db = taint(); + String query = taint(); + String[] selectionArgs = taint(); + DatabaseUtils.blobFileDescriptorForQuery(db, query, selectionArgs); + } + + public static void longForQuery() { + SQLiteDatabase db = taint(); + String query = taint(); + String[] selectionArgs = taint(); + DatabaseUtils.longForQuery(db, query, selectionArgs); + } + + public static void stringForQuery() { + SQLiteDatabase db = taint(); + String query = taint(); + String[] selectionArgs = taint(); + DatabaseUtils.stringForQuery(db, query, selectionArgs); + } +} diff --git a/java/ql/test/library-tests/frameworks/android/taint-database/options b/java/ql/test/library-tests/frameworks/android/taint-database/options new file mode 100644 index 00000000000..020a4a1cebb --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/taint-database/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/android diff --git a/java/ql/test/library-tests/frameworks/android/taint-database/sinks.expected b/java/ql/test/library-tests/frameworks/android/taint-database/sinks.expected new file mode 100644 index 00000000000..3e0e6b19daf --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/taint-database/sinks.expected @@ -0,0 +1,74 @@ +| Sinks.java:29:27:29:29 | sql | +| Sinks.java:37:3:37:8 | target | +| Sinks.java:37:21:37:29 | selection | +| Sinks.java:44:24:44:34 | whereClause | +| Sinks.java:51:22:51:30 | selection | +| Sinks.java:58:22:58:30 | selection | +| Sinks.java:64:31:64:33 | sql | +| Sinks.java:69:18:69:20 | sql | +| Sinks.java:75:18:75:20 | sql | +| Sinks.java:82:3:82:8 | target | +| Sinks.java:95:42:95:50 | selection | +| Sinks.java:95:68:95:74 | groupBy | +| Sinks.java:95:77:95:82 | having | +| Sinks.java:95:85:95:91 | orderBy | +| Sinks.java:95:94:95:98 | limit | +| Sinks.java:109:42:109:50 | selection | +| Sinks.java:109:68:109:74 | groupBy | +| Sinks.java:109:77:109:82 | having | +| Sinks.java:109:85:109:91 | orderBy | +| Sinks.java:109:94:109:98 | limit | +| Sinks.java:121:32:121:40 | selection | +| Sinks.java:121:58:121:64 | groupBy | +| Sinks.java:121:67:121:72 | having | +| Sinks.java:121:75:121:81 | orderBy | +| Sinks.java:133:32:133:40 | selection | +| Sinks.java:133:58:133:64 | groupBy | +| Sinks.java:133:67:133:72 | having | +| Sinks.java:133:75:133:81 | orderBy | +| Sinks.java:133:84:133:88 | limit | +| Sinks.java:145:3:145:8 | target | +| Sinks.java:145:45:145:57 | selectionArgs | +| Sinks.java:145:69:145:74 | having | +| Sinks.java:145:77:145:85 | sortOrder | +| Sinks.java:158:3:158:8 | target | +| Sinks.java:158:45:158:57 | selectionArgs | +| Sinks.java:158:69:158:74 | having | +| Sinks.java:158:77:158:85 | sortOrder | +| Sinks.java:158:88:158:92 | limit | +| Sinks.java:172:3:172:8 | target | +| Sinks.java:172:45:172:57 | selectionArgs | +| Sinks.java:172:69:172:74 | having | +| Sinks.java:172:77:172:85 | sortOrder | +| Sinks.java:172:88:172:92 | limit | +| Sinks.java:172:95:172:112 | cancellationSignal | +| Sinks.java:181:33:181:41 | selection | +| Sinks.java:191:33:191:41 | selection | +| Sinks.java:200:33:200:41 | selection | +| Sinks.java:210:33:210:41 | selection | +| Sinks.java:224:68:224:76 | selection | +| Sinks.java:224:94:224:100 | groupBy | +| Sinks.java:224:103:224:108 | having | +| Sinks.java:225:5:225:11 | orderBy | +| Sinks.java:225:14:225:18 | limit | +| Sinks.java:240:68:240:76 | selection | +| Sinks.java:240:94:240:100 | groupBy | +| Sinks.java:240:103:240:108 | having | +| Sinks.java:241:5:241:11 | orderBy | +| Sinks.java:241:14:241:18 | limit | +| Sinks.java:247:19:247:21 | sql | +| Sinks.java:254:19:254:21 | sql | +| Sinks.java:262:45:262:47 | sql | +| Sinks.java:271:45:271:47 | sql | +| Sinks.java:280:3:280:8 | target | +| Sinks.java:280:29:280:37 | selection | +| Sinks.java:288:32:288:42 | whereClause | +| Sinks.java:296:30:296:38 | selection | +| Sinks.java:304:30:304:38 | selection | +| Sinks.java:313:46:313:56 | whereClause | +| Sinks.java:320:44:320:52 | selection | +| Sinks.java:328:44:328:52 | selection | +| Sinks.java:336:71:336:83 | sqlStatements | +| Sinks.java:343:48:343:52 | query | +| Sinks.java:350:34:350:38 | query | +| Sinks.java:357:36:357:40 | query | diff --git a/java/ql/test/library-tests/frameworks/android/taint-database/sinks.ql b/java/ql/test/library-tests/frameworks/android/taint-database/sinks.ql new file mode 100644 index 00000000000..d898b4f073d --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/taint-database/sinks.ql @@ -0,0 +1,5 @@ +import semmle.code.java.security.QueryInjection + +from QueryInjectionSink sink +where sink.getLocation().getFile().getBaseName() = "Sinks.java" +select sink From 061c2a754f2c631673929daa820c61d23ac157f6 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Wed, 30 Sep 2020 12:11:29 +0200 Subject: [PATCH 126/411] Java: tests for android database flow steps --- .../android/taint-database/FlowSteps.java | 181 ++++++++++++++++++ .../android/taint-database/flowSteps.expected | 56 ++++++ .../android/taint-database/flowSteps.ql | 22 +++ 3 files changed, 259 insertions(+) create mode 100644 java/ql/test/library-tests/frameworks/android/taint-database/FlowSteps.java create mode 100644 java/ql/test/library-tests/frameworks/android/taint-database/flowSteps.expected create mode 100644 java/ql/test/library-tests/frameworks/android/taint-database/flowSteps.ql diff --git a/java/ql/test/library-tests/frameworks/android/taint-database/FlowSteps.java b/java/ql/test/library-tests/frameworks/android/taint-database/FlowSteps.java new file mode 100644 index 00000000000..c53df505671 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/taint-database/FlowSteps.java @@ -0,0 +1,181 @@ +import java.util.Map; +import java.util.Set; + +import android.content.ContentProvider; +import android.content.ContentResolver; +import android.database.Cursor; +import android.database.DatabaseUtils; +import android.database.sqlite.SQLiteQueryBuilder; +import android.net.Uri; +import android.os.CancellationSignal; + +public class FlowSteps { + public static T taint() { + return null; + } + + private static abstract class MyContentProvider extends ContentProvider { + // Dummy class to test for sub classes + } + + private static abstract class MyContentResolver extends ContentResolver { + // Dummy class to test for sub classes + } + + private static abstract class MySQLiteQueryBuilder extends SQLiteQueryBuilder { + // Dummy class to test for sub classes + } + + public static String[] appendSelectionArgs() { + String[] originalValues = taint(); + String[] newValues = taint(); + return DatabaseUtils.appendSelectionArgs(originalValues, newValues); + } + + public static String concatenateWhere() { + String a = taint(); + String b = taint(); + return DatabaseUtils.concatenateWhere(a, b); + } + + public static String buildQueryString(MySQLiteQueryBuilder target) { + target = taint(); + boolean distinct = taint(); + String tables = taint(); + String[] columns = taint(); + String where = taint(); + String groupBy = taint(); + String having = taint(); + String orderBy = taint(); + String limit = taint(); + return SQLiteQueryBuilder.buildQueryString(distinct, tables, columns, where, groupBy, having, orderBy, limit); + } + + public static String buildQuery(MySQLiteQueryBuilder target) { + target = taint(); + String[] projectionIn = taint(); + String selection = taint(); + String groupBy = taint(); + String having = taint(); + String sortOrder = taint(); + String limit = taint(); + return target.buildQuery(projectionIn, selection, groupBy, having, sortOrder, limit); + } + + public static String buildQuery2(MySQLiteQueryBuilder target) { + target = taint(); + String[] projectionIn = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String groupBy = taint(); + String having = taint(); + String sortOrder = taint(); + String limit = taint(); + return target.buildQuery(projectionIn, selection, selectionArgs, groupBy, having, sortOrder, limit); + } + + public static String buildUnionQuery(MySQLiteQueryBuilder target) { + target = taint(); + String[] subQueries = taint(); + String sortOrder = taint(); + String limit = taint(); + return target.buildUnionQuery(subQueries, sortOrder, limit); + } + + public static String buildUnionSubQuery2(MySQLiteQueryBuilder target) { + target = taint(); + String typeDiscriminatorColumn = taint(); + String[] unionColumns = taint(); + Set columnsPresentInTable = taint(); + int computedColumnsOffset = taint(); + String typeDiscriminatorValue = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String groupBy = taint(); + String having = taint(); + return target.buildUnionSubQuery(typeDiscriminatorColumn, unionColumns, columnsPresentInTable, + computedColumnsOffset, typeDiscriminatorValue, selection, selectionArgs, groupBy, having); + } + + public static void buildUnionSubQuery3(MySQLiteQueryBuilder target) { + target = taint(); + String typeDiscriminatorColumn = taint(); + String[] unionColumns = taint(); + Set columnsPresentInTable = taint(); + int computedColumnsOffset = taint(); + String typeDiscriminatorValue = taint(); + String selection = taint(); + String groupBy = taint(); + String having = taint(); + target.buildUnionSubQuery(typeDiscriminatorColumn, unionColumns, columnsPresentInTable, computedColumnsOffset, + typeDiscriminatorValue, selection, groupBy, having); + } + + public static Cursor query(MyContentResolver target) { + Uri uri = taint(); + String[] projection = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String sortOrder = taint(); + CancellationSignal cancellationSignal = taint(); + return target.query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal); + } + + public static Cursor query(MyContentProvider target) { + Uri uri = taint(); + String[] projection = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String sortOrder = taint(); + CancellationSignal cancellationSignal = taint(); + return target.query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal); + } + + public static Cursor query2(MyContentResolver target) { + Uri uri = taint(); + String[] projection = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String sortOrder = taint(); + return target.query(uri, projection, selection, selectionArgs, sortOrder); + } + + public static Cursor query2(MyContentProvider target) { + Uri uri = taint(); + String[] projection = taint(); + String selection = taint(); + String[] selectionArgs = taint(); + String sortOrder = taint(); + return target.query(uri, projection, selection, selectionArgs, sortOrder); + } + + public static void appendColumns() { + StringBuilder s = taint(); + String[] columns = taint(); + SQLiteQueryBuilder.appendColumns(s, columns); + } + + public static void setProjectionMap(MySQLiteQueryBuilder target) { + target = taint(); + Map columnMap = taint(); + target.setProjectionMap(columnMap); + } + + public static void setTables(MySQLiteQueryBuilder target) { + target = taint(); + String inTables = taint(); + target.setTables(inTables); + } + + public static void appendWhere(MySQLiteQueryBuilder target) { + target = taint(); + CharSequence inWhere = taint(); + target.appendWhere(inWhere); + } + + public static void appendWhereStandalone(MySQLiteQueryBuilder target) { + target = taint(); + CharSequence inWhere = taint(); + target.appendWhereStandalone(inWhere); + } +} diff --git a/java/ql/test/library-tests/frameworks/android/taint-database/flowSteps.expected b/java/ql/test/library-tests/frameworks/android/taint-database/flowSteps.expected new file mode 100644 index 00000000000..fd4565cea71 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/taint-database/flowSteps.expected @@ -0,0 +1,56 @@ +| FlowSteps.java:32:44:32:57 | originalValues | FlowSteps.java:32:10:32:69 | appendSelectionArgs(...) | +| FlowSteps.java:32:60:32:68 | newValues | FlowSteps.java:32:10:32:69 | appendSelectionArgs(...) | +| FlowSteps.java:38:41:38:41 | a | FlowSteps.java:38:10:38:45 | concatenateWhere(...) | +| FlowSteps.java:38:44:38:44 | b | FlowSteps.java:38:10:38:45 | concatenateWhere(...) | +| FlowSteps.java:51:56:51:61 | tables | FlowSteps.java:51:10:51:111 | buildQueryString(...) | +| FlowSteps.java:51:64:51:70 | columns | FlowSteps.java:51:10:51:111 | buildQueryString(...) | +| FlowSteps.java:51:73:51:77 | where | FlowSteps.java:51:10:51:111 | buildQueryString(...) | +| FlowSteps.java:51:80:51:86 | groupBy | FlowSteps.java:51:10:51:111 | buildQueryString(...) | +| FlowSteps.java:51:89:51:94 | having | FlowSteps.java:51:10:51:111 | buildQueryString(...) | +| FlowSteps.java:51:97:51:103 | orderBy | FlowSteps.java:51:10:51:111 | buildQueryString(...) | +| FlowSteps.java:51:106:51:110 | limit | FlowSteps.java:51:10:51:111 | buildQueryString(...) | +| FlowSteps.java:62:10:62:15 | target | FlowSteps.java:62:10:62:86 | buildQuery(...) | +| FlowSteps.java:62:28:62:39 | projectionIn | FlowSteps.java:62:10:62:86 | buildQuery(...) | +| FlowSteps.java:62:42:62:50 | selection | FlowSteps.java:62:10:62:86 | buildQuery(...) | +| FlowSteps.java:62:53:62:59 | groupBy | FlowSteps.java:62:10:62:86 | buildQuery(...) | +| FlowSteps.java:62:62:62:67 | having | FlowSteps.java:62:10:62:86 | buildQuery(...) | +| FlowSteps.java:62:70:62:78 | sortOrder | FlowSteps.java:62:10:62:86 | buildQuery(...) | +| FlowSteps.java:62:81:62:85 | limit | FlowSteps.java:62:10:62:86 | buildQuery(...) | +| FlowSteps.java:74:10:74:15 | target | FlowSteps.java:74:10:74:101 | buildQuery(...) | +| FlowSteps.java:74:28:74:39 | projectionIn | FlowSteps.java:74:10:74:101 | buildQuery(...) | +| FlowSteps.java:74:42:74:50 | selection | FlowSteps.java:74:10:74:101 | buildQuery(...) | +| FlowSteps.java:74:53:74:65 | selectionArgs | FlowSteps.java:74:10:74:101 | buildQuery(...) | +| FlowSteps.java:74:68:74:74 | groupBy | FlowSteps.java:74:10:74:101 | buildQuery(...) | +| FlowSteps.java:74:77:74:82 | having | FlowSteps.java:74:10:74:101 | buildQuery(...) | +| FlowSteps.java:74:85:74:93 | sortOrder | FlowSteps.java:74:10:74:101 | buildQuery(...) | +| FlowSteps.java:74:96:74:100 | limit | FlowSteps.java:74:10:74:101 | buildQuery(...) | +| FlowSteps.java:82:10:82:15 | target | FlowSteps.java:82:10:82:61 | buildUnionQuery(...) | +| FlowSteps.java:82:33:82:42 | subQueries | FlowSteps.java:82:10:82:61 | buildUnionQuery(...) | +| FlowSteps.java:82:45:82:53 | sortOrder | FlowSteps.java:82:10:82:61 | buildUnionQuery(...) | +| FlowSteps.java:82:56:82:60 | limit | FlowSteps.java:82:10:82:61 | buildUnionQuery(...) | +| FlowSteps.java:96:10:96:15 | target | FlowSteps.java:96:10:97:93 | buildUnionSubQuery(...) | +| FlowSteps.java:96:36:96:58 | typeDiscriminatorColumn | FlowSteps.java:96:10:97:93 | buildUnionSubQuery(...) | +| FlowSteps.java:96:61:96:72 | unionColumns | FlowSteps.java:96:10:97:93 | buildUnionSubQuery(...) | +| FlowSteps.java:96:75:96:95 | columnsPresentInTable | FlowSteps.java:96:10:97:93 | buildUnionSubQuery(...) | +| FlowSteps.java:97:28:97:49 | typeDiscriminatorValue | FlowSteps.java:96:10:97:93 | buildUnionSubQuery(...) | +| FlowSteps.java:97:52:97:60 | selection | FlowSteps.java:96:10:97:93 | buildUnionSubQuery(...) | +| FlowSteps.java:97:63:97:75 | selectionArgs | FlowSteps.java:96:10:97:93 | buildUnionSubQuery(...) | +| FlowSteps.java:97:78:97:84 | groupBy | FlowSteps.java:96:10:97:93 | buildUnionSubQuery(...) | +| FlowSteps.java:97:87:97:92 | having | FlowSteps.java:96:10:97:93 | buildUnionSubQuery(...) | +| FlowSteps.java:110:3:110:8 | target | FlowSteps.java:110:3:111:55 | buildUnionSubQuery(...) | +| FlowSteps.java:110:29:110:51 | typeDiscriminatorColumn | FlowSteps.java:110:3:111:55 | buildUnionSubQuery(...) | +| FlowSteps.java:110:54:110:65 | unionColumns | FlowSteps.java:110:3:111:55 | buildUnionSubQuery(...) | +| FlowSteps.java:110:68:110:88 | columnsPresentInTable | FlowSteps.java:110:3:111:55 | buildUnionSubQuery(...) | +| FlowSteps.java:111:5:111:26 | typeDiscriminatorValue | FlowSteps.java:110:3:111:55 | buildUnionSubQuery(...) | +| FlowSteps.java:111:29:111:37 | selection | FlowSteps.java:110:3:111:55 | buildUnionSubQuery(...) | +| FlowSteps.java:111:40:111:46 | groupBy | FlowSteps.java:110:3:111:55 | buildUnionSubQuery(...) | +| FlowSteps.java:111:49:111:54 | having | FlowSteps.java:110:3:111:55 | buildUnionSubQuery(...) | +| FlowSteps.java:121:23:121:25 | uri | FlowSteps.java:121:10:121:95 | query(...) | +| FlowSteps.java:131:23:131:25 | uri | FlowSteps.java:131:10:131:95 | query(...) | +| FlowSteps.java:140:23:140:25 | uri | FlowSteps.java:140:10:140:75 | query(...) | +| FlowSteps.java:149:23:149:25 | uri | FlowSteps.java:149:10:149:75 | query(...) | +| FlowSteps.java:155:39:155:45 | columns | FlowSteps.java:155:36:155:36 | s [post update] | +| FlowSteps.java:161:27:161:35 | columnMap | FlowSteps.java:161:3:161:8 | target [post update] | +| FlowSteps.java:167:20:167:27 | inTables | FlowSteps.java:167:3:167:8 | target [post update] | +| FlowSteps.java:173:22:173:28 | inWhere | FlowSteps.java:173:3:173:8 | target [post update] | +| FlowSteps.java:179:32:179:38 | inWhere | FlowSteps.java:179:3:179:8 | target [post update] | diff --git a/java/ql/test/library-tests/frameworks/android/taint-database/flowSteps.ql b/java/ql/test/library-tests/frameworks/android/taint-database/flowSteps.ql new file mode 100644 index 00000000000..32fde9c66c0 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/taint-database/flowSteps.ql @@ -0,0 +1,22 @@ +import semmle.code.java.dataflow.DataFlow +import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.dataflow.FlowSources +import semmle.code.java.security.QueryInjection + +class Conf extends TaintTracking::Configuration { + Conf() { this = "qltest:dataflow:android::flow" } + + override predicate isSource(DataFlow::Node source) { + exists(VarAccess va, MethodAccess ma | + source.asExpr() = va and + va.getVariable().getAnAssignedValue() = ma and + ma.getMethod().hasName("taint") + ) + } + + override predicate isSink(DataFlow::Node sink) { not isSource(sink) } +} + +from DataFlow::Node source, DataFlow::Node sink, Conf config +where config.hasFlow(source, sink) and sink.getLocation().getFile().getBaseName() = "FlowSteps.java" +select source, sink From a2d12f0440762bee7c2a61d8a26e96fb7f11efc8 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 30 Sep 2020 13:00:10 +0200 Subject: [PATCH 127/411] Python: Update CommandInjection.expected --- .../CWE-078/CommandInjection.expected | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected b/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected index 7f71e143109..8e79a98c6c3 100644 --- a/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected +++ b/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected @@ -1,11 +1,25 @@ edges | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | +| command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | +| command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | +| command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:972:11:972:13 | SSA variable cmd | +| file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:972:11:972:13 | SSA variable cmd | file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:981:33:981:35 | ControlFlowNode for cmd | +| file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:972:11:972:13 | SSA variable cmd | file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:987:33:987:35 | ControlFlowNode for cmd | nodes | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| command_injection.py:25:23:25:25 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd | | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:972:11:972:13 | SSA variable cmd | semmle.label | SSA variable cmd | +| file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:981:33:981:35 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd | +| file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:987:33:987:35 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd | #select | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:25:23:25:25 | ControlFlowNode for cmd | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | This command depends on $@. | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | a user-provided value | +| file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:981:33:981:35 | ControlFlowNode for cmd | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:981:33:981:35 | ControlFlowNode for cmd | This command depends on $@. | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | a user-provided value | +| file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:987:33:987:35 | ControlFlowNode for cmd | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:987:33:987:35 | ControlFlowNode for cmd | This command depends on $@. | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | a user-provided value | From b720bfdd11d39d776e7fb84d7f7d9772fff1cd13 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 30 Sep 2020 13:15:06 +0200 Subject: [PATCH 128/411] Apply suggestions from code review Co-authored-by: Asger F --- javascript/ql/src/semmle/javascript/ApiGraphs.qll | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 8d8e124259e..d1995255e84 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -21,13 +21,13 @@ module API { */ class Node extends Impl::TApiNode { /** - * Gets a data-flow corresponding to a use of the API component represented by this node. + * Gets a data-flow node corresponding to a use of the API component represented by this node. * * For example, `require('fs').readFileSync` is a use of the function `readFileSync` from the * `fs` module, and `require('fs').readFileSync(file)` is a use of the return of that function. * - * The use is type-tracked, meaning that in `f(obj.foo); function f(x) {};` both `obj.foo` and - * `x` are uses of the `foo` member from `obj`. + * This includes indirect uses found via data flow, meaning that in + * `f(obj.foo); function f(x) {};` both `obj.foo` and `x` are uses of the `foo` member from `obj`. * * As another example, in the assignment `exports.plusOne = (x) => x+1` the two references to * `x` are uses of the first parameter of `plusOne`. @@ -44,9 +44,10 @@ module API { * For example, `require('fs').readFileSync` is a reference to the `readFileSync` member from the * `fs` module. * - * No local data-flow or type-tracking happens on the result, which means that in - * `const x = fs.readFile` only `fs.readFile` is a reference to the `readFile` member of `fs`, - * neither `x` nor any node that `x` flows to is a reference to this API component. + * Unlike `getAUse()`, this predicate only gets the immediate references, not the indirect uses + * found via data flow. This means that in `const x = fs.readFile` only `fs.readFile` is a reference + * to the `readFile` member of `fs`, neither `x` nor any node that `x` flows to is a reference to + * this API component. */ DataFlow::SourceNode getAReference() { Impl::use(this, result) } @@ -56,7 +57,7 @@ module API { DataFlow::CallNode getACall() { result = getReturn().getAReference() } /** - * Gets an instantiation of the function represented by this API component. + * Gets a `new` call to the function represented by this API component. */ DataFlow::NewNode getAnInstantiation() { result = getInstance().getAReference() } From 9c1253c8af933e36fa921bd91e44e6cb430834fe Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 30 Sep 2020 13:29:21 +0200 Subject: [PATCH 129/411] Python: Remove flow out of CommandInjection sinks --- .../Security-new-dataflow/CWE-078/CommandInjection.ql | 11 +++++++++++ .../CWE-078/CommandInjection.expected | 10 ---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/python/ql/src/experimental/Security-new-dataflow/CWE-078/CommandInjection.ql b/python/ql/src/experimental/Security-new-dataflow/CWE-078/CommandInjection.ql index 3f200b77516..6e241a81a6a 100755 --- a/python/ql/src/experimental/Security-new-dataflow/CWE-078/CommandInjection.ql +++ b/python/ql/src/experimental/Security-new-dataflow/CWE-078/CommandInjection.ql @@ -29,6 +29,17 @@ class CommandInjectionConfiguration extends TaintTracking::Configuration { override predicate isSink(DataFlow::Node sink) { sink = any(SystemCommandExecution e).getCommand() } + + // Since the implementation of os.popen looks like + // ```py + // def popen(cmd, mode="r", buffering=-1): + // ... + // proc = subprocess.Popen(cmd, ...) + // ``` + // any time we would report flow to the `os.popen` sink, we can ALSO report the flow + // from the `cmd` parameter to the `subprocess.Popen` sink -- obviously we don't want + // that, so to prevent that we remove any taint edges out of a sink. + override predicate isSanitizerOut(DataFlow::Node node) { isSink(node) } } from CommandInjectionConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected b/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected index 8e79a98c6c3..68088064555 100644 --- a/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected +++ b/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected @@ -2,10 +2,6 @@ edges | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | -| command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | -| command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:972:11:972:13 | SSA variable cmd | -| file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:972:11:972:13 | SSA variable cmd | file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:981:33:981:35 | ControlFlowNode for cmd | -| file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:972:11:972:13 | SSA variable cmd | file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:987:33:987:35 | ControlFlowNode for cmd | nodes | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | @@ -13,13 +9,7 @@ nodes | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd | | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | -| command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | -| file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:972:11:972:13 | SSA variable cmd | semmle.label | SSA variable cmd | -| file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:981:33:981:35 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd | -| file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:987:33:987:35 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd | #select | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | This command depends on $@. | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | a user-provided value | -| file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:981:33:981:35 | ControlFlowNode for cmd | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:981:33:981:35 | ControlFlowNode for cmd | This command depends on $@. | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | a user-provided value | -| file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:987:33:987:35 | ControlFlowNode for cmd | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | file:///home/rasmus/.pyenv/versions/3.8.0/lib/python3.8/os.py:987:33:987:35 | ControlFlowNode for cmd | This command depends on $@. | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | a user-provided value | From b24e9590333be9252cd00cfa396a7fa76dd944e5 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 30 Sep 2020 13:29:47 +0200 Subject: [PATCH 130/411] add `getAnInvocation` to the ApiGraphs API --- javascript/ql/src/semmle/javascript/ApiGraphs.qll | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index d1995255e84..2ffdca7b92f 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -61,6 +61,11 @@ module API { */ DataFlow::NewNode getAnInstantiation() { result = getInstance().getAReference() } + /** + * Gets an invocation (with our without `new`) to the function represented by this API component. + */ + DataFlow::InvokeNode getAnInvocation() { result = getACall() or result = getAnInstantiation() } + /** * Gets a data-flow node corresponding to the right-hand side of a definition of the API * component represented by this node. From 4adc26eb629f373fcfe7a9be200436bc087d8ac4 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 30 Sep 2020 13:31:56 +0200 Subject: [PATCH 131/411] Python: Fix command injection example code `subprocess.Popen(["ls", "-la"], shell=True)` correspond to running `sh -c "ls" -la` So it doesn't follow the pattern of the rest of the test file. --- .../CWE-078/CommandInjection.expected | 4 ++++ .../Security-new-dataflow/CWE-078/command_injection.py | 2 +- .../Security/CWE-078/CommandInjection.expected | 10 +++++----- .../query-tests/Security/CWE-078/command_injection.py | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected b/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected index 68088064555..665617aa713 100644 --- a/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected +++ b/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected @@ -1,15 +1,19 @@ edges | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | +| command_injection.py:17:13:17:24 | ControlFlowNode for Attribute | command_injection.py:19:22:19:34 | ControlFlowNode for BinaryExpr | | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | nodes | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| command_injection.py:17:13:17:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| command_injection.py:19:22:19:34 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd | | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | #select | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:19:22:19:34 | ControlFlowNode for BinaryExpr | command_injection.py:17:13:17:24 | ControlFlowNode for Attribute | command_injection.py:19:22:19:34 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:17:13:17:24 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | This command depends on $@. | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | a user-provided value | diff --git a/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/command_injection.py b/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/command_injection.py index d50baf6563b..ce533b5e1ee 100644 --- a/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/command_injection.py +++ b/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/command_injection.py @@ -16,7 +16,7 @@ def command_injection1(): def command_injection2(): files = request.args.get('files', '') # Don't let files be `; rm -rf /` - subprocess.Popen(["ls", files], shell = True) + subprocess.Popen("ls " + files, shell=True) @app.route("/command3") diff --git a/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected index 3d1cf22a2d1..d417f55c68c 100644 --- a/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected @@ -7,10 +7,10 @@ edges | command_injection.py:12:23:12:27 | externally controlled string | command_injection.py:12:15:12:27 | externally controlled string | | command_injection.py:17:13:17:24 | dict of externally controlled string | command_injection.py:17:13:17:41 | externally controlled string | | command_injection.py:17:13:17:24 | dict of externally controlled string | command_injection.py:17:13:17:41 | externally controlled string | -| command_injection.py:17:13:17:41 | externally controlled string | command_injection.py:19:29:19:33 | externally controlled string | -| command_injection.py:17:13:17:41 | externally controlled string | command_injection.py:19:29:19:33 | externally controlled string | -| command_injection.py:19:29:19:33 | externally controlled string | command_injection.py:19:22:19:34 | sequence of externally controlled string | -| command_injection.py:19:29:19:33 | externally controlled string | command_injection.py:19:22:19:34 | sequence of externally controlled string | +| command_injection.py:17:13:17:41 | externally controlled string | command_injection.py:19:30:19:34 | externally controlled string | +| command_injection.py:17:13:17:41 | externally controlled string | command_injection.py:19:30:19:34 | externally controlled string | +| command_injection.py:19:30:19:34 | externally controlled string | command_injection.py:19:22:19:34 | externally controlled string | +| command_injection.py:19:30:19:34 | externally controlled string | command_injection.py:19:22:19:34 | externally controlled string | | command_injection.py:24:11:24:22 | dict of externally controlled string | command_injection.py:24:11:24:37 | externally controlled string | | command_injection.py:24:11:24:22 | dict of externally controlled string | command_injection.py:24:11:24:37 | externally controlled string | | command_injection.py:24:11:24:37 | externally controlled string | command_injection.py:25:23:25:25 | externally controlled string | @@ -25,6 +25,6 @@ edges | command_injection.py:32:22:32:26 | externally controlled string | command_injection.py:32:14:32:26 | externally controlled string | #select | command_injection.py:12:15:12:27 | BinaryExpr | command_injection.py:10:13:10:24 | dict of externally controlled string | command_injection.py:12:15:12:27 | externally controlled string | This command depends on $@. | command_injection.py:10:13:10:24 | Attribute | a user-provided value | -| command_injection.py:19:22:19:34 | List | command_injection.py:17:13:17:24 | dict of externally controlled string | command_injection.py:19:22:19:34 | sequence of externally controlled string | This command depends on $@. | command_injection.py:17:13:17:24 | Attribute | a user-provided value | +| command_injection.py:19:22:19:34 | BinaryExpr | command_injection.py:17:13:17:24 | dict of externally controlled string | command_injection.py:19:22:19:34 | externally controlled string | This command depends on $@. | command_injection.py:17:13:17:24 | Attribute | a user-provided value | | command_injection.py:25:22:25:36 | List | command_injection.py:24:11:24:22 | dict of externally controlled string | command_injection.py:25:22:25:36 | first item in sequence of externally controlled string | This command depends on $@. | command_injection.py:24:11:24:22 | Attribute | a user-provided value | | command_injection.py:32:14:32:26 | BinaryExpr | command_injection.py:30:13:30:24 | dict of externally controlled string | command_injection.py:32:14:32:26 | externally controlled string | This command depends on $@. | command_injection.py:30:13:30:24 | Attribute | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-078/command_injection.py b/python/ql/test/query-tests/Security/CWE-078/command_injection.py index 2122a076ec9..ee5629c1b4a 100644 --- a/python/ql/test/query-tests/Security/CWE-078/command_injection.py +++ b/python/ql/test/query-tests/Security/CWE-078/command_injection.py @@ -16,7 +16,7 @@ def command_injection1(): def command_injection2(): files = request.args.get('files', '') # Don't let files be `; rm -rf /` - subprocess.Popen(["ls", files], shell = True) + subprocess.Popen("ls " + files, shell=True) @app.route("/command3") From d316cb512e9df7a9e34abe048a789c62c245dd9b Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 30 Sep 2020 13:24:29 +0200 Subject: [PATCH 132/411] deprecate `exports` and replace uses with the new `getAnExportedValue` --- javascript/ql/src/NodeJS/MissingExports.ql | 4 +- javascript/ql/src/semmle/javascript/AMD.qll | 4 +- .../ql/src/semmle/javascript/Closure.qll | 4 +- .../src/semmle/javascript/ES2015Modules.qll | 6 +- .../ql/src/semmle/javascript/Modules.qll | 76 ++++++++++++++++++- .../ql/src/semmle/javascript/NodeJS.qll | 42 +++++----- .../src/semmle/javascript/PackageExports.qll | 19 +---- .../semmle/javascript/dataflow/Portals.qll | 4 +- .../javascript/frameworks/NodeJSLib.qll | 2 +- .../AMD/AmdModule_exports.expected | 26 +++---- .../library-tests/AMD/AmdModule_exports.ql | 6 +- .../test/library-tests/Modules/tests.expected | 25 +++--- .../ql/test/library-tests/Modules/tests.ql | 4 +- .../NodeJS/NodeModule_exports.expected | 18 ++--- .../NodeJS/NodeModule_exports.ql | 6 +- .../PackageExports/tests.expected | 14 +--- .../library-tests/PackageExports/tests.ql | 4 +- .../MissingExports/MissingExports.expected | 2 +- 18 files changed, 157 insertions(+), 109 deletions(-) diff --git a/javascript/ql/src/NodeJS/MissingExports.ql b/javascript/ql/src/NodeJS/MissingExports.ql index 49938d19889..1210c92441e 100644 --- a/javascript/ql/src/NodeJS/MissingExports.ql +++ b/javascript/ql/src/NodeJS/MissingExports.ql @@ -20,9 +20,9 @@ predicate definedInModule(GlobalVariable v, NodeModule m) { ) } -from NodeModule m, GlobalVariable f, InvokeExpr invk, ASTNode export, GlobalVarAccess acc +from NodeModule m, GlobalVariable f, InvokeExpr invk, DataFlow::Node export, GlobalVarAccess acc where - m.exports(f.getName(), export) and + export = m.getAnExportedValue(f.getName()) and acc = f.getAnAccess() and invk.getCallee() = acc and invk.getTopLevel() = m and diff --git a/javascript/ql/src/semmle/javascript/AMD.qll b/javascript/ql/src/semmle/javascript/AMD.qll index 49e0d8a9c39..7f3e8697d64 100644 --- a/javascript/ql/src/semmle/javascript/AMD.qll +++ b/javascript/ql/src/semmle/javascript/AMD.qll @@ -295,8 +295,8 @@ class AmdModule extends Module { /** Gets the definition of this module. */ AmdModuleDefinition getDefine() { amdModuleTopLevel(result, this) } - override predicate exports(string name, ASTNode export) { - exists(DataFlow::PropWrite pwn | export = pwn.getAstNode() | + override DataFlow::Node getAnExportedValue(string name) { + exists(DataFlow::PropWrite pwn | result = pwn.getRhs() | pwn.getBase().analyze().getAValue() = getDefine().getAModuleExportsValue() and name = pwn.getPropertyName() ) diff --git a/javascript/ql/src/semmle/javascript/Closure.qll b/javascript/ql/src/semmle/javascript/Closure.qll index 0f61a67fed7..e71c624c44d 100644 --- a/javascript/ql/src/semmle/javascript/Closure.qll +++ b/javascript/ql/src/semmle/javascript/Closure.qll @@ -165,9 +165,9 @@ module Closure { result = getScope().getVariable("exports") } - override predicate exports(string name, ASTNode export) { + override DataFlow::Node getAnExportedValue(string name) { exists(DataFlow::PropWrite write, Expr base | - write.getAstNode() = export and + result = write.getRhs() and write.writes(base.flow(), name, _) and ( base = getExportsVariable().getAReference() diff --git a/javascript/ql/src/semmle/javascript/ES2015Modules.qll b/javascript/ql/src/semmle/javascript/ES2015Modules.qll index 6e4acf242b5..c25b070d829 100644 --- a/javascript/ql/src/semmle/javascript/ES2015Modules.qll +++ b/javascript/ql/src/semmle/javascript/ES2015Modules.qll @@ -27,8 +27,8 @@ class ES2015Module extends Module { /** Gets an export declaration in this module. */ ExportDeclaration getAnExport() { result.getTopLevel() = this } - override predicate exports(string name, ASTNode export) { - exists(ExportDeclaration ed | ed = getAnExport() and ed = export | ed.exportsAs(_, name)) + override DataFlow::Node getAnExportedValue(string name) { + exists(ExportDeclaration ed | ed = getAnExport() and result = ed.getSourceNode(name)) } /** Holds if this module exports variable `v` under the name `name`. */ @@ -235,7 +235,7 @@ abstract class ExportDeclaration extends Stmt, @export_declaration { ES2015Module getEnclosingModule() { this = result.getAnExport() } /** Holds if this export declaration exports variable `v` under the name `name`. */ - abstract predicate exportsAs(LexicalName v, string name); + abstract predicate exportsAs(LexicalName v, string name); // TODO: Can I deprecate this? /** * Gets the data flow node corresponding to the value this declaration exports diff --git a/javascript/ql/src/semmle/javascript/Modules.qll b/javascript/ql/src/semmle/javascript/Modules.qll index d21ef6f59ac..9288eb39e4c 100644 --- a/javascript/ql/src/semmle/javascript/Modules.qll +++ b/javascript/ql/src/semmle/javascript/Modules.qll @@ -24,9 +24,11 @@ abstract class Module extends TopLevel { Module getAnImportedModule() { result = getAnImport().getImportedModule() } /** Gets a symbol exported by this module. */ - string getAnExportedSymbol() { exports(result, _) } + string getAnExportedSymbol() { exists(getAnExportedValue(result)) } /** + * DEPRECATED. Use `getAnExportedValue` instead. + * * Holds if this module explicitly exports symbol `name` at the * program element `export`. * @@ -36,9 +38,77 @@ abstract class Module extends TopLevel { * that are explicitly defined on the module object. * * Symbols defined in another module that are re-exported by - * this module are not considered either. + * this module are only sometimes considered. */ - abstract predicate exports(string name, ASTNode export); + deprecated predicate exports(string name, ASTNode export) { + this instanceof AmdModule and + exists(DataFlow::PropWrite pwn | export = pwn.getAstNode() | + pwn.getBase().analyze().getAValue() = this.(AmdModule).getDefine().getAModuleExportsValue() and + name = pwn.getPropertyName() + ) + or + this instanceof Closure::ClosureModule and + exists(DataFlow::PropWrite write, Expr base | + write.getAstNode() = export and + write.writes(base.flow(), name, _) and + ( + base = this.(Closure::ClosureModule).getExportsVariable().getAReference() + or + base = this.(Closure::ClosureModule).getExportsVariable().getAnAssignedExpr() + ) + ) + or + this instanceof NodeModule and + ( + // a property write whose base is `exports` or `module.exports` + exists(DataFlow::PropWrite pwn | export = pwn.getAstNode() | + pwn.getBase() = this.(NodeModule).getAModuleExportsNode() and + name = pwn.getPropertyName() + ) + or + // a re-export using spread-operator. E.g. `const foo = require("./foo"); module.exports = {bar: bar, ...foo};` + exists(ObjectExpr obj | obj = this.(NodeModule).getAModuleExportsNode().asExpr() | + obj + .getAProperty() + .(SpreadProperty) + .getInit() + .(SpreadElement) + .getOperand() + .flow() + .getALocalSource() + .asExpr() + .(Import) + .getImportedModule() + .exports(name, export) + ) + or + // an externs definition (where appropriate) + exists(PropAccess pacc | export = pacc | + pacc.getBase() = this.(NodeModule).getAModuleExportsNode().asExpr() and + name = pacc.getPropertyName() and + isExterns() and + exists(pacc.getDocumentation()) + ) + ) + or + this instanceof ES2015Module and + exists(ExportDeclaration ed | ed = this.(ES2015Module).getAnExport() and ed = export | + ed.exportsAs(_, name) + ) + } + + /** + * Get a value that is explicitly exported from this module with under `name`. + * + * Note that in some module systems (notably CommonJS and AMD) + * modules are arbitrary objects that export all their + * properties. This predicate only considers properties + * that are explicitly defined on the module object. + * + * Symbols defined in another module that are re-exported by + * this module are only sometimes considered. + */ + abstract DataFlow::Node getAnExportedValue(string name); /** * Gets the root folder relative to which the given import path (which must diff --git a/javascript/ql/src/semmle/javascript/NodeJS.qll b/javascript/ql/src/semmle/javascript/NodeJS.qll index a4c1c0cbe70..8a226cc749d 100644 --- a/javascript/ql/src/semmle/javascript/NodeJS.qll +++ b/javascript/ql/src/semmle/javascript/NodeJS.qll @@ -48,7 +48,7 @@ class NodeModule extends Module { * So if using this predicate - consider expanding the list of relevant expressions. */ pragma[noinline] - private DataFlow::Node getAModuleExportsNode() { + DataFlow::Node getAModuleExportsNode() { ( // A bit of manual magic result = any(DataFlow::PropWrite w | exists(w.getPropertyName())).getBase() @@ -62,35 +62,43 @@ class NodeModule extends Module { /** Gets a symbol exported by this module. */ override string getAnExportedSymbol() { - result = super.getAnExportedSymbol() or + result = super.getAnExportedSymbol() + or result = getAnImplicitlyExportedSymbol() + or + // getters and the like. + exists(DataFlow::PropWrite pwn | + pwn.getBase() = this.getAModuleExportsNode() and + result = pwn.getPropertyName() + ) } - override predicate exports(string name, ASTNode export) { + override DataFlow::Node getAnExportedValue(string name) { // a property write whose base is `exports` or `module.exports` - exists(DataFlow::PropWrite pwn | export = pwn.getAstNode() | + exists(DataFlow::PropWrite pwn | result = pwn.getRhs() | pwn.getBase() = getAModuleExportsNode() and name = pwn.getPropertyName() ) or // a re-export using spread-operator. E.g. `const foo = require("./foo"); module.exports = {bar: bar, ...foo};` exists(ObjectExpr obj | obj = getAModuleExportsNode().asExpr() | - obj - .getAProperty() - .(SpreadProperty) - .getInit() - .(SpreadElement) - .getOperand() - .flow() - .getALocalSource() - .asExpr() - .(Import) - .getImportedModule() - .exports(name, export) + result = + obj + .getAProperty() + .(SpreadProperty) + .getInit() + .(SpreadElement) + .getOperand() + .flow() + .getALocalSource() + .asExpr() + .(Import) + .getImportedModule() + .getAnExportedValue(name) ) or // an externs definition (where appropriate) - exists(PropAccess pacc | export = pacc | + exists(PropAccess pacc | result = DataFlow::valueNode(pacc) | pacc.getBase() = getAModuleExportsNode().asExpr() and name = pacc.getPropertyName() and isExterns() and diff --git a/javascript/ql/src/semmle/javascript/PackageExports.qll b/javascript/ql/src/semmle/javascript/PackageExports.qll index b54f0b48351..545e2743eee 100644 --- a/javascript/ql/src/semmle/javascript/PackageExports.qll +++ b/javascript/ql/src/semmle/javascript/PackageExports.qll @@ -68,22 +68,5 @@ DataFlow::Node getAValueExportedBy(PackageJSON packageJSON) { private DataFlow::Node getAnExportFromModule(Module mod) { result.analyze().getAValue() = mod.(NodeModule).getAModuleExportsValue() or - result = getAnExportedValue(mod, _) -} - -/** - * Gets a value exported from `mod` under `name`. - */ -DataFlow::Node getAnExportedValue(Module mod, string name) { - exists(Property export | result.asExpr() = export.getInit() | mod.exports(name, export)) - or - result = - DataFlow::valueNode(any(ASTNode export | mod.exports(name, export))) - .(DataFlow::PropWrite) - .getRhs() - or - exists(ExportDeclaration export | - result = export.getSourceNode(name) and - mod = export.getEnclosingModule() - ) + result = mod.getAnExportedValue(_) } diff --git a/javascript/ql/src/semmle/javascript/dataflow/Portals.qll b/javascript/ql/src/semmle/javascript/dataflow/Portals.qll index a5158ba927f..697e2dd3903 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Portals.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Portals.qll @@ -233,7 +233,9 @@ private module NpmPackagePortal { apw.writes(m.(AnalyzedModule).getModuleObject(), "exports", exp) ) or - m.(ES2015Module).exports("default", exp.(DataFlow::ValueNode).getAstNode()) + exists(DataFlow::PropWrite export | exp = export | + export.getRhs() = m.(ES2015Module).getAnExportedValue("default") + ) ) } } diff --git a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll index e9dbe9980c8..a39660c7b5f 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll @@ -647,7 +647,7 @@ module NodeJSLib { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(Import imp, string name | succ = DataFlow::valueNode(imp).(DataFlow::SourceNode).getAPropertyRead(name) and - pred = Exports::getAnExportedValue(imp.getImportedModule(), name) + pred = imp.getImportedModule().getAnExportedValue(name) ) } } diff --git a/javascript/ql/test/library-tests/AMD/AmdModule_exports.expected b/javascript/ql/test/library-tests/AMD/AmdModule_exports.expected index a860e264404..3f30464008e 100644 --- a/javascript/ql/test/library-tests/AMD/AmdModule_exports.expected +++ b/javascript/ql/test/library-tests/AMD/AmdModule_exports.expected @@ -1,13 +1,13 @@ -| a.js:1:1:3:3 | | foo | a.js:2:14:2:20 | foo: 42 | -| dir/b.js:1:1:3:3 | | bar | dir/b.js:2:5:2:11 | bar: 42 | -| lib/a.js:1:1:3:3 | | foo | lib/a.js:2:14:2:20 | foo: 42 | -| lib/foo.js:1:1:4:0 | | foo | lib/foo.js:2:5:2:11 | foo: 23 | -| lib/nested/a.js:1:1:3:3 | | foo | lib/nested/a.js:2:14:2:20 | foo: 42 | -| tst2.js:1:1:3:3 | | foo | tst2.js:2:5:2:15 | exports.foo | -| tst3.js:1:1:3:3 | | foo | tst3.js:2:29:2:39 | exports.foo | -| tst4.js:1:1:11:3 | | bar | tst4.js:9:9:9:18 | bar: b.bar | -| tst4.js:1:1:11:3 | | foo | tst4.js:8:9:8:18 | foo: a.foo | -| tst.js:1:1:6:3 | | bar | tst.js:4:9:4:18 | bar: b.bar | -| tst.js:1:1:6:3 | | foo | tst.js:3:9:3:18 | foo: a.foo | -| umd.js:1:1:14:4 | | bar | umd.js:11:9:11:18 | bar: a.foo | -| umd.js:1:1:14:4 | | foo | umd.js:12:9:12:18 | foo: b.bar | +| a.js:1:1:3:3 | | foo | a.js:2:19:2:20 | 42 | +| dir/b.js:1:1:3:3 | | bar | dir/b.js:2:10:2:11 | 42 | +| lib/a.js:1:1:3:3 | | foo | lib/a.js:2:19:2:20 | 42 | +| lib/foo.js:1:1:4:0 | | foo | lib/foo.js:2:10:2:11 | 23 | +| lib/nested/a.js:1:1:3:3 | | foo | lib/nested/a.js:2:19:2:20 | 42 | +| tst2.js:1:1:3:3 | | foo | tst2.js:2:19:2:20 | 42 | +| tst3.js:1:1:3:3 | | foo | tst3.js:2:43:2:44 | 42 | +| tst4.js:1:1:11:3 | | bar | tst4.js:9:14:9:18 | b.bar | +| tst4.js:1:1:11:3 | | foo | tst4.js:8:14:8:18 | a.foo | +| tst.js:1:1:6:3 | | bar | tst.js:4:14:4:18 | b.bar | +| tst.js:1:1:6:3 | | foo | tst.js:3:14:3:18 | a.foo | +| umd.js:1:1:14:4 | | bar | umd.js:11:14:11:18 | a.foo | +| umd.js:1:1:14:4 | | foo | umd.js:12:14:12:18 | b.bar | diff --git a/javascript/ql/test/library-tests/AMD/AmdModule_exports.ql b/javascript/ql/test/library-tests/AMD/AmdModule_exports.ql index eaeccca9212..19374dc32bc 100644 --- a/javascript/ql/test/library-tests/AMD/AmdModule_exports.ql +++ b/javascript/ql/test/library-tests/AMD/AmdModule_exports.ql @@ -1,5 +1,5 @@ import javascript -from Module m, string name, ASTNode export -where m.exports(name, export) -select m, name, export +from Module m, string name, DataFlow::Node exportValue +where exportValue = m.getAnExportedValue(name) +select m, name, exportValue diff --git a/javascript/ql/test/library-tests/Modules/tests.expected b/javascript/ql/test/library-tests/Modules/tests.expected index 0695797e6ec..55aa808b14f 100644 --- a/javascript/ql/test/library-tests/Modules/tests.expected +++ b/javascript/ql/test/library-tests/Modules/tests.expected @@ -69,19 +69,18 @@ test_Imports | tst.html:5:3:5:20 | import f from 'a'; | tst.html:5:17:5:19 | 'a' | 1 | | unresolved.js:1:1:1:18 | import f from 'a'; | unresolved.js:1:15:1:17 | 'a' | 1 | test_Module_exports -| a.js:1:1:5:32 | | default | a.js:1:1:3:1 | export ... n 23;\\n} | -| a.js:1:1:5:32 | | x | a.js:5:1:5:32 | export ... } = o; | -| a.js:1:1:5:32 | | y | a.js:5:1:5:32 | export ... } = o; | -| b.js:1:1:8:0 | | f2 | b.js:7:1:7:21 | export ... './a'; | -| b.js:1:1:8:0 | | g | b.js:5:1:5:18 | export { f as g }; | -| e.js:1:1:4:0 | | g | e.js:3:1:3:35 | export ... './a'; | -| e.js:1:1:4:0 | | x | e.js:2:1:2:16 | export { x, y }; | -| e.js:1:1:4:0 | | y | e.js:2:1:2:16 | export { x, y }; | -| es2015_require.js:1:1:3:25 | | default | es2015_require.js:3:1:3:25 | export ... ss C {} | -| export-in-mjs.mjs:1:1:1:34 | | exported_from_mjs | export-in-mjs.mjs:1:1:1:34 | export ... s = 42; | -| f.ts:1:1:6:0 | | foo | f.ts:5:1:5:24 | export ... oo() {} | -| m/c.js:1:1:6:0 | | h | m/c.js:5:1:5:30 | export ... '../b'; | -| tst.html:4:23:8:0 | | y | tst.html:7:3:7:22 | export const y = 42; | +| a.js:1:1:5:32 | | default | a.js:1:16:3:1 | functio ... n 23;\\n} | +| a.js:1:1:5:32 | | x | a.js:5:18:5:20 | f() | +| b.js:1:1:8:0 | | f2 | a.js:1:16:3:1 | functio ... n 23;\\n} | +| b.js:1:1:8:0 | | g | b.js:5:10:5:10 | f | +| e.js:1:1:4:0 | | g | a.js:1:16:3:1 | functio ... n 23;\\n} | +| e.js:1:1:4:0 | | x | e.js:2:10:2:10 | x | +| e.js:1:1:4:0 | | y | e.js:2:13:2:13 | y | +| es2015_require.js:1:1:3:25 | | default | es2015_require.js:3:16:3:25 | class C {} | +| export-in-mjs.mjs:1:1:1:34 | | exported_from_mjs | export-in-mjs.mjs:1:32:1:33 | 42 | +| f.ts:1:1:6:0 | | foo | f.ts:5:8:5:24 | function foo() {} | +| m/c.js:1:1:6:0 | | h | b.js:5:10:5:10 | f | +| tst.html:4:23:8:0 | | y | tst.html:7:20:7:21 | 42 | test_NamedImportSpecifier | d.js:1:10:1:21 | default as g | | d.js:1:24:1:29 | x as y | diff --git a/javascript/ql/test/library-tests/Modules/tests.ql b/javascript/ql/test/library-tests/Modules/tests.ql index c7b874de9e2..ca0e196f488 100644 --- a/javascript/ql/test/library-tests/Modules/tests.ql +++ b/javascript/ql/test/library-tests/Modules/tests.ql @@ -26,8 +26,8 @@ query predicate test_Imports(ImportDeclaration id, PathExpr res0, int res1) { res0 = id.getImportedPath() and res1 = count(id.getASpecifier()) } -query predicate test_Module_exports(Module m, string name, ASTNode export) { - m.exports(name, export) +query predicate test_Module_exports(Module m, string name, DataFlow::Node exportValue) { + exportValue = m.getAnExportedValue(name) } query predicate test_NamedImportSpecifier(NamedImportSpecifier nis) { any() } diff --git a/javascript/ql/test/library-tests/NodeJS/NodeModule_exports.expected b/javascript/ql/test/library-tests/NodeJS/NodeModule_exports.expected index d73a69441af..9e5715f9c06 100644 --- a/javascript/ql/test/library-tests/NodeJS/NodeModule_exports.expected +++ b/javascript/ql/test/library-tests/NodeJS/NodeModule_exports.expected @@ -1,9 +1,9 @@ -| b.js:1:1:8:0 | | sneaky | b.js:7:1:7:48 | (functi ... .sneaky | -| d.js:1:1:7:15 | | baz | d.js:4:2:4:8 | baz: 42 | -| mjs-files/depend-on-me.js:1:1:8:0 | | add | mjs-files/depend-on-me.js:5:1:7:1 | export ... + y;\\n} | -| mjs-files/depend-on-me.mjs:1:1:7:1 | | add | mjs-files/depend-on-me.mjs:5:1:7:1 | export ... + y;\\n} | -| reexport/a.js:1:1:3:1 | | foo | reexport/a.js:2:5:2:26 | foo: fu ... oo() {} | -| reexport/b.js:1:1:6:1 | | bar | reexport/b.js:4:5:4:26 | bar: fu ... ar() {} | -| reexport/b.js:1:1:6:1 | | foo | reexport/a.js:2:5:2:26 | foo: fu ... oo() {} | -| sub/c.js:1:1:4:0 | | foo | sub/c.js:3:1:3:11 | exports.foo | -| sub/f.js:1:1:4:17 | | bar | sub/f.js:4:1:4:11 | exports.bar | +| b.js:1:1:8:0 | | sneaky | b.js:7:52:7:53 | 56 | +| d.js:1:1:7:15 | | baz | d.js:4:7:4:8 | 42 | +| mjs-files/depend-on-me.js:1:1:8:0 | | add | mjs-files/depend-on-me.js:5:8:7:1 | functio ... + y;\\n} | +| mjs-files/depend-on-me.mjs:1:1:7:1 | | add | mjs-files/depend-on-me.mjs:5:8:7:1 | functio ... + y;\\n} | +| reexport/a.js:1:1:3:1 | | foo | reexport/a.js:2:10:2:26 | function foo() {} | +| reexport/b.js:1:1:6:1 | | bar | reexport/b.js:4:10:4:26 | function bar() {} | +| reexport/b.js:1:1:6:1 | | foo | reexport/a.js:2:10:2:26 | function foo() {} | +| sub/c.js:1:1:4:0 | | foo | sub/c.js:3:15:3:16 | 23 | +| sub/f.js:1:1:4:17 | | bar | sub/f.js:4:15:4:16 | 42 | diff --git a/javascript/ql/test/library-tests/NodeJS/NodeModule_exports.ql b/javascript/ql/test/library-tests/NodeJS/NodeModule_exports.ql index eaeccca9212..19374dc32bc 100644 --- a/javascript/ql/test/library-tests/NodeJS/NodeModule_exports.ql +++ b/javascript/ql/test/library-tests/NodeJS/NodeModule_exports.ql @@ -1,5 +1,5 @@ import javascript -from Module m, string name, ASTNode export -where m.exports(name, export) -select m, name, export +from Module m, string name, DataFlow::Node exportValue +where exportValue = m.getAnExportedValue(name) +select m, name, exportValue diff --git a/javascript/ql/test/library-tests/PackageExports/tests.expected b/javascript/ql/test/library-tests/PackageExports/tests.expected index 83ae0c2d2ad..392c3f33d80 100644 --- a/javascript/ql/test/library-tests/PackageExports/tests.expected +++ b/javascript/ql/test/library-tests/PackageExports/tests.expected @@ -45,16 +45,4 @@ getAnExportedValue | lib1/main.js:1:1:17:30 | | foo | lib1/main.js:3:22:3:40 | require("./foo.js") | | lib1/reexport/a.js:1:1:3:1 | | reexported | lib1/reexport/a.js:2:17:2:40 | functio ... ed() {} | | lib1/reexport/b.js:1:1:6:1 | | base | lib1/reexport/b.js:4:11:4:28 | function base() {} | -| lib1/reexport/b.js:1:1:6:1 | | reexported | lib1/reexport/a.js:2:17:2:40 | functio ... ed() {} | -exports -| Baz | lib1/main.js:17:1:17:18 | module.exports.Baz | lib1/main.js:1:1:17:30 | | -| bar | lib1/baz.js:4:5:4:26 | bar: fu ... ar() {} | lib1/baz.js:1:1:5:1 | | -| bar | lib1/main.js:5:1:5:18 | module.exports.bar | lib1/main.js:1:1:17:30 | | -| base | lib1/reexport/b.js:4:5:4:28 | base: f ... se() {} | lib1/reexport/b.js:1:1:6:1 | | -| exported | esmodules/main.js:1:1:1:29 | export ... ed() {} | esmodules/main.js:1:1:4:0 | | -| foo | absent_main/index.js:1:1:1:18 | module.exports.foo | absent_main/index.js:1:1:2:0 | | -| foo | lib1/baz.js:3:5:3:26 | foo: fu ... oo() {} | lib1/baz.js:1:1:5:1 | | -| foo | lib1/foo.js:3:1:3:18 | module.exports.foo | lib1/foo.js:1:1:3:47 | | -| foo | lib1/main.js:3:1:3:18 | module.exports.foo | lib1/main.js:1:1:17:30 | | -| reexported | lib1/reexport/a.js:2:5:2:40 | reexpor ... ed() {} | lib1/reexport/a.js:1:1:3:1 | | -| reexported | lib1/reexport/a.js:2:5:2:40 | reexpor ... ed() {} | lib1/reexport/b.js:1:1:6:1 | | +| lib1/reexport/b.js:1:1:6:1 | | reexported | lib1/reexport/a.js:2:17:2:40 | functio ... ed() {} | \ No newline at end of file diff --git a/javascript/ql/test/library-tests/PackageExports/tests.ql b/javascript/ql/test/library-tests/PackageExports/tests.ql index efbc708a538..ce1f7499051 100644 --- a/javascript/ql/test/library-tests/PackageExports/tests.ql +++ b/javascript/ql/test/library-tests/PackageExports/tests.ql @@ -8,7 +8,5 @@ query DataFlow::Node getAValueExportedBy(PackageJSON json) { } query DataFlow::Node getAnExportedValue(Module mod, string name) { - result = Exports::getAnExportedValue(mod, name) + result = mod.getAnExportedValue(name) } - -query Module exports(string name, ASTNode export) { result.exports(name, export) } diff --git a/javascript/ql/test/query-tests/NodeJS/MissingExports/MissingExports.expected b/javascript/ql/test/query-tests/NodeJS/MissingExports/MissingExports.expected index 83415d17b54..e207c2bcb81 100644 --- a/javascript/ql/test/query-tests/NodeJS/MissingExports/MissingExports.expected +++ b/javascript/ql/test/query-tests/NodeJS/MissingExports/MissingExports.expected @@ -1 +1 @@ -| MissingExports.js:7:5:7:19 | checkOne(xs[i]) | 'checkOne' references an undeclared global variable, not the variable exported $@. | MissingExports.js:1:1:1:16 | exports.checkOne | here | +| MissingExports.js:7:5:7:19 | checkOne(xs[i]) | 'checkOne' references an undeclared global variable, not the variable exported $@. | MissingExports.js:1:20:3:1 | functio ... or();\\n} | here | From 3af3d87ecd2970207742c23309f8f27ee7dca7e0 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 30 Sep 2020 13:52:23 +0200 Subject: [PATCH 133/411] C++: Change note for several range-analysis PRs --- .../2020-09-29-range-analysis-rollup.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 cpp/change-notes/2020-09-29-range-analysis-rollup.md diff --git a/cpp/change-notes/2020-09-29-range-analysis-rollup.md b/cpp/change-notes/2020-09-29-range-analysis-rollup.md new file mode 100644 index 00000000000..d5b2c729bcb --- /dev/null +++ b/cpp/change-notes/2020-09-29-range-analysis-rollup.md @@ -0,0 +1,14 @@ +lgtm,codescanning +* The `SimpleRangeAnalysis` library has gained support for several language + constructs it did not support previously. These improvements primarily affect + the queries `cpp/constant-comparison`, `cpp/comparison-with-wider-type`, and + `cpp/integer-multiplication-cast-to-long`. The newly supported language + features are: + * Multiplication of unsigned numbers. + * Multiplication by a constant. + * Reference-typed function parameters. + * Comparing a variable not equal to an endpoint of its range, thus narrowing the range by one. + * Using `if (x)` or `if (!x)` or similar to test for equality to zero. +* The `SimpleRangeAnalysis` library can now be extended with custom rules. See + examples in + `cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/extensions/`. From 03d8fc7296b18e5244d2b72eb3b7f2634a40bb3f Mon Sep 17 00:00:00 2001 From: Faten Healy <5361987+fatenhealy@users.noreply.github.com> Date: Wed, 30 Sep 2020 22:18:36 +1000 Subject: [PATCH 134/411] changed to AES --- python/ql/src/Security/CWE-327/examples/broken_crypto.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/Security/CWE-327/examples/broken_crypto.py b/python/ql/src/Security/CWE-327/examples/broken_crypto.py index 690ed0096b1..6e229339cdf 100644 --- a/python/ql/src/Security/CWE-327/examples/broken_crypto.py +++ b/python/ql/src/Security/CWE-327/examples/broken_crypto.py @@ -1,4 +1,4 @@ -from Crypto.Cipher import DES, Blowfish +from Crypto.Cipher import DES, AES cipher = DES.new(SECRET_KEY) From cf6036f9b4d79ee59fe1bd199bf9099f4e5c550d Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Wed, 30 Sep 2020 14:42:19 +0200 Subject: [PATCH 135/411] Java: fix some android database sinks --- .../code/java/frameworks/android/SQLite.qll | 8 +++---- .../android/taint-database/sinks.expected | 22 +++++++++++++++---- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll b/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll index fdf7a67d1e5..e0b41027232 100644 --- a/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll +++ b/java/ql/src/semmle/code/java/frameworks/android/SQLite.qll @@ -52,13 +52,13 @@ private class QueryMethod extends SQLiteRunner { this.getName() = "query" and ( if this.getParameter(0).getType() instanceof TypeString - then result = [2, 4, 5, 6, 7] - else result = [3, 5, 6, 7, 8] + then result = [0, 1, 2, 4, 5, 6, 7] + else result = [1, 2, 3, 5, 6, 7, 8] ) or // queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal) // queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) - this.getName() = "queryWithFactory" and result = [4, 6, 7, 8, 9] + this.getName() = "queryWithFactory" and result = [2, 3, 4, 6, 7, 8, 9] } } @@ -171,7 +171,7 @@ private class QueryBuilderQueryMethod extends SQLiteRunner { this.hasName("query") } - override int sqlIndex() { result = [-1, 3, 5, 6, 7, 8] } + override int sqlIndex() { result = [-1, 2, 4, 5, 6, 7] } } private class QueryBuilderUpdateMethod extends SQLiteRunner { diff --git a/java/ql/test/library-tests/frameworks/android/taint-database/sinks.expected b/java/ql/test/library-tests/frameworks/android/taint-database/sinks.expected index 3e0e6b19daf..7c0bdc30dc8 100644 --- a/java/ql/test/library-tests/frameworks/android/taint-database/sinks.expected +++ b/java/ql/test/library-tests/frameworks/android/taint-database/sinks.expected @@ -8,49 +8,63 @@ | Sinks.java:69:18:69:20 | sql | | Sinks.java:75:18:75:20 | sql | | Sinks.java:82:3:82:8 | target | +| Sinks.java:95:26:95:30 | table | +| Sinks.java:95:33:95:39 | columns | | Sinks.java:95:42:95:50 | selection | | Sinks.java:95:68:95:74 | groupBy | | Sinks.java:95:77:95:82 | having | | Sinks.java:95:85:95:91 | orderBy | | Sinks.java:95:94:95:98 | limit | +| Sinks.java:109:26:109:30 | table | +| Sinks.java:109:33:109:39 | columns | | Sinks.java:109:42:109:50 | selection | | Sinks.java:109:68:109:74 | groupBy | | Sinks.java:109:77:109:82 | having | | Sinks.java:109:85:109:91 | orderBy | | Sinks.java:109:94:109:98 | limit | +| Sinks.java:121:16:121:20 | table | +| Sinks.java:121:23:121:29 | columns | | Sinks.java:121:32:121:40 | selection | | Sinks.java:121:58:121:64 | groupBy | | Sinks.java:121:67:121:72 | having | | Sinks.java:121:75:121:81 | orderBy | +| Sinks.java:133:16:133:20 | table | +| Sinks.java:133:23:133:29 | columns | | Sinks.java:133:32:133:40 | selection | | Sinks.java:133:58:133:64 | groupBy | | Sinks.java:133:67:133:72 | having | | Sinks.java:133:75:133:81 | orderBy | | Sinks.java:133:84:133:88 | limit | | Sinks.java:145:3:145:8 | target | -| Sinks.java:145:45:145:57 | selectionArgs | +| Sinks.java:145:34:145:42 | selection | +| Sinks.java:145:60:145:66 | groupBy | | Sinks.java:145:69:145:74 | having | | Sinks.java:145:77:145:85 | sortOrder | | Sinks.java:158:3:158:8 | target | -| Sinks.java:158:45:158:57 | selectionArgs | +| Sinks.java:158:34:158:42 | selection | +| Sinks.java:158:60:158:66 | groupBy | | Sinks.java:158:69:158:74 | having | | Sinks.java:158:77:158:85 | sortOrder | | Sinks.java:158:88:158:92 | limit | | Sinks.java:172:3:172:8 | target | -| Sinks.java:172:45:172:57 | selectionArgs | +| Sinks.java:172:34:172:42 | selection | +| Sinks.java:172:60:172:66 | groupBy | | Sinks.java:172:69:172:74 | having | | Sinks.java:172:77:172:85 | sortOrder | | Sinks.java:172:88:172:92 | limit | -| Sinks.java:172:95:172:112 | cancellationSignal | | Sinks.java:181:33:181:41 | selection | | Sinks.java:191:33:191:41 | selection | | Sinks.java:200:33:200:41 | selection | | Sinks.java:210:33:210:41 | selection | +| Sinks.java:224:52:224:56 | table | +| Sinks.java:224:59:224:65 | columns | | Sinks.java:224:68:224:76 | selection | | Sinks.java:224:94:224:100 | groupBy | | Sinks.java:224:103:224:108 | having | | Sinks.java:225:5:225:11 | orderBy | | Sinks.java:225:14:225:18 | limit | +| Sinks.java:240:52:240:56 | table | +| Sinks.java:240:59:240:65 | columns | | Sinks.java:240:68:240:76 | selection | | Sinks.java:240:94:240:100 | groupBy | | Sinks.java:240:103:240:108 | having | From eb973b39fe780a8915bd90e8a5573a0530200c2a Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 30 Sep 2020 15:12:17 +0200 Subject: [PATCH 136/411] Update javascript/ql/src/semmle/javascript/frameworks/SQL.qll Co-authored-by: Max Schaefer <54907921+max-schaefer@users.noreply.github.com> --- javascript/ql/src/semmle/javascript/frameworks/SQL.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/SQL.qll b/javascript/ql/src/semmle/javascript/frameworks/SQL.qll index 86393cf5d58..c94750e5b3d 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/SQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/SQL.qll @@ -96,7 +96,7 @@ private module MySql { * Provides classes modelling the `pg` package. */ private module Postgres { - /** Gets a reference to the `Client` constructor in the `pg` package. E.g: `require('pg').Client`. */ + /** Gets a reference to the `Client` constructor in the `pg` package, for example `require('pg').Client`. */ API::Node newClient() { result = API::moduleImport("pg").getMember("Client") } /** Gets a freshly created Postgres client instance. */ From bfb653a34a02719211564a41d1dcf24056bfb75d Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 30 Sep 2020 15:15:27 +0200 Subject: [PATCH 137/411] rename getAReference to getAnImmediateUse --- javascript/ql/src/semmle/javascript/ApiGraphs.qll | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 2ffdca7b92f..16b459c3cae 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -39,27 +39,27 @@ module API { } /** - * Gets a reference to the API component represented by this node. + * Gets an immediate use of the API component represented by this node. * - * For example, `require('fs').readFileSync` is a reference to the `readFileSync` member from the - * `fs` module. + * For example, `require('fs').readFileSync` is a an immediate use of the `readFileSync` member + * from the `fs` module. * * Unlike `getAUse()`, this predicate only gets the immediate references, not the indirect uses * found via data flow. This means that in `const x = fs.readFile` only `fs.readFile` is a reference * to the `readFile` member of `fs`, neither `x` nor any node that `x` flows to is a reference to * this API component. */ - DataFlow::SourceNode getAReference() { Impl::use(this, result) } + DataFlow::SourceNode getAnImmediateUse() { Impl::use(this, result) } /** * Gets a call to the function represented by this API component. */ - DataFlow::CallNode getACall() { result = getReturn().getAReference() } + DataFlow::CallNode getACall() { result = getReturn().getAnImmediateUse() } /** * Gets a `new` call to the function represented by this API component. */ - DataFlow::NewNode getAnInstantiation() { result = getInstance().getAReference() } + DataFlow::NewNode getAnInstantiation() { result = getInstance().getAnImmediateUse() } /** * Gets an invocation (with our without `new`) to the function represented by this API component. From 7ecd229ce79da6920fa4683a3cb89aa4dc011310 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 30 Sep 2020 11:47:20 +0100 Subject: [PATCH 138/411] C++: Improve make_pair in stl.h (jbj solution). --- cpp/ql/test/library-tests/dataflow/taint-tests/stl.h | 3 +-- .../test/library-tests/dataflow/taint-tests/test_diff.expected | 2 -- .../test/library-tests/dataflow/taint-tests/test_ir.expected | 2 -- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h index 78ecd7340b9..133eadd0834 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h @@ -324,8 +324,7 @@ namespace std { void swap(pair& p) /*noexcept(...)*/; }; - - template constexpr pair make_pair(T1&&, T2&&); + template< class T1, class T2 > std::pair make_pair(const T1& t, const T2& u ); } // --- map --- 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 e604e787231..bc8a843de51 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 @@ -28,9 +28,7 @@ | map.cpp:76:9:76:13 | map.cpp:63:37:63:42 | IR only | | map.cpp:77:9:77:14 | map.cpp:63:37:63:42 | IR only | | map.cpp:84:34:84:38 | map.cpp:84:17:84:22 | IR only | -| map.cpp:85:7:85:39 | map.cpp:85:17:85:22 | IR only | | map.cpp:85:34:85:39 | map.cpp:85:17:85:22 | IR only | -| map.cpp:87:7:87:38 | map.cpp:87:24:87:29 | IR only | | map.cpp:87:34:87:38 | map.cpp:87:24:87:29 | IR only | | map.cpp:88:34:88:39 | map.cpp:88:24:88:29 | IR only | | map.cpp:92:7:92:7 | map.cpp:91:33:91:38 | 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 f47316752f2..3536273a806 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 @@ -70,10 +70,8 @@ | map.cpp:78:7:78:7 | l | map.cpp:63:37:63:42 | call to source | | map.cpp:83:7:83:32 | call to pair | map.cpp:83:17:83:22 | call to source | | map.cpp:84:34:84:38 | first | map.cpp:84:17:84:22 | call to source | -| map.cpp:85:7:85:39 | (reference dereference) | map.cpp:85:17:85:22 | call to source | | map.cpp:85:34:85:39 | second | map.cpp:85:17:85:22 | call to source | | map.cpp:86:7:86:32 | call to pair | map.cpp:86:24:86:29 | call to source | -| map.cpp:87:7:87:38 | (reference dereference) | map.cpp:87:24:87:29 | call to source | | map.cpp:87:34:87:38 | first | map.cpp:87:24:87:29 | call to source | | map.cpp:88:34:88:39 | second | map.cpp:88:24:88:29 | call to source | | map.cpp:93:9:93:13 | first | map.cpp:91:33:91:38 | call to source | From 952cc89c2a4490ee850c31a072876f276f0f2a24 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 30 Sep 2020 15:57:28 +0100 Subject: [PATCH 139/411] C++: Improve make_pair in stl.h (using remove_reference). --- .../dataflow/taint-tests/localTaint.expected | 50 +++++++++---------- .../library-tests/dataflow/taint-tests/stl.h | 16 +++++- 2 files changed, 40 insertions(+), 26 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 62505016c41..7ec322ae15b 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -1981,31 +1981,31 @@ | standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:53:12:53:18 | source1 | | | standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:54:14:54:20 | source1 | | | standalone_iterators.cpp:53:12:53:18 | ref arg source1 | standalone_iterators.cpp:54:14:54:20 | source1 | | -| stl.h:222:30:222:40 | call to allocator | stl.h:222:21:222:41 | noexcept(...) | TAINT | -| stl.h:222:30:222:40 | call to allocator | stl.h:222:21:222:41 | noexcept(...) | TAINT | -| stl.h:222:30:222:40 | call to allocator | stl.h:222:21:222:41 | noexcept(...) | TAINT | -| stl.h:222:30:222:40 | call to allocator | stl.h:222:21:222:41 | noexcept(...) | TAINT | -| stl.h:222:30:222:40 | call to allocator | stl.h:222:21:222:41 | noexcept(...) | TAINT | -| stl.h:222:53:222:63 | 0 | stl.h:222:46:222:64 | (no string representation) | TAINT | -| stl.h:315:9:315:9 | Unknown literal | stl.h:315:9:315:9 | constructor init of field first | TAINT | -| stl.h:315:9:315:9 | Unknown literal | stl.h:315:9:315:9 | constructor init of field second | TAINT | -| stl.h:315:9:315:9 | constructor init of field first [post-this] | stl.h:315:9:315:9 | constructor init of field second [pre-this] | | -| stl.h:315:9:315:9 | constructor init of field first [pre-this] | stl.h:315:9:315:9 | constructor init of field second [pre-this] | | -| stl.h:315:9:315:9 | this | stl.h:315:9:315:9 | constructor init of field first [pre-this] | | -| stl.h:322:3:322:3 | this | stl.h:322:36:322:43 | constructor init of field first [pre-this] | | -| stl.h:322:3:322:6 | this | stl.h:322:36:322:43 | constructor init of field first [pre-this] | | -| stl.h:322:18:322:18 | x | stl.h:322:42:322:42 | x | | -| stl.h:322:18:322:18 | x | stl.h:322:42:322:42 | x | | -| stl.h:322:31:322:31 | y | stl.h:322:53:322:53 | y | | -| stl.h:322:31:322:31 | y | stl.h:322:53:322:53 | y | | -| stl.h:322:36:322:43 | call to unknown function | stl.h:322:36:322:43 | constructor init of field first | TAINT | -| stl.h:322:36:322:43 | constructor init of field first [post-this] | stl.h:322:46:322:54 | constructor init of field second [pre-this] | | -| stl.h:322:36:322:43 | constructor init of field first [post-this] | stl.h:322:46:322:54 | constructor init of field second [pre-this] | | -| stl.h:322:36:322:43 | constructor init of field first [pre-this] | stl.h:322:46:322:54 | constructor init of field second [pre-this] | | -| stl.h:322:36:322:43 | constructor init of field first [pre-this] | stl.h:322:46:322:54 | constructor init of field second [pre-this] | | -| stl.h:322:42:322:42 | x | stl.h:322:36:322:43 | constructor init of field first | TAINT | -| stl.h:322:46:322:54 | call to unknown function | stl.h:322:46:322:54 | constructor init of field second | TAINT | -| stl.h:322:53:322:53 | y | stl.h:322:46:322:54 | constructor init of field second | TAINT | +| stl.h:235:30:235:40 | call to allocator | stl.h:235:21:235:41 | noexcept(...) | TAINT | +| stl.h:235:30:235:40 | call to allocator | stl.h:235:21:235:41 | noexcept(...) | TAINT | +| stl.h:235:30:235:40 | call to allocator | stl.h:235:21:235:41 | noexcept(...) | TAINT | +| stl.h:235:30:235:40 | call to allocator | stl.h:235:21:235:41 | noexcept(...) | TAINT | +| stl.h:235:30:235:40 | call to allocator | stl.h:235:21:235:41 | noexcept(...) | TAINT | +| stl.h:235:53:235:63 | 0 | stl.h:235:46:235:64 | (no string representation) | TAINT | +| stl.h:328:9:328:9 | Unknown literal | stl.h:328:9:328:9 | constructor init of field first | TAINT | +| stl.h:328:9:328:9 | Unknown literal | stl.h:328:9:328:9 | constructor init of field second | TAINT | +| stl.h:328:9:328:9 | constructor init of field first [post-this] | stl.h:328:9:328:9 | constructor init of field second [pre-this] | | +| stl.h:328:9:328:9 | constructor init of field first [pre-this] | stl.h:328:9:328:9 | constructor init of field second [pre-this] | | +| stl.h:328:9:328:9 | this | stl.h:328:9:328:9 | constructor init of field first [pre-this] | | +| stl.h:335:3:335:3 | this | stl.h:335:36:335:43 | constructor init of field first [pre-this] | | +| stl.h:335:3:335:6 | this | stl.h:335:36:335:43 | constructor init of field first [pre-this] | | +| stl.h:335:18:335:18 | x | stl.h:335:42:335:42 | x | | +| stl.h:335:18:335:18 | x | stl.h:335:42:335:42 | x | | +| stl.h:335:31:335:31 | y | stl.h:335:53:335:53 | y | | +| stl.h:335:31:335:31 | y | stl.h:335:53:335:53 | y | | +| stl.h:335:36:335:43 | call to unknown function | stl.h:335:36:335:43 | constructor init of field first | TAINT | +| stl.h:335:36:335:43 | constructor init of field first [post-this] | stl.h:335:46:335:54 | constructor init of field second [pre-this] | | +| stl.h:335:36:335:43 | constructor init of field first [post-this] | stl.h:335:46:335:54 | constructor init of field second [pre-this] | | +| stl.h:335:36:335:43 | constructor init of field first [pre-this] | stl.h:335:46:335:54 | constructor init of field second [pre-this] | | +| stl.h:335:36:335:43 | constructor init of field first [pre-this] | stl.h:335:46:335:54 | constructor init of field second [pre-this] | | +| stl.h:335:42:335:42 | x | stl.h:335:36:335:43 | constructor init of field first | TAINT | +| stl.h:335:46:335:54 | call to unknown function | stl.h:335:46:335:54 | constructor init of field second | TAINT | +| stl.h:335:53:335:53 | y | stl.h:335:46:335:54 | constructor init of field second | TAINT | | string.cpp:24:12:24:17 | call to source | string.cpp:28:7:28:7 | a | | | string.cpp:25:16:25:20 | 123 | string.cpp:25:16:25:21 | call to basic_string | TAINT | | string.cpp:25:16:25:21 | call to basic_string | string.cpp:29:7:29:7 | b | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h index 133eadd0834..4def0a84e5a 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h @@ -11,6 +11,19 @@ struct remove_const { typedef T type; }; template using remove_const_t = typename remove_const::type; +template +struct remove_reference { typedef T type; }; + +template +struct remove_reference { typedef T type; }; + +template +struct remove_reference { typedef T type; }; + +// `remove_reference_t` removes any `&` from `T` +template +using remove_reference_t = typename remove_reference::type; + // --- iterator --- namespace std { @@ -324,7 +337,8 @@ namespace std { void swap(pair& p) /*noexcept(...)*/; }; - template< class T1, class T2 > std::pair make_pair(const T1& t, const T2& u ); + + template constexpr pair, remove_reference_t> make_pair(T1&& x, T2&& y); } // --- map --- From c4a2e1d6d169429349df26df5151c4ad51401408 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 30 Sep 2020 17:24:50 +0200 Subject: [PATCH 140/411] Python: Rewrite attribute lookup helpers for better performance Not that they actually had a huge problem right now, just that using the old pattern HAS lead to bad performance in the past. See https://github.com/github/codeql/pull/4361 --- .../semmle/python/frameworks/Stdlib.qll | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index a452ecfeb1f..dc5977ecf27 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -29,7 +29,7 @@ private module Stdlib { * * For example, using `attr_name = "system"` will get all uses of `os.system`. */ - private DataFlow::Node os_attr(string attr_name, DataFlow::TypeTracker t) { + private DataFlow::Node os_attr(DataFlow::TypeTracker t, string attr_name) { attr_name in ["system", "popen", // exec "execl", "execle", "execlp", "execlpe", "execv", "execve", "execvp", "execvpe", @@ -41,10 +41,24 @@ private module Stdlib { result = DataFlow::importMember("os", attr_name) or t.startInAttr(attr_name) and - result = os() - or - exists(DataFlow::TypeTracker t2 | result = os_attr(attr_name, t2).track(t2, t)) + result = DataFlow::importModule("os") ) + or + // Due to bad performance when using normal setup with `os_attr(t2, attr_name).track(t2, t)` + // we have inlined that code and forced a join + exists(DataFlow::TypeTracker t2 | + exists(DataFlow::StepSummary summary | + os_attr_first_join(t2, attr_name, result, summary) and + t = t2.append(summary) + ) + ) + } + + pragma[nomagic] + private predicate os_attr_first_join( + DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, DataFlow::StepSummary summary + ) { + DataFlow::StepSummary::step(os_attr(t2, attr_name), res, summary) } /** @@ -54,7 +68,7 @@ private module Stdlib { * For example, using `"system"` will get all uses of `os.system`. */ private DataFlow::Node os_attr(string attr_name) { - result = os_attr(attr_name, DataFlow::TypeTracker::end()) + result = os_attr(DataFlow::TypeTracker::end(), attr_name) } /** @@ -148,17 +162,31 @@ private module Stdlib { * * For example, using `attr_name = "Popen"` will get all uses of `subprocess.Popen`. */ - private DataFlow::Node subprocess_attr(string attr_name, DataFlow::TypeTracker t) { + private DataFlow::Node subprocess_attr(DataFlow::TypeTracker t, string attr_name) { attr_name in ["Popen", "call", "check_call", "check_output", "run"] and ( t.start() and result = DataFlow::importMember("subprocess", attr_name) or t.startInAttr(attr_name) and - result = subprocess() - or - exists(DataFlow::TypeTracker t2 | result = subprocess_attr(attr_name, t2).track(t2, t)) + result = DataFlow::importModule("subprocess") ) + or + // Due to bad performance when using normal setup with `subprocess_attr(t2, attr_name).track(t2, t)` + // we have inlined that code and forced a join + exists(DataFlow::TypeTracker t2 | + exists(DataFlow::StepSummary summary | + subprocess_attr_first_join(t2, attr_name, result, summary) and + t = t2.append(summary) + ) + ) + } + + pragma[nomagic] + private predicate subprocess_attr_first_join( + DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, DataFlow::StepSummary summary + ) { + DataFlow::StepSummary::step(subprocess_attr(t2, attr_name), res, summary) } /** @@ -168,7 +196,7 @@ private module Stdlib { * For example, using `attr_name = "Popen"` will get all uses of `subprocess.Popen`. */ private DataFlow::Node subprocess_attr(string attr_name) { - result = subprocess_attr(attr_name, DataFlow::TypeTracker::end()) + result = subprocess_attr(DataFlow::TypeTracker::end(), attr_name) } /** From e0ca4dafb855e15f4cbddab272379cafa8d1115e Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Wed, 30 Sep 2020 16:31:45 +0100 Subject: [PATCH 141/411] Add support for Variable.is_constinit() --- cpp/ql/src/semmle/code/cpp/Variable.qll | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/Variable.qll b/cpp/ql/src/semmle/code/cpp/Variable.qll index 597facea442..527d8879b96 100644 --- a/cpp/ql/src/semmle/code/cpp/Variable.qll +++ b/cpp/ql/src/semmle/code/cpp/Variable.qll @@ -144,6 +144,11 @@ class Variable extends Declaration, @variable { */ predicate isConstexpr() { this.hasSpecifier("is_constexpr") } + /** + * Holds if this variable is declared `constinit`. + */ + predicate isConstinit() { this.hasSpecifier("declared_constinit") } + /** * Holds if this variable is `thread_local`. */ From 5bc7d3a9b28af484a1684ec475ecaf3fb4153721 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 25 Sep 2020 16:39:33 +0100 Subject: [PATCH 142/411] C++: Add tests for std::set and std::unordered_set. --- .../dataflow/taint-tests/localTaint.expected | 805 ++++++++++++++++++ .../dataflow/taint-tests/set.cpp | 238 ++++++ .../library-tests/dataflow/taint-tests/stl.h | 105 +++ 3 files changed, 1148 insertions(+) create mode 100644 cpp/ql/test/library-tests/dataflow/taint-tests/set.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 7ec322ae15b..59e062f1b7f 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -1919,6 +1919,811 @@ | movableclass.cpp:65:13:65:18 | call to source | movableclass.cpp:65:13:65:20 | call to MyMovableClass | TAINT | | movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:8:65:9 | ref arg s3 | TAINT | | movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:11:65:11 | call to operator= | TAINT | +| set.cpp:17:19:17:20 | call to set | set.cpp:19:7:19:8 | s1 | | +| set.cpp:17:19:17:20 | call to set | set.cpp:23:12:23:13 | s1 | | +| set.cpp:17:19:17:20 | call to set | set.cpp:23:24:23:25 | s1 | | +| set.cpp:17:19:17:20 | call to set | set.cpp:25:7:25:8 | s1 | | +| set.cpp:17:19:17:20 | call to set | set.cpp:31:7:31:8 | s1 | | +| set.cpp:17:19:17:20 | call to set | set.cpp:55:12:55:13 | s1 | | +| set.cpp:17:19:17:20 | call to set | set.cpp:55:30:55:31 | s1 | | +| set.cpp:17:19:17:20 | call to set | set.cpp:126:1:126:1 | s1 | | +| set.cpp:17:23:17:24 | call to set | set.cpp:20:7:20:8 | s2 | | +| set.cpp:17:23:17:24 | call to set | set.cpp:24:12:24:13 | s2 | | +| set.cpp:17:23:17:24 | call to set | set.cpp:24:24:24:25 | s2 | | +| set.cpp:17:23:17:24 | call to set | set.cpp:26:7:26:8 | s2 | | +| set.cpp:17:23:17:24 | call to set | set.cpp:32:7:32:8 | s2 | | +| set.cpp:17:23:17:24 | call to set | set.cpp:39:22:39:23 | s2 | | +| set.cpp:17:23:17:24 | call to set | set.cpp:40:24:40:25 | s2 | | +| set.cpp:17:23:17:24 | call to set | set.cpp:41:22:41:23 | s2 | | +| set.cpp:17:23:17:24 | call to set | set.cpp:41:34:41:35 | s2 | | +| set.cpp:17:23:17:24 | call to set | set.cpp:43:8:43:9 | s2 | | +| set.cpp:17:23:17:24 | call to set | set.cpp:59:12:59:13 | s2 | | +| set.cpp:17:23:17:24 | call to set | set.cpp:59:30:59:31 | s2 | | +| set.cpp:17:23:17:24 | call to set | set.cpp:126:1:126:1 | s2 | | +| set.cpp:17:27:17:28 | call to set | set.cpp:21:7:21:8 | s3 | | +| set.cpp:17:27:17:28 | call to set | set.cpp:21:17:21:18 | s3 | | +| set.cpp:17:27:17:28 | call to set | set.cpp:27:7:27:8 | s3 | | +| set.cpp:17:27:17:28 | call to set | set.cpp:33:7:33:8 | s3 | | +| set.cpp:17:27:17:28 | call to set | set.cpp:126:1:126:1 | s3 | | +| set.cpp:17:31:17:32 | call to set | set.cpp:22:7:22:8 | s4 | | +| set.cpp:17:31:17:32 | call to set | set.cpp:22:17:22:18 | s4 | | +| set.cpp:17:31:17:32 | call to set | set.cpp:28:7:28:8 | s4 | | +| set.cpp:17:31:17:32 | call to set | set.cpp:34:7:34:8 | s4 | | +| set.cpp:17:31:17:32 | call to set | set.cpp:126:1:126:1 | s4 | | +| set.cpp:17:35:17:36 | call to set | set.cpp:23:2:23:3 | s5 | | +| set.cpp:17:35:17:36 | call to set | set.cpp:29:7:29:8 | s5 | | +| set.cpp:17:35:17:36 | call to set | set.cpp:35:7:35:8 | s5 | | +| set.cpp:17:35:17:36 | call to set | set.cpp:126:1:126:1 | s5 | | +| set.cpp:17:39:17:40 | call to set | set.cpp:24:2:24:3 | s6 | | +| set.cpp:17:39:17:40 | call to set | set.cpp:30:7:30:8 | s6 | | +| set.cpp:17:39:17:40 | call to set | set.cpp:36:7:36:8 | s6 | | +| set.cpp:17:39:17:40 | call to set | set.cpp:126:1:126:1 | s6 | | +| set.cpp:19:7:19:8 | ref arg s1 | set.cpp:23:12:23:13 | s1 | | +| set.cpp:19:7:19:8 | ref arg s1 | set.cpp:23:24:23:25 | s1 | | +| set.cpp:19:7:19:8 | ref arg s1 | set.cpp:25:7:25:8 | s1 | | +| set.cpp:19:7:19:8 | ref arg s1 | set.cpp:31:7:31:8 | s1 | | +| set.cpp:19:7:19:8 | ref arg s1 | set.cpp:55:12:55:13 | s1 | | +| set.cpp:19:7:19:8 | ref arg s1 | set.cpp:55:30:55:31 | s1 | | +| set.cpp:19:7:19:8 | ref arg s1 | set.cpp:126:1:126:1 | s1 | | +| set.cpp:19:24:19:28 | first | set.cpp:19:7:19:28 | call to iterator | | +| set.cpp:20:7:20:8 | ref arg s2 | set.cpp:24:12:24:13 | s2 | | +| set.cpp:20:7:20:8 | ref arg s2 | set.cpp:24:24:24:25 | s2 | | +| set.cpp:20:7:20:8 | ref arg s2 | set.cpp:26:7:26:8 | s2 | | +| set.cpp:20:7:20:8 | ref arg s2 | set.cpp:32:7:32:8 | s2 | | +| set.cpp:20:7:20:8 | ref arg s2 | set.cpp:39:22:39:23 | s2 | | +| set.cpp:20:7:20:8 | ref arg s2 | set.cpp:40:24:40:25 | s2 | | +| set.cpp:20:7:20:8 | ref arg s2 | set.cpp:41:22:41:23 | s2 | | +| set.cpp:20:7:20:8 | ref arg s2 | set.cpp:41:34:41:35 | s2 | | +| set.cpp:20:7:20:8 | ref arg s2 | set.cpp:43:8:43:9 | s2 | | +| set.cpp:20:7:20:8 | ref arg s2 | set.cpp:59:12:59:13 | s2 | | +| set.cpp:20:7:20:8 | ref arg s2 | set.cpp:59:30:59:31 | s2 | | +| set.cpp:20:7:20:8 | ref arg s2 | set.cpp:126:1:126:1 | s2 | | +| set.cpp:20:27:20:31 | first | set.cpp:20:7:20:31 | call to iterator | | +| set.cpp:21:7:21:8 | ref arg s3 | set.cpp:27:7:27:8 | s3 | | +| set.cpp:21:7:21:8 | ref arg s3 | set.cpp:33:7:33:8 | s3 | | +| set.cpp:21:7:21:8 | ref arg s3 | set.cpp:126:1:126:1 | s3 | | +| set.cpp:21:17:21:18 | ref arg s3 | set.cpp:21:7:21:8 | s3 | | +| set.cpp:21:17:21:18 | ref arg s3 | set.cpp:27:7:27:8 | s3 | | +| set.cpp:21:17:21:18 | ref arg s3 | set.cpp:33:7:33:8 | s3 | | +| set.cpp:21:17:21:18 | ref arg s3 | set.cpp:126:1:126:1 | s3 | | +| set.cpp:21:20:21:24 | call to begin | set.cpp:21:17:21:26 | call to iterator | TAINT | +| set.cpp:22:7:22:8 | ref arg s4 | set.cpp:28:7:28:8 | s4 | | +| set.cpp:22:7:22:8 | ref arg s4 | set.cpp:34:7:34:8 | s4 | | +| set.cpp:22:7:22:8 | ref arg s4 | set.cpp:126:1:126:1 | s4 | | +| set.cpp:22:17:22:18 | ref arg s4 | set.cpp:22:7:22:8 | s4 | | +| set.cpp:22:17:22:18 | ref arg s4 | set.cpp:28:7:28:8 | s4 | | +| set.cpp:22:17:22:18 | ref arg s4 | set.cpp:34:7:34:8 | s4 | | +| set.cpp:22:17:22:18 | ref arg s4 | set.cpp:126:1:126:1 | s4 | | +| set.cpp:22:20:22:24 | call to begin | set.cpp:22:17:22:26 | call to iterator | TAINT | +| set.cpp:23:2:23:3 | ref arg s5 | set.cpp:29:7:29:8 | s5 | | +| set.cpp:23:2:23:3 | ref arg s5 | set.cpp:35:7:35:8 | s5 | | +| set.cpp:23:2:23:3 | ref arg s5 | set.cpp:126:1:126:1 | s5 | | +| set.cpp:23:12:23:13 | ref arg s1 | set.cpp:23:24:23:25 | s1 | | +| set.cpp:23:12:23:13 | ref arg s1 | set.cpp:25:7:25:8 | s1 | | +| set.cpp:23:12:23:13 | ref arg s1 | set.cpp:31:7:31:8 | s1 | | +| set.cpp:23:12:23:13 | ref arg s1 | set.cpp:55:12:55:13 | s1 | | +| set.cpp:23:12:23:13 | ref arg s1 | set.cpp:55:30:55:31 | s1 | | +| set.cpp:23:12:23:13 | ref arg s1 | set.cpp:126:1:126:1 | s1 | | +| set.cpp:23:24:23:25 | ref arg s1 | set.cpp:25:7:25:8 | s1 | | +| set.cpp:23:24:23:25 | ref arg s1 | set.cpp:31:7:31:8 | s1 | | +| set.cpp:23:24:23:25 | ref arg s1 | set.cpp:55:12:55:13 | s1 | | +| set.cpp:23:24:23:25 | ref arg s1 | set.cpp:55:30:55:31 | s1 | | +| set.cpp:23:24:23:25 | ref arg s1 | set.cpp:126:1:126:1 | s1 | | +| set.cpp:24:2:24:3 | ref arg s6 | set.cpp:30:7:30:8 | s6 | | +| set.cpp:24:2:24:3 | ref arg s6 | set.cpp:36:7:36:8 | s6 | | +| set.cpp:24:2:24:3 | ref arg s6 | set.cpp:126:1:126:1 | s6 | | +| set.cpp:24:12:24:13 | ref arg s2 | set.cpp:24:24:24:25 | s2 | | +| set.cpp:24:12:24:13 | ref arg s2 | set.cpp:26:7:26:8 | s2 | | +| set.cpp:24:12:24:13 | ref arg s2 | set.cpp:32:7:32:8 | s2 | | +| set.cpp:24:12:24:13 | ref arg s2 | set.cpp:39:22:39:23 | s2 | | +| set.cpp:24:12:24:13 | ref arg s2 | set.cpp:40:24:40:25 | s2 | | +| set.cpp:24:12:24:13 | ref arg s2 | set.cpp:41:22:41:23 | s2 | | +| set.cpp:24:12:24:13 | ref arg s2 | set.cpp:41:34:41:35 | s2 | | +| set.cpp:24:12:24:13 | ref arg s2 | set.cpp:43:8:43:9 | s2 | | +| set.cpp:24:12:24:13 | ref arg s2 | set.cpp:59:12:59:13 | s2 | | +| set.cpp:24:12:24:13 | ref arg s2 | set.cpp:59:30:59:31 | s2 | | +| set.cpp:24:12:24:13 | ref arg s2 | set.cpp:126:1:126:1 | s2 | | +| set.cpp:24:24:24:25 | ref arg s2 | set.cpp:26:7:26:8 | s2 | | +| set.cpp:24:24:24:25 | ref arg s2 | set.cpp:32:7:32:8 | s2 | | +| set.cpp:24:24:24:25 | ref arg s2 | set.cpp:39:22:39:23 | s2 | | +| set.cpp:24:24:24:25 | ref arg s2 | set.cpp:40:24:40:25 | s2 | | +| set.cpp:24:24:24:25 | ref arg s2 | set.cpp:41:22:41:23 | s2 | | +| set.cpp:24:24:24:25 | ref arg s2 | set.cpp:41:34:41:35 | s2 | | +| set.cpp:24:24:24:25 | ref arg s2 | set.cpp:43:8:43:9 | s2 | | +| set.cpp:24:24:24:25 | ref arg s2 | set.cpp:59:12:59:13 | s2 | | +| set.cpp:24:24:24:25 | ref arg s2 | set.cpp:59:30:59:31 | s2 | | +| set.cpp:24:24:24:25 | ref arg s2 | set.cpp:126:1:126:1 | s2 | | +| set.cpp:25:7:25:8 | s1 | set.cpp:25:7:25:8 | call to set | | +| set.cpp:26:7:26:8 | s2 | set.cpp:26:7:26:8 | call to set | | +| set.cpp:27:7:27:8 | s3 | set.cpp:27:7:27:8 | call to set | | +| set.cpp:28:7:28:8 | s4 | set.cpp:28:7:28:8 | call to set | | +| set.cpp:29:7:29:8 | s5 | set.cpp:29:7:29:8 | call to set | | +| set.cpp:30:7:30:8 | s6 | set.cpp:30:7:30:8 | call to set | | +| set.cpp:31:7:31:8 | ref arg s1 | set.cpp:55:12:55:13 | s1 | | +| set.cpp:31:7:31:8 | ref arg s1 | set.cpp:55:30:55:31 | s1 | | +| set.cpp:31:7:31:8 | ref arg s1 | set.cpp:126:1:126:1 | s1 | | +| set.cpp:32:7:32:8 | ref arg s2 | set.cpp:39:22:39:23 | s2 | | +| set.cpp:32:7:32:8 | ref arg s2 | set.cpp:40:24:40:25 | s2 | | +| set.cpp:32:7:32:8 | ref arg s2 | set.cpp:41:22:41:23 | s2 | | +| set.cpp:32:7:32:8 | ref arg s2 | set.cpp:41:34:41:35 | s2 | | +| set.cpp:32:7:32:8 | ref arg s2 | set.cpp:43:8:43:9 | s2 | | +| set.cpp:32:7:32:8 | ref arg s2 | set.cpp:59:12:59:13 | s2 | | +| set.cpp:32:7:32:8 | ref arg s2 | set.cpp:59:30:59:31 | s2 | | +| set.cpp:32:7:32:8 | ref arg s2 | set.cpp:126:1:126:1 | s2 | | +| set.cpp:33:7:33:8 | ref arg s3 | set.cpp:126:1:126:1 | s3 | | +| set.cpp:34:7:34:8 | ref arg s4 | set.cpp:126:1:126:1 | s4 | | +| set.cpp:35:7:35:8 | ref arg s5 | set.cpp:126:1:126:1 | s5 | | +| set.cpp:36:7:36:8 | ref arg s6 | set.cpp:126:1:126:1 | s6 | | +| set.cpp:39:22:39:23 | s2 | set.cpp:39:22:39:24 | call to set | | +| set.cpp:39:22:39:24 | call to set | set.cpp:44:7:44:8 | s7 | | +| set.cpp:39:22:39:24 | call to set | set.cpp:48:7:48:8 | s7 | | +| set.cpp:39:22:39:24 | call to set | set.cpp:126:1:126:1 | s7 | | +| set.cpp:40:23:40:25 | call to set | set.cpp:45:7:45:8 | s8 | | +| set.cpp:40:23:40:25 | call to set | set.cpp:49:7:49:8 | s8 | | +| set.cpp:40:23:40:25 | call to set | set.cpp:126:1:126:1 | s8 | | +| set.cpp:40:24:40:25 | s2 | set.cpp:40:23:40:25 | call to set | | +| set.cpp:41:22:41:23 | ref arg s2 | set.cpp:41:34:41:35 | s2 | | +| set.cpp:41:22:41:23 | ref arg s2 | set.cpp:43:8:43:9 | s2 | | +| set.cpp:41:22:41:23 | ref arg s2 | set.cpp:59:12:59:13 | s2 | | +| set.cpp:41:22:41:23 | ref arg s2 | set.cpp:59:30:59:31 | s2 | | +| set.cpp:41:22:41:23 | ref arg s2 | set.cpp:126:1:126:1 | s2 | | +| set.cpp:41:22:41:42 | call to set | set.cpp:46:7:46:8 | s9 | | +| set.cpp:41:22:41:42 | call to set | set.cpp:50:7:50:8 | s9 | | +| set.cpp:41:22:41:42 | call to set | set.cpp:126:1:126:1 | s9 | | +| set.cpp:41:34:41:35 | ref arg s2 | set.cpp:43:8:43:9 | s2 | | +| set.cpp:41:34:41:35 | ref arg s2 | set.cpp:59:12:59:13 | s2 | | +| set.cpp:41:34:41:35 | ref arg s2 | set.cpp:59:30:59:31 | s2 | | +| set.cpp:41:34:41:35 | ref arg s2 | set.cpp:126:1:126:1 | s2 | | +| set.cpp:42:19:42:21 | call to set | set.cpp:43:2:43:4 | s10 | | +| set.cpp:42:19:42:21 | call to set | set.cpp:47:7:47:9 | s10 | | +| set.cpp:42:19:42:21 | call to set | set.cpp:51:7:51:9 | s10 | | +| set.cpp:42:19:42:21 | call to set | set.cpp:126:1:126:1 | s10 | | +| set.cpp:43:2:43:4 | ref arg s10 | set.cpp:47:7:47:9 | s10 | | +| set.cpp:43:2:43:4 | ref arg s10 | set.cpp:51:7:51:9 | s10 | | +| set.cpp:43:2:43:4 | ref arg s10 | set.cpp:126:1:126:1 | s10 | | +| set.cpp:43:8:43:9 | s2 | set.cpp:43:2:43:4 | ref arg s10 | TAINT | +| set.cpp:43:8:43:9 | s2 | set.cpp:43:6:43:6 | call to operator= | TAINT | +| set.cpp:44:7:44:8 | s7 | set.cpp:44:7:44:8 | call to set | | +| set.cpp:45:7:45:8 | s8 | set.cpp:45:7:45:8 | call to set | | +| set.cpp:46:7:46:8 | s9 | set.cpp:46:7:46:8 | call to set | | +| set.cpp:47:7:47:9 | s10 | set.cpp:47:7:47:9 | call to set | | +| set.cpp:48:7:48:8 | ref arg s7 | set.cpp:126:1:126:1 | s7 | | +| set.cpp:49:7:49:8 | ref arg s8 | set.cpp:126:1:126:1 | s8 | | +| set.cpp:50:7:50:8 | ref arg s9 | set.cpp:126:1:126:1 | s9 | | +| set.cpp:51:7:51:9 | ref arg s10 | set.cpp:126:1:126:1 | s10 | | +| set.cpp:55:12:55:13 | ref arg s1 | set.cpp:55:30:55:31 | s1 | | +| set.cpp:55:12:55:13 | ref arg s1 | set.cpp:126:1:126:1 | s1 | | +| set.cpp:55:15:55:19 | call to begin | set.cpp:55:7:55:21 | ... = ... | | +| set.cpp:55:15:55:19 | call to begin | set.cpp:55:24:55:25 | i1 | | +| set.cpp:55:15:55:19 | call to begin | set.cpp:55:40:55:41 | i1 | | +| set.cpp:55:15:55:19 | call to begin | set.cpp:57:9:57:10 | i1 | | +| set.cpp:55:30:55:31 | ref arg s1 | set.cpp:55:30:55:31 | s1 | | +| set.cpp:55:30:55:31 | ref arg s1 | set.cpp:126:1:126:1 | s1 | | +| set.cpp:55:40:55:41 | i1 | set.cpp:55:42:55:42 | call to operator++ | | +| set.cpp:55:40:55:41 | ref arg i1 | set.cpp:55:24:55:25 | i1 | | +| set.cpp:55:40:55:41 | ref arg i1 | set.cpp:55:40:55:41 | i1 | | +| set.cpp:55:40:55:41 | ref arg i1 | set.cpp:57:9:57:10 | i1 | | +| set.cpp:57:9:57:10 | i1 | set.cpp:57:8:57:8 | call to operator* | TAINT | +| set.cpp:59:12:59:13 | ref arg s2 | set.cpp:59:30:59:31 | s2 | | +| set.cpp:59:12:59:13 | ref arg s2 | set.cpp:126:1:126:1 | s2 | | +| set.cpp:59:15:59:19 | call to begin | set.cpp:59:7:59:21 | ... = ... | | +| set.cpp:59:15:59:19 | call to begin | set.cpp:59:24:59:25 | i2 | | +| set.cpp:59:15:59:19 | call to begin | set.cpp:59:40:59:41 | i2 | | +| set.cpp:59:15:59:19 | call to begin | set.cpp:61:9:61:10 | i2 | | +| set.cpp:59:30:59:31 | ref arg s2 | set.cpp:59:30:59:31 | s2 | | +| set.cpp:59:30:59:31 | ref arg s2 | set.cpp:126:1:126:1 | s2 | | +| set.cpp:59:40:59:41 | i2 | set.cpp:59:42:59:42 | call to operator++ | | +| set.cpp:59:40:59:41 | ref arg i2 | set.cpp:59:24:59:25 | i2 | | +| set.cpp:59:40:59:41 | ref arg i2 | set.cpp:59:40:59:41 | i2 | | +| set.cpp:59:40:59:41 | ref arg i2 | set.cpp:61:9:61:10 | i2 | | +| set.cpp:61:9:61:10 | i2 | set.cpp:61:8:61:8 | call to operator* | TAINT | +| set.cpp:65:19:65:21 | call to set | set.cpp:66:2:66:4 | s11 | | +| set.cpp:65:19:65:21 | call to set | set.cpp:67:2:67:4 | s11 | | +| set.cpp:65:19:65:21 | call to set | set.cpp:68:2:68:4 | s11 | | +| set.cpp:65:19:65:21 | call to set | set.cpp:69:7:69:9 | s11 | | +| set.cpp:65:19:65:21 | call to set | set.cpp:70:7:70:9 | s11 | | +| set.cpp:65:19:65:21 | call to set | set.cpp:71:7:71:9 | s11 | | +| set.cpp:65:19:65:21 | call to set | set.cpp:72:7:72:9 | s11 | | +| set.cpp:65:19:65:21 | call to set | set.cpp:126:1:126:1 | s11 | | +| set.cpp:66:2:66:4 | ref arg s11 | set.cpp:67:2:67:4 | s11 | | +| set.cpp:66:2:66:4 | ref arg s11 | set.cpp:68:2:68:4 | s11 | | +| set.cpp:66:2:66:4 | ref arg s11 | set.cpp:69:7:69:9 | s11 | | +| set.cpp:66:2:66:4 | ref arg s11 | set.cpp:70:7:70:9 | s11 | | +| set.cpp:66:2:66:4 | ref arg s11 | set.cpp:71:7:71:9 | s11 | | +| set.cpp:66:2:66:4 | ref arg s11 | set.cpp:72:7:72:9 | s11 | | +| set.cpp:66:2:66:4 | ref arg s11 | set.cpp:126:1:126:1 | s11 | | +| set.cpp:67:2:67:4 | ref arg s11 | set.cpp:68:2:68:4 | s11 | | +| set.cpp:67:2:67:4 | ref arg s11 | set.cpp:69:7:69:9 | s11 | | +| set.cpp:67:2:67:4 | ref arg s11 | set.cpp:70:7:70:9 | s11 | | +| set.cpp:67:2:67:4 | ref arg s11 | set.cpp:71:7:71:9 | s11 | | +| set.cpp:67:2:67:4 | ref arg s11 | set.cpp:72:7:72:9 | s11 | | +| set.cpp:67:2:67:4 | ref arg s11 | set.cpp:126:1:126:1 | s11 | | +| set.cpp:68:2:68:4 | ref arg s11 | set.cpp:69:7:69:9 | s11 | | +| set.cpp:68:2:68:4 | ref arg s11 | set.cpp:70:7:70:9 | s11 | | +| set.cpp:68:2:68:4 | ref arg s11 | set.cpp:71:7:71:9 | s11 | | +| set.cpp:68:2:68:4 | ref arg s11 | set.cpp:72:7:72:9 | s11 | | +| set.cpp:68:2:68:4 | ref arg s11 | set.cpp:126:1:126:1 | s11 | | +| set.cpp:69:7:69:9 | ref arg s11 | set.cpp:70:7:70:9 | s11 | | +| set.cpp:69:7:69:9 | ref arg s11 | set.cpp:71:7:71:9 | s11 | | +| set.cpp:69:7:69:9 | ref arg s11 | set.cpp:72:7:72:9 | s11 | | +| set.cpp:69:7:69:9 | ref arg s11 | set.cpp:126:1:126:1 | s11 | | +| set.cpp:70:7:70:9 | ref arg s11 | set.cpp:71:7:71:9 | s11 | | +| set.cpp:70:7:70:9 | ref arg s11 | set.cpp:72:7:72:9 | s11 | | +| set.cpp:70:7:70:9 | ref arg s11 | set.cpp:126:1:126:1 | s11 | | +| set.cpp:71:7:71:9 | ref arg s11 | set.cpp:72:7:72:9 | s11 | | +| set.cpp:71:7:71:9 | ref arg s11 | set.cpp:126:1:126:1 | s11 | | +| set.cpp:71:28:71:32 | first | set.cpp:71:7:71:32 | call to iterator | | +| set.cpp:72:7:72:9 | ref arg s11 | set.cpp:126:1:126:1 | s11 | | +| set.cpp:72:28:72:33 | second | set.cpp:72:7:72:33 | call to iterator | | +| set.cpp:75:19:75:21 | call to set | set.cpp:76:2:76:4 | s12 | | +| set.cpp:75:19:75:21 | call to set | set.cpp:78:7:78:9 | s12 | | +| set.cpp:75:19:75:21 | call to set | set.cpp:82:2:82:4 | s12 | | +| set.cpp:75:19:75:21 | call to set | set.cpp:84:7:84:9 | s12 | | +| set.cpp:75:19:75:21 | call to set | set.cpp:126:1:126:1 | s12 | | +| set.cpp:75:24:75:26 | call to set | set.cpp:79:7:79:9 | s13 | | +| set.cpp:75:24:75:26 | call to set | set.cpp:82:11:82:13 | s13 | | +| set.cpp:75:24:75:26 | call to set | set.cpp:85:7:85:9 | s13 | | +| set.cpp:75:24:75:26 | call to set | set.cpp:126:1:126:1 | s13 | | +| set.cpp:75:29:75:31 | call to set | set.cpp:80:7:80:9 | s14 | | +| set.cpp:75:29:75:31 | call to set | set.cpp:83:2:83:4 | s14 | | +| set.cpp:75:29:75:31 | call to set | set.cpp:86:7:86:9 | s14 | | +| set.cpp:75:29:75:31 | call to set | set.cpp:126:1:126:1 | s14 | | +| set.cpp:75:34:75:36 | call to set | set.cpp:77:2:77:4 | s15 | | +| set.cpp:75:34:75:36 | call to set | set.cpp:81:7:81:9 | s15 | | +| set.cpp:75:34:75:36 | call to set | set.cpp:83:11:83:13 | s15 | | +| set.cpp:75:34:75:36 | call to set | set.cpp:87:7:87:9 | s15 | | +| set.cpp:75:34:75:36 | call to set | set.cpp:126:1:126:1 | s15 | | +| set.cpp:76:2:76:4 | ref arg s12 | set.cpp:78:7:78:9 | s12 | | +| set.cpp:76:2:76:4 | ref arg s12 | set.cpp:82:2:82:4 | s12 | | +| set.cpp:76:2:76:4 | ref arg s12 | set.cpp:84:7:84:9 | s12 | | +| set.cpp:76:2:76:4 | ref arg s12 | set.cpp:126:1:126:1 | s12 | | +| set.cpp:77:2:77:4 | ref arg s15 | set.cpp:81:7:81:9 | s15 | | +| set.cpp:77:2:77:4 | ref arg s15 | set.cpp:83:11:83:13 | s15 | | +| set.cpp:77:2:77:4 | ref arg s15 | set.cpp:87:7:87:9 | s15 | | +| set.cpp:77:2:77:4 | ref arg s15 | set.cpp:126:1:126:1 | s15 | | +| set.cpp:78:7:78:9 | s12 | set.cpp:78:7:78:9 | call to set | | +| set.cpp:79:7:79:9 | s13 | set.cpp:79:7:79:9 | call to set | | +| set.cpp:80:7:80:9 | s14 | set.cpp:80:7:80:9 | call to set | | +| set.cpp:81:7:81:9 | s15 | set.cpp:81:7:81:9 | call to set | | +| set.cpp:82:2:82:4 | ref arg s12 | set.cpp:84:7:84:9 | s12 | | +| set.cpp:82:2:82:4 | ref arg s12 | set.cpp:126:1:126:1 | s12 | | +| set.cpp:82:11:82:13 | ref arg s13 | set.cpp:85:7:85:9 | s13 | | +| set.cpp:82:11:82:13 | ref arg s13 | set.cpp:126:1:126:1 | s13 | | +| set.cpp:83:2:83:4 | ref arg s14 | set.cpp:86:7:86:9 | s14 | | +| set.cpp:83:2:83:4 | ref arg s14 | set.cpp:126:1:126:1 | s14 | | +| set.cpp:83:11:83:13 | ref arg s15 | set.cpp:87:7:87:9 | s15 | | +| set.cpp:83:11:83:13 | ref arg s15 | set.cpp:126:1:126:1 | s15 | | +| set.cpp:84:7:84:9 | s12 | set.cpp:84:7:84:9 | call to set | | +| set.cpp:85:7:85:9 | s13 | set.cpp:85:7:85:9 | call to set | | +| set.cpp:86:7:86:9 | s14 | set.cpp:86:7:86:9 | call to set | | +| set.cpp:87:7:87:9 | s15 | set.cpp:87:7:87:9 | call to set | | +| set.cpp:90:19:90:21 | call to set | set.cpp:91:2:91:4 | s16 | | +| set.cpp:90:19:90:21 | call to set | set.cpp:95:7:95:9 | s16 | | +| set.cpp:90:19:90:21 | call to set | set.cpp:99:2:99:4 | s16 | | +| set.cpp:90:19:90:21 | call to set | set.cpp:101:7:101:9 | s16 | | +| set.cpp:90:19:90:21 | call to set | set.cpp:126:1:126:1 | s16 | | +| set.cpp:90:24:90:26 | call to set | set.cpp:92:2:92:4 | s17 | | +| set.cpp:90:24:90:26 | call to set | set.cpp:96:7:96:9 | s17 | | +| set.cpp:90:24:90:26 | call to set | set.cpp:99:12:99:14 | s17 | | +| set.cpp:90:24:90:26 | call to set | set.cpp:102:7:102:9 | s17 | | +| set.cpp:90:24:90:26 | call to set | set.cpp:126:1:126:1 | s17 | | +| set.cpp:90:29:90:31 | call to set | set.cpp:93:2:93:4 | s18 | | +| set.cpp:90:29:90:31 | call to set | set.cpp:97:7:97:9 | s18 | | +| set.cpp:90:29:90:31 | call to set | set.cpp:100:2:100:4 | s18 | | +| set.cpp:90:29:90:31 | call to set | set.cpp:103:7:103:9 | s18 | | +| set.cpp:90:29:90:31 | call to set | set.cpp:126:1:126:1 | s18 | | +| set.cpp:90:34:90:36 | call to set | set.cpp:94:2:94:4 | s19 | | +| set.cpp:90:34:90:36 | call to set | set.cpp:98:7:98:9 | s19 | | +| set.cpp:90:34:90:36 | call to set | set.cpp:100:12:100:14 | s19 | | +| set.cpp:90:34:90:36 | call to set | set.cpp:104:7:104:9 | s19 | | +| set.cpp:90:34:90:36 | call to set | set.cpp:126:1:126:1 | s19 | | +| set.cpp:91:2:91:4 | ref arg s16 | set.cpp:95:7:95:9 | s16 | | +| set.cpp:91:2:91:4 | ref arg s16 | set.cpp:99:2:99:4 | s16 | | +| set.cpp:91:2:91:4 | ref arg s16 | set.cpp:101:7:101:9 | s16 | | +| set.cpp:91:2:91:4 | ref arg s16 | set.cpp:126:1:126:1 | s16 | | +| set.cpp:92:2:92:4 | ref arg s17 | set.cpp:96:7:96:9 | s17 | | +| set.cpp:92:2:92:4 | ref arg s17 | set.cpp:99:12:99:14 | s17 | | +| set.cpp:92:2:92:4 | ref arg s17 | set.cpp:102:7:102:9 | s17 | | +| set.cpp:92:2:92:4 | ref arg s17 | set.cpp:126:1:126:1 | s17 | | +| set.cpp:93:2:93:4 | ref arg s18 | set.cpp:97:7:97:9 | s18 | | +| set.cpp:93:2:93:4 | ref arg s18 | set.cpp:100:2:100:4 | s18 | | +| set.cpp:93:2:93:4 | ref arg s18 | set.cpp:103:7:103:9 | s18 | | +| set.cpp:93:2:93:4 | ref arg s18 | set.cpp:126:1:126:1 | s18 | | +| set.cpp:94:2:94:4 | ref arg s19 | set.cpp:98:7:98:9 | s19 | | +| set.cpp:94:2:94:4 | ref arg s19 | set.cpp:100:12:100:14 | s19 | | +| set.cpp:94:2:94:4 | ref arg s19 | set.cpp:104:7:104:9 | s19 | | +| set.cpp:94:2:94:4 | ref arg s19 | set.cpp:126:1:126:1 | s19 | | +| set.cpp:95:7:95:9 | s16 | set.cpp:95:7:95:9 | call to set | | +| set.cpp:96:7:96:9 | s17 | set.cpp:96:7:96:9 | call to set | | +| set.cpp:97:7:97:9 | s18 | set.cpp:97:7:97:9 | call to set | | +| set.cpp:98:7:98:9 | s19 | set.cpp:98:7:98:9 | call to set | | +| set.cpp:99:2:99:4 | ref arg s16 | set.cpp:101:7:101:9 | s16 | | +| set.cpp:99:2:99:4 | ref arg s16 | set.cpp:126:1:126:1 | s16 | | +| set.cpp:99:12:99:14 | ref arg s17 | set.cpp:102:7:102:9 | s17 | | +| set.cpp:99:12:99:14 | ref arg s17 | set.cpp:126:1:126:1 | s17 | | +| set.cpp:100:2:100:4 | ref arg s18 | set.cpp:103:7:103:9 | s18 | | +| set.cpp:100:2:100:4 | ref arg s18 | set.cpp:126:1:126:1 | s18 | | +| set.cpp:100:12:100:14 | ref arg s19 | set.cpp:104:7:104:9 | s19 | | +| set.cpp:100:12:100:14 | ref arg s19 | set.cpp:126:1:126:1 | s19 | | +| set.cpp:101:7:101:9 | s16 | set.cpp:101:7:101:9 | call to set | | +| set.cpp:102:7:102:9 | s17 | set.cpp:102:7:102:9 | call to set | | +| set.cpp:103:7:103:9 | s18 | set.cpp:103:7:103:9 | call to set | | +| set.cpp:104:7:104:9 | s19 | set.cpp:104:7:104:9 | call to set | | +| set.cpp:107:19:107:21 | call to set | set.cpp:108:2:108:4 | s20 | | +| set.cpp:107:19:107:21 | call to set | set.cpp:109:2:109:4 | s20 | | +| set.cpp:107:19:107:21 | call to set | set.cpp:110:7:110:9 | s20 | | +| set.cpp:107:19:107:21 | call to set | set.cpp:111:7:111:9 | s20 | | +| set.cpp:107:19:107:21 | call to set | set.cpp:111:17:111:19 | s20 | | +| set.cpp:107:19:107:21 | call to set | set.cpp:112:7:112:9 | s20 | | +| set.cpp:107:19:107:21 | call to set | set.cpp:113:2:113:4 | s20 | | +| set.cpp:107:19:107:21 | call to set | set.cpp:114:7:114:9 | s20 | | +| set.cpp:107:19:107:21 | call to set | set.cpp:126:1:126:1 | s20 | | +| set.cpp:108:2:108:4 | ref arg s20 | set.cpp:109:2:109:4 | s20 | | +| set.cpp:108:2:108:4 | ref arg s20 | set.cpp:110:7:110:9 | s20 | | +| set.cpp:108:2:108:4 | ref arg s20 | set.cpp:111:7:111:9 | s20 | | +| set.cpp:108:2:108:4 | ref arg s20 | set.cpp:111:17:111:19 | s20 | | +| set.cpp:108:2:108:4 | ref arg s20 | set.cpp:112:7:112:9 | s20 | | +| set.cpp:108:2:108:4 | ref arg s20 | set.cpp:113:2:113:4 | s20 | | +| set.cpp:108:2:108:4 | ref arg s20 | set.cpp:114:7:114:9 | s20 | | +| set.cpp:108:2:108:4 | ref arg s20 | set.cpp:126:1:126:1 | s20 | | +| set.cpp:109:2:109:4 | ref arg s20 | set.cpp:110:7:110:9 | s20 | | +| set.cpp:109:2:109:4 | ref arg s20 | set.cpp:111:7:111:9 | s20 | | +| set.cpp:109:2:109:4 | ref arg s20 | set.cpp:111:17:111:19 | s20 | | +| set.cpp:109:2:109:4 | ref arg s20 | set.cpp:112:7:112:9 | s20 | | +| set.cpp:109:2:109:4 | ref arg s20 | set.cpp:113:2:113:4 | s20 | | +| set.cpp:109:2:109:4 | ref arg s20 | set.cpp:114:7:114:9 | s20 | | +| set.cpp:109:2:109:4 | ref arg s20 | set.cpp:126:1:126:1 | s20 | | +| set.cpp:110:7:110:9 | s20 | set.cpp:110:7:110:9 | call to set | | +| set.cpp:111:7:111:9 | ref arg s20 | set.cpp:112:7:112:9 | s20 | | +| set.cpp:111:7:111:9 | ref arg s20 | set.cpp:113:2:113:4 | s20 | | +| set.cpp:111:7:111:9 | ref arg s20 | set.cpp:114:7:114:9 | s20 | | +| set.cpp:111:7:111:9 | ref arg s20 | set.cpp:126:1:126:1 | s20 | | +| set.cpp:111:17:111:19 | ref arg s20 | set.cpp:111:7:111:9 | s20 | | +| set.cpp:111:17:111:19 | ref arg s20 | set.cpp:112:7:112:9 | s20 | | +| set.cpp:111:17:111:19 | ref arg s20 | set.cpp:113:2:113:4 | s20 | | +| set.cpp:111:17:111:19 | ref arg s20 | set.cpp:114:7:114:9 | s20 | | +| set.cpp:111:17:111:19 | ref arg s20 | set.cpp:126:1:126:1 | s20 | | +| set.cpp:112:7:112:9 | s20 | set.cpp:112:7:112:9 | call to set | | +| set.cpp:113:2:113:4 | ref arg s20 | set.cpp:114:7:114:9 | s20 | | +| set.cpp:113:2:113:4 | ref arg s20 | set.cpp:126:1:126:1 | s20 | | +| set.cpp:114:7:114:9 | s20 | set.cpp:114:7:114:9 | call to set | | +| set.cpp:117:19:117:21 | call to set | set.cpp:118:7:118:9 | s21 | | +| set.cpp:117:19:117:21 | call to set | set.cpp:119:7:119:9 | s21 | | +| set.cpp:117:19:117:21 | call to set | set.cpp:120:7:120:9 | s21 | | +| set.cpp:117:19:117:21 | call to set | set.cpp:121:7:121:9 | s21 | | +| set.cpp:117:19:117:21 | call to set | set.cpp:126:1:126:1 | s21 | | +| set.cpp:117:24:117:26 | call to set | set.cpp:122:7:122:9 | s22 | | +| set.cpp:117:24:117:26 | call to set | set.cpp:122:24:122:26 | s22 | | +| set.cpp:117:24:117:26 | call to set | set.cpp:123:7:123:9 | s22 | | +| set.cpp:117:24:117:26 | call to set | set.cpp:124:7:124:9 | s22 | | +| set.cpp:117:24:117:26 | call to set | set.cpp:124:24:124:26 | s22 | | +| set.cpp:117:24:117:26 | call to set | set.cpp:125:7:125:9 | s22 | | +| set.cpp:117:24:117:26 | call to set | set.cpp:126:1:126:1 | s22 | | +| set.cpp:118:7:118:9 | ref arg s21 | set.cpp:119:7:119:9 | s21 | | +| set.cpp:118:7:118:9 | ref arg s21 | set.cpp:120:7:120:9 | s21 | | +| set.cpp:118:7:118:9 | ref arg s21 | set.cpp:121:7:121:9 | s21 | | +| set.cpp:118:7:118:9 | ref arg s21 | set.cpp:126:1:126:1 | s21 | | +| set.cpp:118:26:118:30 | first | set.cpp:118:7:118:30 | call to iterator | | +| set.cpp:119:7:119:9 | s21 | set.cpp:119:7:119:9 | call to set | | +| set.cpp:120:7:120:9 | ref arg s21 | set.cpp:121:7:121:9 | s21 | | +| set.cpp:120:7:120:9 | ref arg s21 | set.cpp:126:1:126:1 | s21 | | +| set.cpp:120:29:120:33 | first | set.cpp:120:7:120:33 | call to iterator | | +| set.cpp:121:7:121:9 | s21 | set.cpp:121:7:121:9 | call to set | | +| set.cpp:122:7:122:9 | ref arg s22 | set.cpp:123:7:123:9 | s22 | | +| set.cpp:122:7:122:9 | ref arg s22 | set.cpp:124:7:124:9 | s22 | | +| set.cpp:122:7:122:9 | ref arg s22 | set.cpp:124:24:124:26 | s22 | | +| set.cpp:122:7:122:9 | ref arg s22 | set.cpp:125:7:125:9 | s22 | | +| set.cpp:122:7:122:9 | ref arg s22 | set.cpp:126:1:126:1 | s22 | | +| set.cpp:122:24:122:26 | ref arg s22 | set.cpp:122:7:122:9 | s22 | | +| set.cpp:122:24:122:26 | ref arg s22 | set.cpp:123:7:123:9 | s22 | | +| set.cpp:122:24:122:26 | ref arg s22 | set.cpp:124:7:124:9 | s22 | | +| set.cpp:122:24:122:26 | ref arg s22 | set.cpp:124:24:124:26 | s22 | | +| set.cpp:122:24:122:26 | ref arg s22 | set.cpp:125:7:125:9 | s22 | | +| set.cpp:122:24:122:26 | ref arg s22 | set.cpp:126:1:126:1 | s22 | | +| set.cpp:122:28:122:32 | call to begin | set.cpp:122:24:122:34 | call to iterator | TAINT | +| set.cpp:123:7:123:9 | s22 | set.cpp:123:7:123:9 | call to set | | +| set.cpp:124:7:124:9 | ref arg s22 | set.cpp:125:7:125:9 | s22 | | +| set.cpp:124:7:124:9 | ref arg s22 | set.cpp:126:1:126:1 | s22 | | +| set.cpp:124:24:124:26 | ref arg s22 | set.cpp:124:7:124:9 | s22 | | +| set.cpp:124:24:124:26 | ref arg s22 | set.cpp:125:7:125:9 | s22 | | +| set.cpp:124:24:124:26 | ref arg s22 | set.cpp:126:1:126:1 | s22 | | +| set.cpp:124:28:124:32 | call to begin | set.cpp:124:24:124:34 | call to iterator | TAINT | +| set.cpp:125:7:125:9 | s22 | set.cpp:125:7:125:9 | call to set | | +| set.cpp:131:29:131:30 | call to unordered_set | set.cpp:133:7:133:8 | s1 | | +| set.cpp:131:29:131:30 | call to unordered_set | set.cpp:137:12:137:13 | s1 | | +| set.cpp:131:29:131:30 | call to unordered_set | set.cpp:137:24:137:25 | s1 | | +| set.cpp:131:29:131:30 | call to unordered_set | set.cpp:139:7:139:8 | s1 | | +| set.cpp:131:29:131:30 | call to unordered_set | set.cpp:145:7:145:8 | s1 | | +| set.cpp:131:29:131:30 | call to unordered_set | set.cpp:169:12:169:13 | s1 | | +| set.cpp:131:29:131:30 | call to unordered_set | set.cpp:169:30:169:31 | s1 | | +| set.cpp:131:29:131:30 | call to unordered_set | set.cpp:238:1:238:1 | s1 | | +| set.cpp:131:33:131:34 | call to unordered_set | set.cpp:134:7:134:8 | s2 | | +| set.cpp:131:33:131:34 | call to unordered_set | set.cpp:138:12:138:13 | s2 | | +| set.cpp:131:33:131:34 | call to unordered_set | set.cpp:138:24:138:25 | s2 | | +| set.cpp:131:33:131:34 | call to unordered_set | set.cpp:140:7:140:8 | s2 | | +| set.cpp:131:33:131:34 | call to unordered_set | set.cpp:146:7:146:8 | s2 | | +| set.cpp:131:33:131:34 | call to unordered_set | set.cpp:153:32:153:33 | s2 | | +| set.cpp:131:33:131:34 | call to unordered_set | set.cpp:154:34:154:35 | s2 | | +| set.cpp:131:33:131:34 | call to unordered_set | set.cpp:155:32:155:33 | s2 | | +| set.cpp:131:33:131:34 | call to unordered_set | set.cpp:155:44:155:45 | s2 | | +| set.cpp:131:33:131:34 | call to unordered_set | set.cpp:157:8:157:9 | s2 | | +| set.cpp:131:33:131:34 | call to unordered_set | set.cpp:173:12:173:13 | s2 | | +| set.cpp:131:33:131:34 | call to unordered_set | set.cpp:173:30:173:31 | s2 | | +| set.cpp:131:33:131:34 | call to unordered_set | set.cpp:238:1:238:1 | s2 | | +| set.cpp:131:37:131:38 | call to unordered_set | set.cpp:135:7:135:8 | s3 | | +| set.cpp:131:37:131:38 | call to unordered_set | set.cpp:135:17:135:18 | s3 | | +| set.cpp:131:37:131:38 | call to unordered_set | set.cpp:141:7:141:8 | s3 | | +| set.cpp:131:37:131:38 | call to unordered_set | set.cpp:147:7:147:8 | s3 | | +| set.cpp:131:37:131:38 | call to unordered_set | set.cpp:238:1:238:1 | s3 | | +| set.cpp:131:41:131:42 | call to unordered_set | set.cpp:136:7:136:8 | s4 | | +| set.cpp:131:41:131:42 | call to unordered_set | set.cpp:136:17:136:18 | s4 | | +| set.cpp:131:41:131:42 | call to unordered_set | set.cpp:142:7:142:8 | s4 | | +| set.cpp:131:41:131:42 | call to unordered_set | set.cpp:148:7:148:8 | s4 | | +| set.cpp:131:41:131:42 | call to unordered_set | set.cpp:238:1:238:1 | s4 | | +| set.cpp:131:45:131:46 | call to unordered_set | set.cpp:137:2:137:3 | s5 | | +| set.cpp:131:45:131:46 | call to unordered_set | set.cpp:143:7:143:8 | s5 | | +| set.cpp:131:45:131:46 | call to unordered_set | set.cpp:149:7:149:8 | s5 | | +| set.cpp:131:45:131:46 | call to unordered_set | set.cpp:238:1:238:1 | s5 | | +| set.cpp:131:49:131:50 | call to unordered_set | set.cpp:138:2:138:3 | s6 | | +| set.cpp:131:49:131:50 | call to unordered_set | set.cpp:144:7:144:8 | s6 | | +| set.cpp:131:49:131:50 | call to unordered_set | set.cpp:150:7:150:8 | s6 | | +| set.cpp:131:49:131:50 | call to unordered_set | set.cpp:238:1:238:1 | s6 | | +| set.cpp:133:7:133:8 | ref arg s1 | set.cpp:137:12:137:13 | s1 | | +| set.cpp:133:7:133:8 | ref arg s1 | set.cpp:137:24:137:25 | s1 | | +| set.cpp:133:7:133:8 | ref arg s1 | set.cpp:139:7:139:8 | s1 | | +| set.cpp:133:7:133:8 | ref arg s1 | set.cpp:145:7:145:8 | s1 | | +| set.cpp:133:7:133:8 | ref arg s1 | set.cpp:169:12:169:13 | s1 | | +| set.cpp:133:7:133:8 | ref arg s1 | set.cpp:169:30:169:31 | s1 | | +| set.cpp:133:7:133:8 | ref arg s1 | set.cpp:238:1:238:1 | s1 | | +| set.cpp:133:24:133:28 | first | set.cpp:133:7:133:28 | call to iterator | | +| set.cpp:134:7:134:8 | ref arg s2 | set.cpp:138:12:138:13 | s2 | | +| set.cpp:134:7:134:8 | ref arg s2 | set.cpp:138:24:138:25 | s2 | | +| set.cpp:134:7:134:8 | ref arg s2 | set.cpp:140:7:140:8 | s2 | | +| set.cpp:134:7:134:8 | ref arg s2 | set.cpp:146:7:146:8 | s2 | | +| set.cpp:134:7:134:8 | ref arg s2 | set.cpp:153:32:153:33 | s2 | | +| set.cpp:134:7:134:8 | ref arg s2 | set.cpp:154:34:154:35 | s2 | | +| set.cpp:134:7:134:8 | ref arg s2 | set.cpp:155:32:155:33 | s2 | | +| set.cpp:134:7:134:8 | ref arg s2 | set.cpp:155:44:155:45 | s2 | | +| set.cpp:134:7:134:8 | ref arg s2 | set.cpp:157:8:157:9 | s2 | | +| set.cpp:134:7:134:8 | ref arg s2 | set.cpp:173:12:173:13 | s2 | | +| set.cpp:134:7:134:8 | ref arg s2 | set.cpp:173:30:173:31 | s2 | | +| set.cpp:134:7:134:8 | ref arg s2 | set.cpp:238:1:238:1 | s2 | | +| set.cpp:134:27:134:31 | first | set.cpp:134:7:134:31 | call to iterator | | +| set.cpp:135:7:135:8 | ref arg s3 | set.cpp:141:7:141:8 | s3 | | +| set.cpp:135:7:135:8 | ref arg s3 | set.cpp:147:7:147:8 | s3 | | +| set.cpp:135:7:135:8 | ref arg s3 | set.cpp:238:1:238:1 | s3 | | +| set.cpp:135:17:135:18 | ref arg s3 | set.cpp:135:7:135:8 | s3 | | +| set.cpp:135:17:135:18 | ref arg s3 | set.cpp:141:7:141:8 | s3 | | +| set.cpp:135:17:135:18 | ref arg s3 | set.cpp:147:7:147:8 | s3 | | +| set.cpp:135:17:135:18 | ref arg s3 | set.cpp:238:1:238:1 | s3 | | +| set.cpp:135:20:135:24 | call to begin | set.cpp:135:17:135:26 | call to iterator | TAINT | +| set.cpp:136:7:136:8 | ref arg s4 | set.cpp:142:7:142:8 | s4 | | +| set.cpp:136:7:136:8 | ref arg s4 | set.cpp:148:7:148:8 | s4 | | +| set.cpp:136:7:136:8 | ref arg s4 | set.cpp:238:1:238:1 | s4 | | +| set.cpp:136:17:136:18 | ref arg s4 | set.cpp:136:7:136:8 | s4 | | +| set.cpp:136:17:136:18 | ref arg s4 | set.cpp:142:7:142:8 | s4 | | +| set.cpp:136:17:136:18 | ref arg s4 | set.cpp:148:7:148:8 | s4 | | +| set.cpp:136:17:136:18 | ref arg s4 | set.cpp:238:1:238:1 | s4 | | +| set.cpp:136:20:136:24 | call to begin | set.cpp:136:17:136:26 | call to iterator | TAINT | +| set.cpp:137:2:137:3 | ref arg s5 | set.cpp:143:7:143:8 | s5 | | +| set.cpp:137:2:137:3 | ref arg s5 | set.cpp:149:7:149:8 | s5 | | +| set.cpp:137:2:137:3 | ref arg s5 | set.cpp:238:1:238:1 | s5 | | +| set.cpp:137:12:137:13 | ref arg s1 | set.cpp:137:24:137:25 | s1 | | +| set.cpp:137:12:137:13 | ref arg s1 | set.cpp:139:7:139:8 | s1 | | +| set.cpp:137:12:137:13 | ref arg s1 | set.cpp:145:7:145:8 | s1 | | +| set.cpp:137:12:137:13 | ref arg s1 | set.cpp:169:12:169:13 | s1 | | +| set.cpp:137:12:137:13 | ref arg s1 | set.cpp:169:30:169:31 | s1 | | +| set.cpp:137:12:137:13 | ref arg s1 | set.cpp:238:1:238:1 | s1 | | +| set.cpp:137:24:137:25 | ref arg s1 | set.cpp:139:7:139:8 | s1 | | +| set.cpp:137:24:137:25 | ref arg s1 | set.cpp:145:7:145:8 | s1 | | +| set.cpp:137:24:137:25 | ref arg s1 | set.cpp:169:12:169:13 | s1 | | +| set.cpp:137:24:137:25 | ref arg s1 | set.cpp:169:30:169:31 | s1 | | +| set.cpp:137:24:137:25 | ref arg s1 | set.cpp:238:1:238:1 | s1 | | +| set.cpp:138:2:138:3 | ref arg s6 | set.cpp:144:7:144:8 | s6 | | +| set.cpp:138:2:138:3 | ref arg s6 | set.cpp:150:7:150:8 | s6 | | +| set.cpp:138:2:138:3 | ref arg s6 | set.cpp:238:1:238:1 | s6 | | +| set.cpp:138:12:138:13 | ref arg s2 | set.cpp:138:24:138:25 | s2 | | +| set.cpp:138:12:138:13 | ref arg s2 | set.cpp:140:7:140:8 | s2 | | +| set.cpp:138:12:138:13 | ref arg s2 | set.cpp:146:7:146:8 | s2 | | +| set.cpp:138:12:138:13 | ref arg s2 | set.cpp:153:32:153:33 | s2 | | +| set.cpp:138:12:138:13 | ref arg s2 | set.cpp:154:34:154:35 | s2 | | +| set.cpp:138:12:138:13 | ref arg s2 | set.cpp:155:32:155:33 | s2 | | +| set.cpp:138:12:138:13 | ref arg s2 | set.cpp:155:44:155:45 | s2 | | +| set.cpp:138:12:138:13 | ref arg s2 | set.cpp:157:8:157:9 | s2 | | +| set.cpp:138:12:138:13 | ref arg s2 | set.cpp:173:12:173:13 | s2 | | +| set.cpp:138:12:138:13 | ref arg s2 | set.cpp:173:30:173:31 | s2 | | +| set.cpp:138:12:138:13 | ref arg s2 | set.cpp:238:1:238:1 | s2 | | +| set.cpp:138:24:138:25 | ref arg s2 | set.cpp:140:7:140:8 | s2 | | +| set.cpp:138:24:138:25 | ref arg s2 | set.cpp:146:7:146:8 | s2 | | +| set.cpp:138:24:138:25 | ref arg s2 | set.cpp:153:32:153:33 | s2 | | +| set.cpp:138:24:138:25 | ref arg s2 | set.cpp:154:34:154:35 | s2 | | +| set.cpp:138:24:138:25 | ref arg s2 | set.cpp:155:32:155:33 | s2 | | +| set.cpp:138:24:138:25 | ref arg s2 | set.cpp:155:44:155:45 | s2 | | +| set.cpp:138:24:138:25 | ref arg s2 | set.cpp:157:8:157:9 | s2 | | +| set.cpp:138:24:138:25 | ref arg s2 | set.cpp:173:12:173:13 | s2 | | +| set.cpp:138:24:138:25 | ref arg s2 | set.cpp:173:30:173:31 | s2 | | +| set.cpp:138:24:138:25 | ref arg s2 | set.cpp:238:1:238:1 | s2 | | +| set.cpp:139:7:139:8 | s1 | set.cpp:139:7:139:8 | call to unordered_set | | +| set.cpp:140:7:140:8 | s2 | set.cpp:140:7:140:8 | call to unordered_set | | +| set.cpp:141:7:141:8 | s3 | set.cpp:141:7:141:8 | call to unordered_set | | +| set.cpp:142:7:142:8 | s4 | set.cpp:142:7:142:8 | call to unordered_set | | +| set.cpp:143:7:143:8 | s5 | set.cpp:143:7:143:8 | call to unordered_set | | +| set.cpp:144:7:144:8 | s6 | set.cpp:144:7:144:8 | call to unordered_set | | +| set.cpp:145:7:145:8 | ref arg s1 | set.cpp:169:12:169:13 | s1 | | +| set.cpp:145:7:145:8 | ref arg s1 | set.cpp:169:30:169:31 | s1 | | +| set.cpp:145:7:145:8 | ref arg s1 | set.cpp:238:1:238:1 | s1 | | +| set.cpp:146:7:146:8 | ref arg s2 | set.cpp:153:32:153:33 | s2 | | +| set.cpp:146:7:146:8 | ref arg s2 | set.cpp:154:34:154:35 | s2 | | +| set.cpp:146:7:146:8 | ref arg s2 | set.cpp:155:32:155:33 | s2 | | +| set.cpp:146:7:146:8 | ref arg s2 | set.cpp:155:44:155:45 | s2 | | +| set.cpp:146:7:146:8 | ref arg s2 | set.cpp:157:8:157:9 | s2 | | +| set.cpp:146:7:146:8 | ref arg s2 | set.cpp:173:12:173:13 | s2 | | +| set.cpp:146:7:146:8 | ref arg s2 | set.cpp:173:30:173:31 | s2 | | +| set.cpp:146:7:146:8 | ref arg s2 | set.cpp:238:1:238:1 | s2 | | +| set.cpp:147:7:147:8 | ref arg s3 | set.cpp:238:1:238:1 | s3 | | +| set.cpp:148:7:148:8 | ref arg s4 | set.cpp:238:1:238:1 | s4 | | +| set.cpp:149:7:149:8 | ref arg s5 | set.cpp:238:1:238:1 | s5 | | +| set.cpp:150:7:150:8 | ref arg s6 | set.cpp:238:1:238:1 | s6 | | +| set.cpp:153:32:153:33 | s2 | set.cpp:153:32:153:34 | call to unordered_set | | +| set.cpp:153:32:153:34 | call to unordered_set | set.cpp:158:7:158:8 | s7 | | +| set.cpp:153:32:153:34 | call to unordered_set | set.cpp:162:7:162:8 | s7 | | +| set.cpp:153:32:153:34 | call to unordered_set | set.cpp:238:1:238:1 | s7 | | +| set.cpp:154:33:154:35 | call to unordered_set | set.cpp:159:7:159:8 | s8 | | +| set.cpp:154:33:154:35 | call to unordered_set | set.cpp:163:7:163:8 | s8 | | +| set.cpp:154:33:154:35 | call to unordered_set | set.cpp:238:1:238:1 | s8 | | +| set.cpp:154:34:154:35 | s2 | set.cpp:154:33:154:35 | call to unordered_set | | +| set.cpp:155:32:155:33 | ref arg s2 | set.cpp:155:44:155:45 | s2 | | +| set.cpp:155:32:155:33 | ref arg s2 | set.cpp:157:8:157:9 | s2 | | +| set.cpp:155:32:155:33 | ref arg s2 | set.cpp:173:12:173:13 | s2 | | +| set.cpp:155:32:155:33 | ref arg s2 | set.cpp:173:30:173:31 | s2 | | +| set.cpp:155:32:155:33 | ref arg s2 | set.cpp:238:1:238:1 | s2 | | +| set.cpp:155:32:155:52 | call to unordered_set | set.cpp:160:7:160:8 | s9 | | +| set.cpp:155:32:155:52 | call to unordered_set | set.cpp:164:7:164:8 | s9 | | +| set.cpp:155:32:155:52 | call to unordered_set | set.cpp:238:1:238:1 | s9 | | +| set.cpp:155:44:155:45 | ref arg s2 | set.cpp:157:8:157:9 | s2 | | +| set.cpp:155:44:155:45 | ref arg s2 | set.cpp:173:12:173:13 | s2 | | +| set.cpp:155:44:155:45 | ref arg s2 | set.cpp:173:30:173:31 | s2 | | +| set.cpp:155:44:155:45 | ref arg s2 | set.cpp:238:1:238:1 | s2 | | +| set.cpp:156:29:156:31 | call to unordered_set | set.cpp:157:2:157:4 | s10 | | +| set.cpp:156:29:156:31 | call to unordered_set | set.cpp:161:7:161:9 | s10 | | +| set.cpp:156:29:156:31 | call to unordered_set | set.cpp:165:7:165:9 | s10 | | +| set.cpp:156:29:156:31 | call to unordered_set | set.cpp:238:1:238:1 | s10 | | +| set.cpp:157:2:157:4 | ref arg s10 | set.cpp:161:7:161:9 | s10 | | +| set.cpp:157:2:157:4 | ref arg s10 | set.cpp:165:7:165:9 | s10 | | +| set.cpp:157:2:157:4 | ref arg s10 | set.cpp:238:1:238:1 | s10 | | +| set.cpp:157:8:157:9 | s2 | set.cpp:157:2:157:4 | ref arg s10 | TAINT | +| set.cpp:157:8:157:9 | s2 | set.cpp:157:6:157:6 | call to operator= | TAINT | +| set.cpp:158:7:158:8 | s7 | set.cpp:158:7:158:8 | call to unordered_set | | +| set.cpp:159:7:159:8 | s8 | set.cpp:159:7:159:8 | call to unordered_set | | +| set.cpp:160:7:160:8 | s9 | set.cpp:160:7:160:8 | call to unordered_set | | +| set.cpp:161:7:161:9 | s10 | set.cpp:161:7:161:9 | call to unordered_set | | +| set.cpp:162:7:162:8 | ref arg s7 | set.cpp:238:1:238:1 | s7 | | +| set.cpp:163:7:163:8 | ref arg s8 | set.cpp:238:1:238:1 | s8 | | +| set.cpp:164:7:164:8 | ref arg s9 | set.cpp:238:1:238:1 | s9 | | +| set.cpp:165:7:165:9 | ref arg s10 | set.cpp:238:1:238:1 | s10 | | +| set.cpp:169:12:169:13 | ref arg s1 | set.cpp:169:30:169:31 | s1 | | +| set.cpp:169:12:169:13 | ref arg s1 | set.cpp:238:1:238:1 | s1 | | +| set.cpp:169:15:169:19 | call to begin | set.cpp:169:7:169:21 | ... = ... | | +| set.cpp:169:15:169:19 | call to begin | set.cpp:169:24:169:25 | i1 | | +| set.cpp:169:15:169:19 | call to begin | set.cpp:169:40:169:41 | i1 | | +| set.cpp:169:15:169:19 | call to begin | set.cpp:171:9:171:10 | i1 | | +| set.cpp:169:30:169:31 | ref arg s1 | set.cpp:169:30:169:31 | s1 | | +| set.cpp:169:30:169:31 | ref arg s1 | set.cpp:238:1:238:1 | s1 | | +| set.cpp:169:40:169:41 | i1 | set.cpp:169:42:169:42 | call to operator++ | | +| set.cpp:169:40:169:41 | ref arg i1 | set.cpp:169:24:169:25 | i1 | | +| set.cpp:169:40:169:41 | ref arg i1 | set.cpp:169:40:169:41 | i1 | | +| set.cpp:169:40:169:41 | ref arg i1 | set.cpp:171:9:171:10 | i1 | | +| set.cpp:171:9:171:10 | i1 | set.cpp:171:8:171:8 | call to operator* | TAINT | +| set.cpp:173:12:173:13 | ref arg s2 | set.cpp:173:30:173:31 | s2 | | +| set.cpp:173:12:173:13 | ref arg s2 | set.cpp:238:1:238:1 | s2 | | +| set.cpp:173:15:173:19 | call to begin | set.cpp:173:7:173:21 | ... = ... | | +| set.cpp:173:15:173:19 | call to begin | set.cpp:173:24:173:25 | i2 | | +| set.cpp:173:15:173:19 | call to begin | set.cpp:173:40:173:41 | i2 | | +| set.cpp:173:15:173:19 | call to begin | set.cpp:175:9:175:10 | i2 | | +| set.cpp:173:30:173:31 | ref arg s2 | set.cpp:173:30:173:31 | s2 | | +| set.cpp:173:30:173:31 | ref arg s2 | set.cpp:238:1:238:1 | s2 | | +| set.cpp:173:40:173:41 | i2 | set.cpp:173:42:173:42 | call to operator++ | | +| set.cpp:173:40:173:41 | ref arg i2 | set.cpp:173:24:173:25 | i2 | | +| set.cpp:173:40:173:41 | ref arg i2 | set.cpp:173:40:173:41 | i2 | | +| set.cpp:173:40:173:41 | ref arg i2 | set.cpp:175:9:175:10 | i2 | | +| set.cpp:175:9:175:10 | i2 | set.cpp:175:8:175:8 | call to operator* | TAINT | +| set.cpp:179:29:179:31 | call to unordered_set | set.cpp:180:2:180:4 | s11 | | +| set.cpp:179:29:179:31 | call to unordered_set | set.cpp:181:2:181:4 | s11 | | +| set.cpp:179:29:179:31 | call to unordered_set | set.cpp:182:2:182:4 | s11 | | +| set.cpp:179:29:179:31 | call to unordered_set | set.cpp:183:7:183:9 | s11 | | +| set.cpp:179:29:179:31 | call to unordered_set | set.cpp:184:7:184:9 | s11 | | +| set.cpp:179:29:179:31 | call to unordered_set | set.cpp:238:1:238:1 | s11 | | +| set.cpp:180:2:180:4 | ref arg s11 | set.cpp:181:2:181:4 | s11 | | +| set.cpp:180:2:180:4 | ref arg s11 | set.cpp:182:2:182:4 | s11 | | +| set.cpp:180:2:180:4 | ref arg s11 | set.cpp:183:7:183:9 | s11 | | +| set.cpp:180:2:180:4 | ref arg s11 | set.cpp:184:7:184:9 | s11 | | +| set.cpp:180:2:180:4 | ref arg s11 | set.cpp:238:1:238:1 | s11 | | +| set.cpp:181:2:181:4 | ref arg s11 | set.cpp:182:2:182:4 | s11 | | +| set.cpp:181:2:181:4 | ref arg s11 | set.cpp:183:7:183:9 | s11 | | +| set.cpp:181:2:181:4 | ref arg s11 | set.cpp:184:7:184:9 | s11 | | +| set.cpp:181:2:181:4 | ref arg s11 | set.cpp:238:1:238:1 | s11 | | +| set.cpp:182:2:182:4 | ref arg s11 | set.cpp:183:7:183:9 | s11 | | +| set.cpp:182:2:182:4 | ref arg s11 | set.cpp:184:7:184:9 | s11 | | +| set.cpp:182:2:182:4 | ref arg s11 | set.cpp:238:1:238:1 | s11 | | +| set.cpp:183:7:183:9 | ref arg s11 | set.cpp:184:7:184:9 | s11 | | +| set.cpp:183:7:183:9 | ref arg s11 | set.cpp:238:1:238:1 | s11 | | +| set.cpp:183:28:183:32 | first | set.cpp:183:7:183:32 | call to iterator | | +| set.cpp:184:7:184:9 | ref arg s11 | set.cpp:238:1:238:1 | s11 | | +| set.cpp:184:28:184:33 | second | set.cpp:184:7:184:33 | call to iterator | | +| set.cpp:187:29:187:31 | call to unordered_set | set.cpp:188:2:188:4 | s12 | | +| set.cpp:187:29:187:31 | call to unordered_set | set.cpp:190:7:190:9 | s12 | | +| set.cpp:187:29:187:31 | call to unordered_set | set.cpp:194:2:194:4 | s12 | | +| set.cpp:187:29:187:31 | call to unordered_set | set.cpp:196:7:196:9 | s12 | | +| set.cpp:187:29:187:31 | call to unordered_set | set.cpp:238:1:238:1 | s12 | | +| set.cpp:187:34:187:36 | call to unordered_set | set.cpp:191:7:191:9 | s13 | | +| set.cpp:187:34:187:36 | call to unordered_set | set.cpp:194:11:194:13 | s13 | | +| set.cpp:187:34:187:36 | call to unordered_set | set.cpp:197:7:197:9 | s13 | | +| set.cpp:187:34:187:36 | call to unordered_set | set.cpp:238:1:238:1 | s13 | | +| set.cpp:187:39:187:41 | call to unordered_set | set.cpp:192:7:192:9 | s14 | | +| set.cpp:187:39:187:41 | call to unordered_set | set.cpp:195:2:195:4 | s14 | | +| set.cpp:187:39:187:41 | call to unordered_set | set.cpp:198:7:198:9 | s14 | | +| set.cpp:187:39:187:41 | call to unordered_set | set.cpp:238:1:238:1 | s14 | | +| set.cpp:187:44:187:46 | call to unordered_set | set.cpp:189:2:189:4 | s15 | | +| set.cpp:187:44:187:46 | call to unordered_set | set.cpp:193:7:193:9 | s15 | | +| set.cpp:187:44:187:46 | call to unordered_set | set.cpp:195:11:195:13 | s15 | | +| set.cpp:187:44:187:46 | call to unordered_set | set.cpp:199:7:199:9 | s15 | | +| set.cpp:187:44:187:46 | call to unordered_set | set.cpp:238:1:238:1 | s15 | | +| set.cpp:188:2:188:4 | ref arg s12 | set.cpp:190:7:190:9 | s12 | | +| set.cpp:188:2:188:4 | ref arg s12 | set.cpp:194:2:194:4 | s12 | | +| set.cpp:188:2:188:4 | ref arg s12 | set.cpp:196:7:196:9 | s12 | | +| set.cpp:188:2:188:4 | ref arg s12 | set.cpp:238:1:238:1 | s12 | | +| set.cpp:189:2:189:4 | ref arg s15 | set.cpp:193:7:193:9 | s15 | | +| set.cpp:189:2:189:4 | ref arg s15 | set.cpp:195:11:195:13 | s15 | | +| set.cpp:189:2:189:4 | ref arg s15 | set.cpp:199:7:199:9 | s15 | | +| set.cpp:189:2:189:4 | ref arg s15 | set.cpp:238:1:238:1 | s15 | | +| set.cpp:190:7:190:9 | s12 | set.cpp:190:7:190:9 | call to unordered_set | | +| set.cpp:191:7:191:9 | s13 | set.cpp:191:7:191:9 | call to unordered_set | | +| set.cpp:192:7:192:9 | s14 | set.cpp:192:7:192:9 | call to unordered_set | | +| set.cpp:193:7:193:9 | s15 | set.cpp:193:7:193:9 | call to unordered_set | | +| set.cpp:194:2:194:4 | ref arg s12 | set.cpp:196:7:196:9 | s12 | | +| set.cpp:194:2:194:4 | ref arg s12 | set.cpp:238:1:238:1 | s12 | | +| set.cpp:194:11:194:13 | ref arg s13 | set.cpp:197:7:197:9 | s13 | | +| set.cpp:194:11:194:13 | ref arg s13 | set.cpp:238:1:238:1 | s13 | | +| set.cpp:195:2:195:4 | ref arg s14 | set.cpp:198:7:198:9 | s14 | | +| set.cpp:195:2:195:4 | ref arg s14 | set.cpp:238:1:238:1 | s14 | | +| set.cpp:195:11:195:13 | ref arg s15 | set.cpp:199:7:199:9 | s15 | | +| set.cpp:195:11:195:13 | ref arg s15 | set.cpp:238:1:238:1 | s15 | | +| set.cpp:196:7:196:9 | s12 | set.cpp:196:7:196:9 | call to unordered_set | | +| set.cpp:197:7:197:9 | s13 | set.cpp:197:7:197:9 | call to unordered_set | | +| set.cpp:198:7:198:9 | s14 | set.cpp:198:7:198:9 | call to unordered_set | | +| set.cpp:199:7:199:9 | s15 | set.cpp:199:7:199:9 | call to unordered_set | | +| set.cpp:202:29:202:31 | call to unordered_set | set.cpp:203:2:203:4 | s16 | | +| set.cpp:202:29:202:31 | call to unordered_set | set.cpp:207:7:207:9 | s16 | | +| set.cpp:202:29:202:31 | call to unordered_set | set.cpp:211:2:211:4 | s16 | | +| set.cpp:202:29:202:31 | call to unordered_set | set.cpp:213:7:213:9 | s16 | | +| set.cpp:202:29:202:31 | call to unordered_set | set.cpp:238:1:238:1 | s16 | | +| set.cpp:202:34:202:36 | call to unordered_set | set.cpp:204:2:204:4 | s17 | | +| set.cpp:202:34:202:36 | call to unordered_set | set.cpp:208:7:208:9 | s17 | | +| set.cpp:202:34:202:36 | call to unordered_set | set.cpp:211:12:211:14 | s17 | | +| set.cpp:202:34:202:36 | call to unordered_set | set.cpp:214:7:214:9 | s17 | | +| set.cpp:202:34:202:36 | call to unordered_set | set.cpp:238:1:238:1 | s17 | | +| set.cpp:202:39:202:41 | call to unordered_set | set.cpp:205:2:205:4 | s18 | | +| set.cpp:202:39:202:41 | call to unordered_set | set.cpp:209:7:209:9 | s18 | | +| set.cpp:202:39:202:41 | call to unordered_set | set.cpp:212:2:212:4 | s18 | | +| set.cpp:202:39:202:41 | call to unordered_set | set.cpp:215:7:215:9 | s18 | | +| set.cpp:202:39:202:41 | call to unordered_set | set.cpp:238:1:238:1 | s18 | | +| set.cpp:202:44:202:46 | call to unordered_set | set.cpp:206:2:206:4 | s19 | | +| set.cpp:202:44:202:46 | call to unordered_set | set.cpp:210:7:210:9 | s19 | | +| set.cpp:202:44:202:46 | call to unordered_set | set.cpp:212:12:212:14 | s19 | | +| set.cpp:202:44:202:46 | call to unordered_set | set.cpp:216:7:216:9 | s19 | | +| set.cpp:202:44:202:46 | call to unordered_set | set.cpp:238:1:238:1 | s19 | | +| set.cpp:203:2:203:4 | ref arg s16 | set.cpp:207:7:207:9 | s16 | | +| set.cpp:203:2:203:4 | ref arg s16 | set.cpp:211:2:211:4 | s16 | | +| set.cpp:203:2:203:4 | ref arg s16 | set.cpp:213:7:213:9 | s16 | | +| set.cpp:203:2:203:4 | ref arg s16 | set.cpp:238:1:238:1 | s16 | | +| set.cpp:204:2:204:4 | ref arg s17 | set.cpp:208:7:208:9 | s17 | | +| set.cpp:204:2:204:4 | ref arg s17 | set.cpp:211:12:211:14 | s17 | | +| set.cpp:204:2:204:4 | ref arg s17 | set.cpp:214:7:214:9 | s17 | | +| set.cpp:204:2:204:4 | ref arg s17 | set.cpp:238:1:238:1 | s17 | | +| set.cpp:205:2:205:4 | ref arg s18 | set.cpp:209:7:209:9 | s18 | | +| set.cpp:205:2:205:4 | ref arg s18 | set.cpp:212:2:212:4 | s18 | | +| set.cpp:205:2:205:4 | ref arg s18 | set.cpp:215:7:215:9 | s18 | | +| set.cpp:205:2:205:4 | ref arg s18 | set.cpp:238:1:238:1 | s18 | | +| set.cpp:206:2:206:4 | ref arg s19 | set.cpp:210:7:210:9 | s19 | | +| set.cpp:206:2:206:4 | ref arg s19 | set.cpp:212:12:212:14 | s19 | | +| set.cpp:206:2:206:4 | ref arg s19 | set.cpp:216:7:216:9 | s19 | | +| set.cpp:206:2:206:4 | ref arg s19 | set.cpp:238:1:238:1 | s19 | | +| set.cpp:207:7:207:9 | s16 | set.cpp:207:7:207:9 | call to unordered_set | | +| set.cpp:208:7:208:9 | s17 | set.cpp:208:7:208:9 | call to unordered_set | | +| set.cpp:209:7:209:9 | s18 | set.cpp:209:7:209:9 | call to unordered_set | | +| set.cpp:210:7:210:9 | s19 | set.cpp:210:7:210:9 | call to unordered_set | | +| set.cpp:211:2:211:4 | ref arg s16 | set.cpp:213:7:213:9 | s16 | | +| set.cpp:211:2:211:4 | ref arg s16 | set.cpp:238:1:238:1 | s16 | | +| set.cpp:211:12:211:14 | ref arg s17 | set.cpp:214:7:214:9 | s17 | | +| set.cpp:211:12:211:14 | ref arg s17 | set.cpp:238:1:238:1 | s17 | | +| set.cpp:212:2:212:4 | ref arg s18 | set.cpp:215:7:215:9 | s18 | | +| set.cpp:212:2:212:4 | ref arg s18 | set.cpp:238:1:238:1 | s18 | | +| set.cpp:212:12:212:14 | ref arg s19 | set.cpp:216:7:216:9 | s19 | | +| set.cpp:212:12:212:14 | ref arg s19 | set.cpp:238:1:238:1 | s19 | | +| set.cpp:213:7:213:9 | s16 | set.cpp:213:7:213:9 | call to unordered_set | | +| set.cpp:214:7:214:9 | s17 | set.cpp:214:7:214:9 | call to unordered_set | | +| set.cpp:215:7:215:9 | s18 | set.cpp:215:7:215:9 | call to unordered_set | | +| set.cpp:216:7:216:9 | s19 | set.cpp:216:7:216:9 | call to unordered_set | | +| set.cpp:219:29:219:31 | call to unordered_set | set.cpp:220:2:220:4 | s20 | | +| set.cpp:219:29:219:31 | call to unordered_set | set.cpp:221:2:221:4 | s20 | | +| set.cpp:219:29:219:31 | call to unordered_set | set.cpp:222:7:222:9 | s20 | | +| set.cpp:219:29:219:31 | call to unordered_set | set.cpp:223:7:223:9 | s20 | | +| set.cpp:219:29:219:31 | call to unordered_set | set.cpp:223:17:223:19 | s20 | | +| set.cpp:219:29:219:31 | call to unordered_set | set.cpp:224:7:224:9 | s20 | | +| set.cpp:219:29:219:31 | call to unordered_set | set.cpp:225:2:225:4 | s20 | | +| set.cpp:219:29:219:31 | call to unordered_set | set.cpp:226:7:226:9 | s20 | | +| set.cpp:219:29:219:31 | call to unordered_set | set.cpp:238:1:238:1 | s20 | | +| set.cpp:220:2:220:4 | ref arg s20 | set.cpp:221:2:221:4 | s20 | | +| set.cpp:220:2:220:4 | ref arg s20 | set.cpp:222:7:222:9 | s20 | | +| set.cpp:220:2:220:4 | ref arg s20 | set.cpp:223:7:223:9 | s20 | | +| set.cpp:220:2:220:4 | ref arg s20 | set.cpp:223:17:223:19 | s20 | | +| set.cpp:220:2:220:4 | ref arg s20 | set.cpp:224:7:224:9 | s20 | | +| set.cpp:220:2:220:4 | ref arg s20 | set.cpp:225:2:225:4 | s20 | | +| set.cpp:220:2:220:4 | ref arg s20 | set.cpp:226:7:226:9 | s20 | | +| set.cpp:220:2:220:4 | ref arg s20 | set.cpp:238:1:238:1 | s20 | | +| set.cpp:221:2:221:4 | ref arg s20 | set.cpp:222:7:222:9 | s20 | | +| set.cpp:221:2:221:4 | ref arg s20 | set.cpp:223:7:223:9 | s20 | | +| set.cpp:221:2:221:4 | ref arg s20 | set.cpp:223:17:223:19 | s20 | | +| set.cpp:221:2:221:4 | ref arg s20 | set.cpp:224:7:224:9 | s20 | | +| set.cpp:221:2:221:4 | ref arg s20 | set.cpp:225:2:225:4 | s20 | | +| set.cpp:221:2:221:4 | ref arg s20 | set.cpp:226:7:226:9 | s20 | | +| set.cpp:221:2:221:4 | ref arg s20 | set.cpp:238:1:238:1 | s20 | | +| set.cpp:222:7:222:9 | s20 | set.cpp:222:7:222:9 | call to unordered_set | | +| set.cpp:223:7:223:9 | ref arg s20 | set.cpp:224:7:224:9 | s20 | | +| set.cpp:223:7:223:9 | ref arg s20 | set.cpp:225:2:225:4 | s20 | | +| set.cpp:223:7:223:9 | ref arg s20 | set.cpp:226:7:226:9 | s20 | | +| set.cpp:223:7:223:9 | ref arg s20 | set.cpp:238:1:238:1 | s20 | | +| set.cpp:223:17:223:19 | ref arg s20 | set.cpp:223:7:223:9 | s20 | | +| set.cpp:223:17:223:19 | ref arg s20 | set.cpp:224:7:224:9 | s20 | | +| set.cpp:223:17:223:19 | ref arg s20 | set.cpp:225:2:225:4 | s20 | | +| set.cpp:223:17:223:19 | ref arg s20 | set.cpp:226:7:226:9 | s20 | | +| set.cpp:223:17:223:19 | ref arg s20 | set.cpp:238:1:238:1 | s20 | | +| set.cpp:224:7:224:9 | s20 | set.cpp:224:7:224:9 | call to unordered_set | | +| set.cpp:225:2:225:4 | ref arg s20 | set.cpp:226:7:226:9 | s20 | | +| set.cpp:225:2:225:4 | ref arg s20 | set.cpp:238:1:238:1 | s20 | | +| set.cpp:226:7:226:9 | s20 | set.cpp:226:7:226:9 | call to unordered_set | | +| set.cpp:229:29:229:31 | call to unordered_set | set.cpp:230:7:230:9 | s21 | | +| set.cpp:229:29:229:31 | call to unordered_set | set.cpp:231:7:231:9 | s21 | | +| set.cpp:229:29:229:31 | call to unordered_set | set.cpp:232:7:232:9 | s21 | | +| set.cpp:229:29:229:31 | call to unordered_set | set.cpp:233:7:233:9 | s21 | | +| set.cpp:229:29:229:31 | call to unordered_set | set.cpp:238:1:238:1 | s21 | | +| set.cpp:229:34:229:36 | call to unordered_set | set.cpp:234:7:234:9 | s22 | | +| set.cpp:229:34:229:36 | call to unordered_set | set.cpp:234:24:234:26 | s22 | | +| set.cpp:229:34:229:36 | call to unordered_set | set.cpp:235:7:235:9 | s22 | | +| set.cpp:229:34:229:36 | call to unordered_set | set.cpp:236:7:236:9 | s22 | | +| set.cpp:229:34:229:36 | call to unordered_set | set.cpp:236:24:236:26 | s22 | | +| set.cpp:229:34:229:36 | call to unordered_set | set.cpp:237:7:237:9 | s22 | | +| set.cpp:229:34:229:36 | call to unordered_set | set.cpp:238:1:238:1 | s22 | | +| set.cpp:230:7:230:9 | ref arg s21 | set.cpp:231:7:231:9 | s21 | | +| set.cpp:230:7:230:9 | ref arg s21 | set.cpp:232:7:232:9 | s21 | | +| set.cpp:230:7:230:9 | ref arg s21 | set.cpp:233:7:233:9 | s21 | | +| set.cpp:230:7:230:9 | ref arg s21 | set.cpp:238:1:238:1 | s21 | | +| set.cpp:230:26:230:30 | first | set.cpp:230:7:230:30 | call to iterator | | +| set.cpp:231:7:231:9 | s21 | set.cpp:231:7:231:9 | call to unordered_set | | +| set.cpp:232:7:232:9 | ref arg s21 | set.cpp:233:7:233:9 | s21 | | +| set.cpp:232:7:232:9 | ref arg s21 | set.cpp:238:1:238:1 | s21 | | +| set.cpp:232:29:232:33 | first | set.cpp:232:7:232:33 | call to iterator | | +| set.cpp:233:7:233:9 | s21 | set.cpp:233:7:233:9 | call to unordered_set | | +| set.cpp:234:7:234:9 | ref arg s22 | set.cpp:235:7:235:9 | s22 | | +| set.cpp:234:7:234:9 | ref arg s22 | set.cpp:236:7:236:9 | s22 | | +| set.cpp:234:7:234:9 | ref arg s22 | set.cpp:236:24:236:26 | s22 | | +| set.cpp:234:7:234:9 | ref arg s22 | set.cpp:237:7:237:9 | s22 | | +| set.cpp:234:7:234:9 | ref arg s22 | set.cpp:238:1:238:1 | s22 | | +| set.cpp:234:24:234:26 | ref arg s22 | set.cpp:234:7:234:9 | s22 | | +| set.cpp:234:24:234:26 | ref arg s22 | set.cpp:235:7:235:9 | s22 | | +| set.cpp:234:24:234:26 | ref arg s22 | set.cpp:236:7:236:9 | s22 | | +| set.cpp:234:24:234:26 | ref arg s22 | set.cpp:236:24:236:26 | s22 | | +| set.cpp:234:24:234:26 | ref arg s22 | set.cpp:237:7:237:9 | s22 | | +| set.cpp:234:24:234:26 | ref arg s22 | set.cpp:238:1:238:1 | s22 | | +| set.cpp:234:28:234:32 | call to begin | set.cpp:234:24:234:34 | call to iterator | TAINT | +| set.cpp:235:7:235:9 | s22 | set.cpp:235:7:235:9 | call to unordered_set | | +| set.cpp:236:7:236:9 | ref arg s22 | set.cpp:237:7:237:9 | s22 | | +| set.cpp:236:7:236:9 | ref arg s22 | set.cpp:238:1:238:1 | s22 | | +| set.cpp:236:24:236:26 | ref arg s22 | set.cpp:236:7:236:9 | s22 | | +| set.cpp:236:24:236:26 | ref arg s22 | set.cpp:237:7:237:9 | s22 | | +| set.cpp:236:24:236:26 | ref arg s22 | set.cpp:238:1:238:1 | s22 | | +| set.cpp:236:28:236:32 | call to begin | set.cpp:236:24:236:34 | call to iterator | TAINT | +| set.cpp:237:7:237:9 | s22 | set.cpp:237:7:237:9 | call to unordered_set | | | smart_pointer.cpp:11:30:11:50 | call to make_shared | smart_pointer.cpp:12:11:12:11 | p | | | smart_pointer.cpp:11:30:11:50 | call to make_shared | smart_pointer.cpp:13:10:13:10 | p | | | smart_pointer.cpp:11:52:11:57 | call to source | smart_pointer.cpp:11:30:11:50 | call to make_shared | TAINT | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/set.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/set.cpp new file mode 100644 index 00000000000..585ed398358 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/set.cpp @@ -0,0 +1,238 @@ + +#include "stl.h" + +using namespace std; + +char *source(); + +void sink(char *); +void sink(std::set); +void sink(std::set::iterator); +void sink(std::unordered_set); +void sink(std::unordered_set::iterator); + +void test_set() +{ + // insert, find + std::set s1, s2, s3, s4, s5, s6; + + sink(s1.insert("abc").first); + sink(s2.insert(source()).first); // tainted [NOT DETECTED] + sink(s3.insert(s3.begin(), "abc")); + sink(s4.insert(s4.begin(), source())); // tainted [NOT DETECTED] + s5.insert(s1.begin(), s1.end()); + s6.insert(s2.begin(), s2.end()); + sink(s1); + sink(s2); // tainted [NOT DETECTED] + sink(s3); + sink(s4); // tainted [NOT DETECTED] + sink(s5); + sink(s6); // tainted [NOT DETECTED] + sink(s1.find("abc")); + sink(s2.find("abc")); // tainted [NOT DETECTED] + sink(s3.find("abc")); + sink(s4.find("abc")); // tainted [NOT DETECTED] + sink(s5.find("abc")); + sink(s6.find("abc")); // tainted [NOT DETECTED] + + // copy constructors and assignment + std::set s7(s2); + std::set s8 = s2; + std::set s9(s2.begin(), s2.end()); + std::set s10; + s10 = s2; + sink(s7); // tainted [NOT DETECTED] + sink(s8); // tainted [NOT DETECTED] + sink(s9); // tainted [NOT DETECTED] + sink(s10); // tainted [NOT DETECTED] + sink(s7.find("abc")); // tainted [NOT DETECTED] + sink(s8.find("abc")); // tainted [NOT DETECTED] + sink(s9.find("abc")); // tainted [NOT DETECTED] + sink(s10.find("abc")); // tainted [NOT DETECTED] + + // iterators + std::set::iterator i1, i2; + for (i1 = s1.begin(); i1 != s1.end(); i1++) + { + sink(*i1); + } + for (i2 = s2.begin(); i2 != s2.end(); i2++) + { + sink(*i2); // tainted [NOT DETECTED] + } + + // ranges + std::set s11; + s11.insert("a"); + s11.insert(source()); + s11.insert("c"); + sink(s11.lower_bound("b")); // tainted [NOT DETECTED] + sink(s11.upper_bound("b")); // tainted [NOT DETECTED] + sink(s11.equal_range("b").first); // tainted [NOT DETECTED] + sink(s11.equal_range("b").second); // tainted [NOT DETECTED] + + // swap + std::set s12, s13, s14, s15; + s12.insert(source()); + s15.insert(source()); + sink(s12); // tainted [NOT DETECTED] + sink(s13); + sink(s14); + sink(s15); // tainted [NOT DETECTED] + s12.swap(s13); + s14.swap(s15); + sink(s12); + sink(s13); // tainted [NOT DETECTED] + sink(s14); // tainted [NOT DETECTED] + sink(s15); + + // merge + std::set s16, s17, s18, s19; + s16.insert(source()); + s17.insert("abc"); + s18.insert("def"); + s19.insert(source()); + sink(s16); // tainted [NOT DETECTED] + sink(s17); + sink(s18); + sink(s19); // tainted [NOT DETECTED] + s16.merge(s17); + s18.merge(s19); + sink(s16); // tainted [NOT DETECTED] + sink(s17); // tainted [NOT DETECTED] + sink(s18); // tainted [NOT DETECTED] + sink(s19); // tainted [NOT DETECTED] + + // erase, clear + std::set s20; + s20.insert(source()); + s20.insert(source()); + sink(s20); // tainted [NOT DETECTED] + sink(s20.erase(s20.begin())); // tainted [NOT DETECTED] + sink(s20); // tainted [NOT DETECTED] + s20.clear(); + sink(s20); + + // emplace, emplace_hint + std::set s21, s22; + sink(s21.emplace("abc").first); + sink(s21); + sink(s21.emplace(source()).first); // tainted [NOT DETECTED] + sink(s21); // tainted [NOT DETECTED] + sink(s22.emplace_hint(s22.begin(), "abc")); + sink(s22); + sink(s22.emplace_hint(s22.begin(), source())); // tainted [NOT DETECTED] + sink(s22); // tainted [NOT DETECTED] +} + +void test_unordered_set() +{ + // insert, find + std::unordered_set s1, s2, s3, s4, s5, s6; + + sink(s1.insert("abc").first); + sink(s2.insert(source()).first); // tainted [NOT DETECTED] + sink(s3.insert(s3.begin(), "abc")); + sink(s4.insert(s4.begin(), source())); // tainted [NOT DETECTED] + s5.insert(s1.begin(), s1.end()); + s6.insert(s2.begin(), s2.end()); + sink(s1); + sink(s2); // tainted [NOT DETECTED] + sink(s3); + sink(s4); // tainted [NOT DETECTED] + sink(s5); + sink(s6); // tainted [NOT DETECTED] + sink(s1.find("abc")); + sink(s2.find("abc")); // tainted [NOT DETECTED] + sink(s3.find("abc")); + sink(s4.find("abc")); // tainted [NOT DETECTED] + sink(s5.find("abc")); + sink(s6.find("abc")); // tainted [NOT DETECTED] + + // copy constructors and assignment + std::unordered_set s7(s2); + std::unordered_set s8 = s2; + std::unordered_set s9(s2.begin(), s2.end()); + std::unordered_set s10; + s10 = s2; + sink(s7); // tainted [NOT DETECTED] + sink(s8); // tainted [NOT DETECTED] + sink(s9); // tainted [NOT DETECTED] + sink(s10); // tainted [NOT DETECTED] + sink(s7.find("abc")); // tainted [NOT DETECTED] + sink(s8.find("abc")); // tainted [NOT DETECTED] + sink(s9.find("abc")); // tainted [NOT DETECTED] + sink(s10.find("abc")); // tainted [NOT DETECTED] + + // iterators + std::unordered_set::iterator i1, i2; + for (i1 = s1.begin(); i1 != s1.end(); i1++) + { + sink(*i1); + } + for (i2 = s2.begin(); i2 != s2.end(); i2++) + { + sink(*i2); // tainted [NOT DETECTED] + } + + // ranges + std::unordered_set s11; + s11.insert("a"); + s11.insert(source()); + s11.insert("c"); + sink(s11.equal_range("b").first); // tainted [NOT DETECTED] + sink(s11.equal_range("b").second); // tainted [NOT DETECTED] + + // swap + std::unordered_set s12, s13, s14, s15; + s12.insert(source()); + s15.insert(source()); + sink(s12); // tainted [NOT DETECTED] + sink(s13); + sink(s14); + sink(s15); // tainted [NOT DETECTED] + s12.swap(s13); + s14.swap(s15); + sink(s12); + sink(s13); // tainted [NOT DETECTED] + sink(s14); // tainted [NOT DETECTED] + sink(s15); + + // merge + std::unordered_set s16, s17, s18, s19; + s16.insert(source()); + s17.insert("abc"); + s18.insert("def"); + s19.insert(source()); + sink(s16); // tainted [NOT DETECTED] + sink(s17); + sink(s18); + sink(s19); // tainted [NOT DETECTED] + s16.merge(s17); + s18.merge(s19); + sink(s16); // tainted [NOT DETECTED] + sink(s17); // tainted [NOT DETECTED] + sink(s18); // tainted [NOT DETECTED] + sink(s19); // tainted [NOT DETECTED] + + // erase, clear + std::unordered_set s20; + s20.insert(source()); + s20.insert(source()); + sink(s20); // tainted [NOT DETECTED] + sink(s20.erase(s20.begin())); // tainted [NOT DETECTED] + sink(s20); // tainted [NOT DETECTED] + s20.clear(); + sink(s20); + + // emplace, emplace_hint + std::unordered_set s21, s22; + sink(s21.emplace("abc").first); + sink(s21); + sink(s21.emplace(source()).first); // tainted [NOT DETECTED] + sink(s21); // tainted [NOT DETECTED] + sink(s22.emplace_hint(s22.begin(), "abc")); + sink(s22); + sink(s22.emplace_hint(s22.begin(), source())); // tainted [NOT DETECTED] + sink(s22); // tainted [NOT DETECTED] +} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h index 4def0a84e5a..88b28a08241 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h @@ -474,3 +474,108 @@ namespace std { pair equal_range(const key_type& k) const; }; }; + +// --- set --- + +namespace std { + template, class Allocator = allocator> + class set { + public: + using key_type = Key; + using value_type = Key; + using size_type = size_t; + using allocator_type = Allocator; + using iterator = std::iterator; + using const_iterator = std::iterator; + + set() /*: set(Compare())*/ { } + set(const set& x); + set(set&& x); + template set(InputIterator first, InputIterator last/*, const Compare& comp = Compare(), const Allocator& = Allocator()*/); + ~set(); + + set& operator=(const set& x); + set& operator=(set&& x) noexcept/*(allocator_traits::is_always_equal::value && is_nothrow_move_assignable_v)*/; + + iterator begin() noexcept; + const_iterator begin() const noexcept; + iterator end() noexcept; + const_iterator end() const noexcept; + + template pair emplace(Args&&... args); + template iterator emplace_hint(const_iterator position, Args&&... args); + pair insert(const value_type& x); + pair insert(value_type&& x); + iterator insert(const_iterator position, const value_type& x); + iterator insert(const_iterator position, value_type&& x); + template void insert(InputIterator first, InputIterator last); + + iterator erase(iterator position); + iterator erase(const_iterator position); + iterator erase(const_iterator first, const_iterator last); + void swap(set&) noexcept/*(allocator_traits::is_always_equal::value && is_nothrow_swappable_v)*/; + void clear() noexcept; + + template void merge(set& source); + template void merge(set&& source); + + iterator find(const key_type& x); + const_iterator find(const key_type& x) const; + + iterator lower_bound(const key_type& x); + const_iterator lower_bound(const key_type& x) const; + iterator upper_bound(const key_type& x); + const_iterator upper_bound(const key_type& x) const; + pair equal_range(const key_type& x); + pair equal_range(const key_type& x) const; + }; + + template, class Pred = equal_to, class Allocator = allocator> + class unordered_set { + public: + using key_type = Key; + using value_type = Key; + using hasher = Hash; + using key_equal = Pred; + using allocator_type = Allocator; + using size_type = size_t; + using iterator = std::iterator; + using const_iterator = std::iterator; + + unordered_set(); + unordered_set(const unordered_set&); + unordered_set(unordered_set&&); + template unordered_set(InputIterator f, InputIterator l, size_type n = 0/*, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()*/); + ~unordered_set(); + + unordered_set& operator=(const unordered_set&); + unordered_set& operator=(unordered_set&&) noexcept/*(allocator_traits::is_always_equal::value && is_nothrow_move_assignable_v && is_nothrow_move_assignable_v)*/; + + iterator begin() noexcept; + const_iterator begin() const noexcept; + iterator end() noexcept; + const_iterator end() const noexcept; + + template pair emplace(Args&&... args); + template iterator emplace_hint(const_iterator position, Args&&... args); + pair insert(const value_type& obj); + pair insert(value_type&& obj); + iterator insert(const_iterator hint, const value_type& obj); + iterator insert(const_iterator hint, value_type&& obj); + template void insert(InputIterator first, InputIterator last); + + iterator erase(iterator position); + iterator erase(const_iterator position); + iterator erase(const_iterator first, const_iterator last); + void swap(unordered_set&) noexcept/*(allocator_traits::is_always_equal::value && is_nothrow_swappable_v && is_nothrow_swappable_v)*/; + void clear() noexcept; + + template void merge(unordered_set& source); + template void merge(unordered_set&& source); + + iterator find(const key_type& k); + const_iterator find(const key_type& k) const; + pair equal_range(const key_type& k); + pair equal_range(const key_type& k) const; + }; +} From 6520f9d0fb3981093a43b1d2d800358d3bcd2096 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 30 Sep 2020 17:21:13 +0100 Subject: [PATCH 143/411] C++: Add basic std::set models. --- cpp/ql/src/semmle/code/cpp/models/Models.qll | 1 + .../cpp/models/implementations/StdSet.qll | 84 ++++++++++++ .../dataflow/taint-tests/localTaint.expected | 128 ++++++++++++++++++ .../dataflow/taint-tests/set.cpp | 116 ++++++++-------- .../dataflow/taint-tests/taint.expected | 64 +++++++++ .../dataflow/taint-tests/test_diff.expected | 52 +++++++ .../dataflow/taint-tests/test_ir.expected | 20 +++ 7 files changed, 407 insertions(+), 58 deletions(-) create mode 100644 cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll diff --git a/cpp/ql/src/semmle/code/cpp/models/Models.qll b/cpp/ql/src/semmle/code/cpp/models/Models.qll index 7df1edc34ac..75e81fdc318 100644 --- a/cpp/ql/src/semmle/code/cpp/models/Models.qll +++ b/cpp/ql/src/semmle/code/cpp/models/Models.qll @@ -17,6 +17,7 @@ private import implementations.Strftime private import implementations.StdContainer private import implementations.StdPair private import implementations.StdMap +private import implementations.StdSet private import implementations.StdString private import implementations.Swap private import implementations.GetDelim diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll new file mode 100644 index 00000000000..9101745219a --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll @@ -0,0 +1,84 @@ +/** + * Provides models for C++ containers `std::set` and `std::unordered_set`. + */ + +import semmle.code.cpp.models.interfaces.Taint +import semmle.code.cpp.models.implementations.Iterator + +/** + * The standard set `insert` and `insert_or_assign` functions. + */ +class StdSetInsert extends TaintFunction { + StdSetInsert() { + this.hasQualifiedName("std", ["set", "unordered_set"], "insert") + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from last parameter to qualifier and return value + // (where the return value is a pair, this should really flow just to the first part of it) + input.isParameterDeref(getNumberOfParameters() - 1) and + ( + output.isQualifierObject() or + output.isReturnValue() + ) + } +} + +/** + * The standard set `begin` and `end` functions and their + * variants. + */ +class StdSetBeginEnd extends TaintFunction { + StdSetBeginEnd() { + this.hasQualifiedName("std", ["set", "unordered_set"], ["begin", "end", "cbegin", "cend"]) + or + this.hasQualifiedName("std", "set", ["rbegin", "crbegin", "rend", "crend"]) + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + input.isQualifierObject() and + output.isReturnValue() + } +} + +/** + * The standard set `swap` functions. + */ +class StdSetSwap extends TaintFunction { + StdSetSwap() { this.hasQualifiedName("std", ["set", "unordered_set"], "swap") } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // container1.swap(container2) + input.isQualifierObject() and + output.isParameterDeref(0) + or + input.isParameterDeref(0) and + output.isQualifierObject() + } +} + +/** + * The standard set `find` function. + */ +class StdSetFind extends TaintFunction { + StdSetFind() { this.hasQualifiedName("std", ["set", "unordered_set"], "find") } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + input.isQualifierObject() and + output.isReturnValue() + } +} + +/** + * The standard set `erase` function. + */ +class StdSetErase extends TaintFunction { + StdSetErase() { this.hasQualifiedName("std", ["set", "unordered_set"], "erase") } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from qualifier to iterator return value + getType().getUnderlyingType() instanceof Iterator and + input.isQualifierObject() and + output.isReturnValue() + } +} 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 59e062f1b7f..144fd743cab 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -1965,6 +1965,8 @@ | set.cpp:19:7:19:8 | ref arg s1 | set.cpp:55:12:55:13 | s1 | | | set.cpp:19:7:19:8 | ref arg s1 | set.cpp:55:30:55:31 | s1 | | | set.cpp:19:7:19:8 | ref arg s1 | set.cpp:126:1:126:1 | s1 | | +| set.cpp:19:17:19:21 | abc | set.cpp:19:7:19:8 | ref arg s1 | TAINT | +| set.cpp:19:17:19:21 | abc | set.cpp:19:10:19:15 | call to insert | TAINT | | set.cpp:19:24:19:28 | first | set.cpp:19:7:19:28 | call to iterator | | | set.cpp:20:7:20:8 | ref arg s2 | set.cpp:24:12:24:13 | s2 | | | set.cpp:20:7:20:8 | ref arg s2 | set.cpp:24:24:24:25 | s2 | | @@ -1978,6 +1980,8 @@ | set.cpp:20:7:20:8 | ref arg s2 | set.cpp:59:12:59:13 | s2 | | | set.cpp:20:7:20:8 | ref arg s2 | set.cpp:59:30:59:31 | s2 | | | set.cpp:20:7:20:8 | ref arg s2 | set.cpp:126:1:126:1 | s2 | | +| set.cpp:20:17:20:22 | call to source | set.cpp:20:7:20:8 | ref arg s2 | TAINT | +| set.cpp:20:17:20:22 | call to source | set.cpp:20:10:20:15 | call to insert | TAINT | | set.cpp:20:27:20:31 | first | set.cpp:20:7:20:31 | call to iterator | | | set.cpp:21:7:21:8 | ref arg s3 | set.cpp:27:7:27:8 | s3 | | | set.cpp:21:7:21:8 | ref arg s3 | set.cpp:33:7:33:8 | s3 | | @@ -1986,7 +1990,10 @@ | set.cpp:21:17:21:18 | ref arg s3 | set.cpp:27:7:27:8 | s3 | | | set.cpp:21:17:21:18 | ref arg s3 | set.cpp:33:7:33:8 | s3 | | | set.cpp:21:17:21:18 | ref arg s3 | set.cpp:126:1:126:1 | s3 | | +| set.cpp:21:17:21:18 | s3 | set.cpp:21:20:21:24 | call to begin | TAINT | | set.cpp:21:20:21:24 | call to begin | set.cpp:21:17:21:26 | call to iterator | TAINT | +| set.cpp:21:29:21:33 | abc | set.cpp:21:7:21:8 | ref arg s3 | TAINT | +| set.cpp:21:29:21:33 | abc | set.cpp:21:10:21:15 | call to insert | TAINT | | set.cpp:22:7:22:8 | ref arg s4 | set.cpp:28:7:28:8 | s4 | | | set.cpp:22:7:22:8 | ref arg s4 | set.cpp:34:7:34:8 | s4 | | | set.cpp:22:7:22:8 | ref arg s4 | set.cpp:126:1:126:1 | s4 | | @@ -1994,7 +2001,10 @@ | set.cpp:22:17:22:18 | ref arg s4 | set.cpp:28:7:28:8 | s4 | | | set.cpp:22:17:22:18 | ref arg s4 | set.cpp:34:7:34:8 | s4 | | | set.cpp:22:17:22:18 | ref arg s4 | set.cpp:126:1:126:1 | s4 | | +| set.cpp:22:17:22:18 | s4 | set.cpp:22:20:22:24 | call to begin | TAINT | | set.cpp:22:20:22:24 | call to begin | set.cpp:22:17:22:26 | call to iterator | TAINT | +| set.cpp:22:29:22:34 | call to source | set.cpp:22:7:22:8 | ref arg s4 | TAINT | +| set.cpp:22:29:22:34 | call to source | set.cpp:22:10:22:15 | call to insert | TAINT | | set.cpp:23:2:23:3 | ref arg s5 | set.cpp:29:7:29:8 | s5 | | | set.cpp:23:2:23:3 | ref arg s5 | set.cpp:35:7:35:8 | s5 | | | set.cpp:23:2:23:3 | ref arg s5 | set.cpp:126:1:126:1 | s5 | | @@ -2004,11 +2014,15 @@ | set.cpp:23:12:23:13 | ref arg s1 | set.cpp:55:12:55:13 | s1 | | | set.cpp:23:12:23:13 | ref arg s1 | set.cpp:55:30:55:31 | s1 | | | set.cpp:23:12:23:13 | ref arg s1 | set.cpp:126:1:126:1 | s1 | | +| set.cpp:23:12:23:13 | s1 | set.cpp:23:15:23:19 | call to begin | TAINT | | set.cpp:23:24:23:25 | ref arg s1 | set.cpp:25:7:25:8 | s1 | | | set.cpp:23:24:23:25 | ref arg s1 | set.cpp:31:7:31:8 | s1 | | | set.cpp:23:24:23:25 | ref arg s1 | set.cpp:55:12:55:13 | s1 | | | set.cpp:23:24:23:25 | ref arg s1 | set.cpp:55:30:55:31 | s1 | | | set.cpp:23:24:23:25 | ref arg s1 | set.cpp:126:1:126:1 | s1 | | +| set.cpp:23:24:23:25 | s1 | set.cpp:23:27:23:29 | call to end | TAINT | +| set.cpp:23:27:23:29 | call to end | set.cpp:23:2:23:3 | ref arg s5 | TAINT | +| set.cpp:23:27:23:29 | call to end | set.cpp:23:5:23:10 | call to insert | TAINT | | set.cpp:24:2:24:3 | ref arg s6 | set.cpp:30:7:30:8 | s6 | | | set.cpp:24:2:24:3 | ref arg s6 | set.cpp:36:7:36:8 | s6 | | | set.cpp:24:2:24:3 | ref arg s6 | set.cpp:126:1:126:1 | s6 | | @@ -2023,6 +2037,7 @@ | set.cpp:24:12:24:13 | ref arg s2 | set.cpp:59:12:59:13 | s2 | | | set.cpp:24:12:24:13 | ref arg s2 | set.cpp:59:30:59:31 | s2 | | | set.cpp:24:12:24:13 | ref arg s2 | set.cpp:126:1:126:1 | s2 | | +| set.cpp:24:12:24:13 | s2 | set.cpp:24:15:24:19 | call to begin | TAINT | | set.cpp:24:24:24:25 | ref arg s2 | set.cpp:26:7:26:8 | s2 | | | set.cpp:24:24:24:25 | ref arg s2 | set.cpp:32:7:32:8 | s2 | | | set.cpp:24:24:24:25 | ref arg s2 | set.cpp:39:22:39:23 | s2 | | @@ -2033,6 +2048,9 @@ | set.cpp:24:24:24:25 | ref arg s2 | set.cpp:59:12:59:13 | s2 | | | set.cpp:24:24:24:25 | ref arg s2 | set.cpp:59:30:59:31 | s2 | | | set.cpp:24:24:24:25 | ref arg s2 | set.cpp:126:1:126:1 | s2 | | +| set.cpp:24:24:24:25 | s2 | set.cpp:24:27:24:29 | call to end | TAINT | +| set.cpp:24:27:24:29 | call to end | set.cpp:24:2:24:3 | ref arg s6 | TAINT | +| set.cpp:24:27:24:29 | call to end | set.cpp:24:5:24:10 | call to insert | TAINT | | set.cpp:25:7:25:8 | s1 | set.cpp:25:7:25:8 | call to set | | | set.cpp:26:7:26:8 | s2 | set.cpp:26:7:26:8 | call to set | | | set.cpp:27:7:27:8 | s3 | set.cpp:27:7:27:8 | call to set | | @@ -2042,6 +2060,7 @@ | set.cpp:31:7:31:8 | ref arg s1 | set.cpp:55:12:55:13 | s1 | | | set.cpp:31:7:31:8 | ref arg s1 | set.cpp:55:30:55:31 | s1 | | | set.cpp:31:7:31:8 | ref arg s1 | set.cpp:126:1:126:1 | s1 | | +| set.cpp:31:7:31:8 | s1 | set.cpp:31:10:31:13 | call to find | TAINT | | set.cpp:32:7:32:8 | ref arg s2 | set.cpp:39:22:39:23 | s2 | | | set.cpp:32:7:32:8 | ref arg s2 | set.cpp:40:24:40:25 | s2 | | | set.cpp:32:7:32:8 | ref arg s2 | set.cpp:41:22:41:23 | s2 | | @@ -2050,10 +2069,15 @@ | set.cpp:32:7:32:8 | ref arg s2 | set.cpp:59:12:59:13 | s2 | | | set.cpp:32:7:32:8 | ref arg s2 | set.cpp:59:30:59:31 | s2 | | | set.cpp:32:7:32:8 | ref arg s2 | set.cpp:126:1:126:1 | s2 | | +| set.cpp:32:7:32:8 | s2 | set.cpp:32:10:32:13 | call to find | TAINT | | set.cpp:33:7:33:8 | ref arg s3 | set.cpp:126:1:126:1 | s3 | | +| set.cpp:33:7:33:8 | s3 | set.cpp:33:10:33:13 | call to find | TAINT | | set.cpp:34:7:34:8 | ref arg s4 | set.cpp:126:1:126:1 | s4 | | +| set.cpp:34:7:34:8 | s4 | set.cpp:34:10:34:13 | call to find | TAINT | | set.cpp:35:7:35:8 | ref arg s5 | set.cpp:126:1:126:1 | s5 | | +| set.cpp:35:7:35:8 | s5 | set.cpp:35:10:35:13 | call to find | TAINT | | set.cpp:36:7:36:8 | ref arg s6 | set.cpp:126:1:126:1 | s6 | | +| set.cpp:36:7:36:8 | s6 | set.cpp:36:10:36:13 | call to find | TAINT | | set.cpp:39:22:39:23 | s2 | set.cpp:39:22:39:24 | call to set | | | set.cpp:39:22:39:24 | call to set | set.cpp:44:7:44:8 | s7 | | | set.cpp:39:22:39:24 | call to set | set.cpp:48:7:48:8 | s7 | | @@ -2067,6 +2091,7 @@ | set.cpp:41:22:41:23 | ref arg s2 | set.cpp:59:12:59:13 | s2 | | | set.cpp:41:22:41:23 | ref arg s2 | set.cpp:59:30:59:31 | s2 | | | set.cpp:41:22:41:23 | ref arg s2 | set.cpp:126:1:126:1 | s2 | | +| set.cpp:41:22:41:23 | s2 | set.cpp:41:25:41:29 | call to begin | TAINT | | set.cpp:41:22:41:42 | call to set | set.cpp:46:7:46:8 | s9 | | | set.cpp:41:22:41:42 | call to set | set.cpp:50:7:50:8 | s9 | | | set.cpp:41:22:41:42 | call to set | set.cpp:126:1:126:1 | s9 | | @@ -2074,6 +2099,7 @@ | set.cpp:41:34:41:35 | ref arg s2 | set.cpp:59:12:59:13 | s2 | | | set.cpp:41:34:41:35 | ref arg s2 | set.cpp:59:30:59:31 | s2 | | | set.cpp:41:34:41:35 | ref arg s2 | set.cpp:126:1:126:1 | s2 | | +| set.cpp:41:34:41:35 | s2 | set.cpp:41:37:41:39 | call to end | TAINT | | set.cpp:42:19:42:21 | call to set | set.cpp:43:2:43:4 | s10 | | | set.cpp:42:19:42:21 | call to set | set.cpp:47:7:47:9 | s10 | | | set.cpp:42:19:42:21 | call to set | set.cpp:51:7:51:9 | s10 | | @@ -2088,17 +2114,23 @@ | set.cpp:46:7:46:8 | s9 | set.cpp:46:7:46:8 | call to set | | | set.cpp:47:7:47:9 | s10 | set.cpp:47:7:47:9 | call to set | | | set.cpp:48:7:48:8 | ref arg s7 | set.cpp:126:1:126:1 | s7 | | +| set.cpp:48:7:48:8 | s7 | set.cpp:48:10:48:13 | call to find | TAINT | | set.cpp:49:7:49:8 | ref arg s8 | set.cpp:126:1:126:1 | s8 | | +| set.cpp:49:7:49:8 | s8 | set.cpp:49:10:49:13 | call to find | TAINT | | set.cpp:50:7:50:8 | ref arg s9 | set.cpp:126:1:126:1 | s9 | | +| set.cpp:50:7:50:8 | s9 | set.cpp:50:10:50:13 | call to find | TAINT | | set.cpp:51:7:51:9 | ref arg s10 | set.cpp:126:1:126:1 | s10 | | +| set.cpp:51:7:51:9 | s10 | set.cpp:51:11:51:14 | call to find | TAINT | | set.cpp:55:12:55:13 | ref arg s1 | set.cpp:55:30:55:31 | s1 | | | set.cpp:55:12:55:13 | ref arg s1 | set.cpp:126:1:126:1 | s1 | | +| set.cpp:55:12:55:13 | s1 | set.cpp:55:15:55:19 | call to begin | TAINT | | set.cpp:55:15:55:19 | call to begin | set.cpp:55:7:55:21 | ... = ... | | | set.cpp:55:15:55:19 | call to begin | set.cpp:55:24:55:25 | i1 | | | set.cpp:55:15:55:19 | call to begin | set.cpp:55:40:55:41 | i1 | | | set.cpp:55:15:55:19 | call to begin | set.cpp:57:9:57:10 | i1 | | | set.cpp:55:30:55:31 | ref arg s1 | set.cpp:55:30:55:31 | s1 | | | set.cpp:55:30:55:31 | ref arg s1 | set.cpp:126:1:126:1 | s1 | | +| set.cpp:55:30:55:31 | s1 | set.cpp:55:33:55:35 | call to end | TAINT | | set.cpp:55:40:55:41 | i1 | set.cpp:55:42:55:42 | call to operator++ | | | set.cpp:55:40:55:41 | ref arg i1 | set.cpp:55:24:55:25 | i1 | | | set.cpp:55:40:55:41 | ref arg i1 | set.cpp:55:40:55:41 | i1 | | @@ -2106,12 +2138,14 @@ | set.cpp:57:9:57:10 | i1 | set.cpp:57:8:57:8 | call to operator* | TAINT | | set.cpp:59:12:59:13 | ref arg s2 | set.cpp:59:30:59:31 | s2 | | | set.cpp:59:12:59:13 | ref arg s2 | set.cpp:126:1:126:1 | s2 | | +| set.cpp:59:12:59:13 | s2 | set.cpp:59:15:59:19 | call to begin | TAINT | | set.cpp:59:15:59:19 | call to begin | set.cpp:59:7:59:21 | ... = ... | | | set.cpp:59:15:59:19 | call to begin | set.cpp:59:24:59:25 | i2 | | | set.cpp:59:15:59:19 | call to begin | set.cpp:59:40:59:41 | i2 | | | set.cpp:59:15:59:19 | call to begin | set.cpp:61:9:61:10 | i2 | | | set.cpp:59:30:59:31 | ref arg s2 | set.cpp:59:30:59:31 | s2 | | | set.cpp:59:30:59:31 | ref arg s2 | set.cpp:126:1:126:1 | s2 | | +| set.cpp:59:30:59:31 | s2 | set.cpp:59:33:59:35 | call to end | TAINT | | set.cpp:59:40:59:41 | i2 | set.cpp:59:42:59:42 | call to operator++ | | | set.cpp:59:40:59:41 | ref arg i2 | set.cpp:59:24:59:25 | i2 | | | set.cpp:59:40:59:41 | ref arg i2 | set.cpp:59:40:59:41 | i2 | | @@ -2132,17 +2166,23 @@ | set.cpp:66:2:66:4 | ref arg s11 | set.cpp:71:7:71:9 | s11 | | | set.cpp:66:2:66:4 | ref arg s11 | set.cpp:72:7:72:9 | s11 | | | set.cpp:66:2:66:4 | ref arg s11 | set.cpp:126:1:126:1 | s11 | | +| set.cpp:66:13:66:15 | a | set.cpp:66:2:66:4 | ref arg s11 | TAINT | +| set.cpp:66:13:66:15 | a | set.cpp:66:6:66:11 | call to insert | TAINT | | set.cpp:67:2:67:4 | ref arg s11 | set.cpp:68:2:68:4 | s11 | | | set.cpp:67:2:67:4 | ref arg s11 | set.cpp:69:7:69:9 | s11 | | | set.cpp:67:2:67:4 | ref arg s11 | set.cpp:70:7:70:9 | s11 | | | set.cpp:67:2:67:4 | ref arg s11 | set.cpp:71:7:71:9 | s11 | | | set.cpp:67:2:67:4 | ref arg s11 | set.cpp:72:7:72:9 | s11 | | | set.cpp:67:2:67:4 | ref arg s11 | set.cpp:126:1:126:1 | s11 | | +| set.cpp:67:13:67:18 | call to source | set.cpp:67:2:67:4 | ref arg s11 | TAINT | +| set.cpp:67:13:67:18 | call to source | set.cpp:67:6:67:11 | call to insert | TAINT | | set.cpp:68:2:68:4 | ref arg s11 | set.cpp:69:7:69:9 | s11 | | | set.cpp:68:2:68:4 | ref arg s11 | set.cpp:70:7:70:9 | s11 | | | set.cpp:68:2:68:4 | ref arg s11 | set.cpp:71:7:71:9 | s11 | | | set.cpp:68:2:68:4 | ref arg s11 | set.cpp:72:7:72:9 | s11 | | | set.cpp:68:2:68:4 | ref arg s11 | set.cpp:126:1:126:1 | s11 | | +| set.cpp:68:13:68:15 | c | set.cpp:68:2:68:4 | ref arg s11 | TAINT | +| set.cpp:68:13:68:15 | c | set.cpp:68:6:68:11 | call to insert | TAINT | | set.cpp:69:7:69:9 | ref arg s11 | set.cpp:70:7:70:9 | s11 | | | set.cpp:69:7:69:9 | ref arg s11 | set.cpp:71:7:71:9 | s11 | | | set.cpp:69:7:69:9 | ref arg s11 | set.cpp:72:7:72:9 | s11 | | @@ -2177,22 +2217,30 @@ | set.cpp:76:2:76:4 | ref arg s12 | set.cpp:82:2:82:4 | s12 | | | set.cpp:76:2:76:4 | ref arg s12 | set.cpp:84:7:84:9 | s12 | | | set.cpp:76:2:76:4 | ref arg s12 | set.cpp:126:1:126:1 | s12 | | +| set.cpp:76:13:76:18 | call to source | set.cpp:76:2:76:4 | ref arg s12 | TAINT | +| set.cpp:76:13:76:18 | call to source | set.cpp:76:6:76:11 | call to insert | TAINT | | set.cpp:77:2:77:4 | ref arg s15 | set.cpp:81:7:81:9 | s15 | | | set.cpp:77:2:77:4 | ref arg s15 | set.cpp:83:11:83:13 | s15 | | | set.cpp:77:2:77:4 | ref arg s15 | set.cpp:87:7:87:9 | s15 | | | set.cpp:77:2:77:4 | ref arg s15 | set.cpp:126:1:126:1 | s15 | | +| set.cpp:77:13:77:18 | call to source | set.cpp:77:2:77:4 | ref arg s15 | TAINT | +| set.cpp:77:13:77:18 | call to source | set.cpp:77:6:77:11 | call to insert | TAINT | | set.cpp:78:7:78:9 | s12 | set.cpp:78:7:78:9 | call to set | | | set.cpp:79:7:79:9 | s13 | set.cpp:79:7:79:9 | call to set | | | set.cpp:80:7:80:9 | s14 | set.cpp:80:7:80:9 | call to set | | | set.cpp:81:7:81:9 | s15 | set.cpp:81:7:81:9 | call to set | | | set.cpp:82:2:82:4 | ref arg s12 | set.cpp:84:7:84:9 | s12 | | | set.cpp:82:2:82:4 | ref arg s12 | set.cpp:126:1:126:1 | s12 | | +| set.cpp:82:2:82:4 | s12 | set.cpp:82:11:82:13 | ref arg s13 | TAINT | | set.cpp:82:11:82:13 | ref arg s13 | set.cpp:85:7:85:9 | s13 | | | set.cpp:82:11:82:13 | ref arg s13 | set.cpp:126:1:126:1 | s13 | | +| set.cpp:82:11:82:13 | s13 | set.cpp:82:2:82:4 | ref arg s12 | TAINT | | set.cpp:83:2:83:4 | ref arg s14 | set.cpp:86:7:86:9 | s14 | | | set.cpp:83:2:83:4 | ref arg s14 | set.cpp:126:1:126:1 | s14 | | +| set.cpp:83:2:83:4 | s14 | set.cpp:83:11:83:13 | ref arg s15 | TAINT | | set.cpp:83:11:83:13 | ref arg s15 | set.cpp:87:7:87:9 | s15 | | | set.cpp:83:11:83:13 | ref arg s15 | set.cpp:126:1:126:1 | s15 | | +| set.cpp:83:11:83:13 | s15 | set.cpp:83:2:83:4 | ref arg s14 | TAINT | | set.cpp:84:7:84:9 | s12 | set.cpp:84:7:84:9 | call to set | | | set.cpp:85:7:85:9 | s13 | set.cpp:85:7:85:9 | call to set | | | set.cpp:86:7:86:9 | s14 | set.cpp:86:7:86:9 | call to set | | @@ -2221,18 +2269,26 @@ | set.cpp:91:2:91:4 | ref arg s16 | set.cpp:99:2:99:4 | s16 | | | set.cpp:91:2:91:4 | ref arg s16 | set.cpp:101:7:101:9 | s16 | | | set.cpp:91:2:91:4 | ref arg s16 | set.cpp:126:1:126:1 | s16 | | +| set.cpp:91:13:91:18 | call to source | set.cpp:91:2:91:4 | ref arg s16 | TAINT | +| set.cpp:91:13:91:18 | call to source | set.cpp:91:6:91:11 | call to insert | TAINT | | set.cpp:92:2:92:4 | ref arg s17 | set.cpp:96:7:96:9 | s17 | | | set.cpp:92:2:92:4 | ref arg s17 | set.cpp:99:12:99:14 | s17 | | | set.cpp:92:2:92:4 | ref arg s17 | set.cpp:102:7:102:9 | s17 | | | set.cpp:92:2:92:4 | ref arg s17 | set.cpp:126:1:126:1 | s17 | | +| set.cpp:92:13:92:17 | abc | set.cpp:92:2:92:4 | ref arg s17 | TAINT | +| set.cpp:92:13:92:17 | abc | set.cpp:92:6:92:11 | call to insert | TAINT | | set.cpp:93:2:93:4 | ref arg s18 | set.cpp:97:7:97:9 | s18 | | | set.cpp:93:2:93:4 | ref arg s18 | set.cpp:100:2:100:4 | s18 | | | set.cpp:93:2:93:4 | ref arg s18 | set.cpp:103:7:103:9 | s18 | | | set.cpp:93:2:93:4 | ref arg s18 | set.cpp:126:1:126:1 | s18 | | +| set.cpp:93:13:93:17 | def | set.cpp:93:2:93:4 | ref arg s18 | TAINT | +| set.cpp:93:13:93:17 | def | set.cpp:93:6:93:11 | call to insert | TAINT | | set.cpp:94:2:94:4 | ref arg s19 | set.cpp:98:7:98:9 | s19 | | | set.cpp:94:2:94:4 | ref arg s19 | set.cpp:100:12:100:14 | s19 | | | set.cpp:94:2:94:4 | ref arg s19 | set.cpp:104:7:104:9 | s19 | | | set.cpp:94:2:94:4 | ref arg s19 | set.cpp:126:1:126:1 | s19 | | +| set.cpp:94:13:94:18 | call to source | set.cpp:94:2:94:4 | ref arg s19 | TAINT | +| set.cpp:94:13:94:18 | call to source | set.cpp:94:6:94:11 | call to insert | TAINT | | set.cpp:95:7:95:9 | s16 | set.cpp:95:7:95:9 | call to set | | | set.cpp:96:7:96:9 | s17 | set.cpp:96:7:96:9 | call to set | | | set.cpp:97:7:97:9 | s18 | set.cpp:97:7:97:9 | call to set | | @@ -2266,6 +2322,8 @@ | set.cpp:108:2:108:4 | ref arg s20 | set.cpp:113:2:113:4 | s20 | | | set.cpp:108:2:108:4 | ref arg s20 | set.cpp:114:7:114:9 | s20 | | | set.cpp:108:2:108:4 | ref arg s20 | set.cpp:126:1:126:1 | s20 | | +| set.cpp:108:13:108:18 | call to source | set.cpp:108:2:108:4 | ref arg s20 | TAINT | +| set.cpp:108:13:108:18 | call to source | set.cpp:108:6:108:11 | call to insert | TAINT | | set.cpp:109:2:109:4 | ref arg s20 | set.cpp:110:7:110:9 | s20 | | | set.cpp:109:2:109:4 | ref arg s20 | set.cpp:111:7:111:9 | s20 | | | set.cpp:109:2:109:4 | ref arg s20 | set.cpp:111:17:111:19 | s20 | | @@ -2273,16 +2331,20 @@ | set.cpp:109:2:109:4 | ref arg s20 | set.cpp:113:2:113:4 | s20 | | | set.cpp:109:2:109:4 | ref arg s20 | set.cpp:114:7:114:9 | s20 | | | set.cpp:109:2:109:4 | ref arg s20 | set.cpp:126:1:126:1 | s20 | | +| set.cpp:109:13:109:18 | call to source | set.cpp:109:2:109:4 | ref arg s20 | TAINT | +| set.cpp:109:13:109:18 | call to source | set.cpp:109:6:109:11 | call to insert | TAINT | | set.cpp:110:7:110:9 | s20 | set.cpp:110:7:110:9 | call to set | | | set.cpp:111:7:111:9 | ref arg s20 | set.cpp:112:7:112:9 | s20 | | | set.cpp:111:7:111:9 | ref arg s20 | set.cpp:113:2:113:4 | s20 | | | set.cpp:111:7:111:9 | ref arg s20 | set.cpp:114:7:114:9 | s20 | | | set.cpp:111:7:111:9 | ref arg s20 | set.cpp:126:1:126:1 | s20 | | +| set.cpp:111:7:111:9 | s20 | set.cpp:111:11:111:15 | call to erase | TAINT | | set.cpp:111:17:111:19 | ref arg s20 | set.cpp:111:7:111:9 | s20 | | | set.cpp:111:17:111:19 | ref arg s20 | set.cpp:112:7:112:9 | s20 | | | set.cpp:111:17:111:19 | ref arg s20 | set.cpp:113:2:113:4 | s20 | | | set.cpp:111:17:111:19 | ref arg s20 | set.cpp:114:7:114:9 | s20 | | | set.cpp:111:17:111:19 | ref arg s20 | set.cpp:126:1:126:1 | s20 | | +| set.cpp:111:17:111:19 | s20 | set.cpp:111:21:111:25 | call to begin | TAINT | | set.cpp:112:7:112:9 | s20 | set.cpp:112:7:112:9 | call to set | | | set.cpp:113:2:113:4 | ref arg s20 | set.cpp:114:7:114:9 | s20 | | | set.cpp:113:2:113:4 | ref arg s20 | set.cpp:126:1:126:1 | s20 | | @@ -2320,6 +2382,7 @@ | set.cpp:122:24:122:26 | ref arg s22 | set.cpp:124:24:124:26 | s22 | | | set.cpp:122:24:122:26 | ref arg s22 | set.cpp:125:7:125:9 | s22 | | | set.cpp:122:24:122:26 | ref arg s22 | set.cpp:126:1:126:1 | s22 | | +| set.cpp:122:24:122:26 | s22 | set.cpp:122:28:122:32 | call to begin | TAINT | | set.cpp:122:28:122:32 | call to begin | set.cpp:122:24:122:34 | call to iterator | TAINT | | set.cpp:123:7:123:9 | s22 | set.cpp:123:7:123:9 | call to set | | | set.cpp:124:7:124:9 | ref arg s22 | set.cpp:125:7:125:9 | s22 | | @@ -2327,6 +2390,7 @@ | set.cpp:124:24:124:26 | ref arg s22 | set.cpp:124:7:124:9 | s22 | | | set.cpp:124:24:124:26 | ref arg s22 | set.cpp:125:7:125:9 | s22 | | | set.cpp:124:24:124:26 | ref arg s22 | set.cpp:126:1:126:1 | s22 | | +| set.cpp:124:24:124:26 | s22 | set.cpp:124:28:124:32 | call to begin | TAINT | | set.cpp:124:28:124:32 | call to begin | set.cpp:124:24:124:34 | call to iterator | TAINT | | set.cpp:125:7:125:9 | s22 | set.cpp:125:7:125:9 | call to set | | | set.cpp:131:29:131:30 | call to unordered_set | set.cpp:133:7:133:8 | s1 | | @@ -2375,6 +2439,8 @@ | set.cpp:133:7:133:8 | ref arg s1 | set.cpp:169:12:169:13 | s1 | | | set.cpp:133:7:133:8 | ref arg s1 | set.cpp:169:30:169:31 | s1 | | | set.cpp:133:7:133:8 | ref arg s1 | set.cpp:238:1:238:1 | s1 | | +| set.cpp:133:17:133:21 | abc | set.cpp:133:7:133:8 | ref arg s1 | TAINT | +| set.cpp:133:17:133:21 | abc | set.cpp:133:10:133:15 | call to insert | TAINT | | set.cpp:133:24:133:28 | first | set.cpp:133:7:133:28 | call to iterator | | | set.cpp:134:7:134:8 | ref arg s2 | set.cpp:138:12:138:13 | s2 | | | set.cpp:134:7:134:8 | ref arg s2 | set.cpp:138:24:138:25 | s2 | | @@ -2388,6 +2454,8 @@ | set.cpp:134:7:134:8 | ref arg s2 | set.cpp:173:12:173:13 | s2 | | | set.cpp:134:7:134:8 | ref arg s2 | set.cpp:173:30:173:31 | s2 | | | set.cpp:134:7:134:8 | ref arg s2 | set.cpp:238:1:238:1 | s2 | | +| set.cpp:134:17:134:22 | call to source | set.cpp:134:7:134:8 | ref arg s2 | TAINT | +| set.cpp:134:17:134:22 | call to source | set.cpp:134:10:134:15 | call to insert | TAINT | | set.cpp:134:27:134:31 | first | set.cpp:134:7:134:31 | call to iterator | | | set.cpp:135:7:135:8 | ref arg s3 | set.cpp:141:7:141:8 | s3 | | | set.cpp:135:7:135:8 | ref arg s3 | set.cpp:147:7:147:8 | s3 | | @@ -2396,7 +2464,10 @@ | set.cpp:135:17:135:18 | ref arg s3 | set.cpp:141:7:141:8 | s3 | | | set.cpp:135:17:135:18 | ref arg s3 | set.cpp:147:7:147:8 | s3 | | | set.cpp:135:17:135:18 | ref arg s3 | set.cpp:238:1:238:1 | s3 | | +| set.cpp:135:17:135:18 | s3 | set.cpp:135:20:135:24 | call to begin | TAINT | | set.cpp:135:20:135:24 | call to begin | set.cpp:135:17:135:26 | call to iterator | TAINT | +| set.cpp:135:29:135:33 | abc | set.cpp:135:7:135:8 | ref arg s3 | TAINT | +| set.cpp:135:29:135:33 | abc | set.cpp:135:10:135:15 | call to insert | TAINT | | set.cpp:136:7:136:8 | ref arg s4 | set.cpp:142:7:142:8 | s4 | | | set.cpp:136:7:136:8 | ref arg s4 | set.cpp:148:7:148:8 | s4 | | | set.cpp:136:7:136:8 | ref arg s4 | set.cpp:238:1:238:1 | s4 | | @@ -2404,7 +2475,10 @@ | set.cpp:136:17:136:18 | ref arg s4 | set.cpp:142:7:142:8 | s4 | | | set.cpp:136:17:136:18 | ref arg s4 | set.cpp:148:7:148:8 | s4 | | | set.cpp:136:17:136:18 | ref arg s4 | set.cpp:238:1:238:1 | s4 | | +| set.cpp:136:17:136:18 | s4 | set.cpp:136:20:136:24 | call to begin | TAINT | | set.cpp:136:20:136:24 | call to begin | set.cpp:136:17:136:26 | call to iterator | TAINT | +| set.cpp:136:29:136:34 | call to source | set.cpp:136:7:136:8 | ref arg s4 | TAINT | +| set.cpp:136:29:136:34 | call to source | set.cpp:136:10:136:15 | call to insert | TAINT | | set.cpp:137:2:137:3 | ref arg s5 | set.cpp:143:7:143:8 | s5 | | | set.cpp:137:2:137:3 | ref arg s5 | set.cpp:149:7:149:8 | s5 | | | set.cpp:137:2:137:3 | ref arg s5 | set.cpp:238:1:238:1 | s5 | | @@ -2414,11 +2488,15 @@ | set.cpp:137:12:137:13 | ref arg s1 | set.cpp:169:12:169:13 | s1 | | | set.cpp:137:12:137:13 | ref arg s1 | set.cpp:169:30:169:31 | s1 | | | set.cpp:137:12:137:13 | ref arg s1 | set.cpp:238:1:238:1 | s1 | | +| set.cpp:137:12:137:13 | s1 | set.cpp:137:15:137:19 | call to begin | TAINT | | set.cpp:137:24:137:25 | ref arg s1 | set.cpp:139:7:139:8 | s1 | | | set.cpp:137:24:137:25 | ref arg s1 | set.cpp:145:7:145:8 | s1 | | | set.cpp:137:24:137:25 | ref arg s1 | set.cpp:169:12:169:13 | s1 | | | set.cpp:137:24:137:25 | ref arg s1 | set.cpp:169:30:169:31 | s1 | | | set.cpp:137:24:137:25 | ref arg s1 | set.cpp:238:1:238:1 | s1 | | +| set.cpp:137:24:137:25 | s1 | set.cpp:137:27:137:29 | call to end | TAINT | +| set.cpp:137:27:137:29 | call to end | set.cpp:137:2:137:3 | ref arg s5 | TAINT | +| set.cpp:137:27:137:29 | call to end | set.cpp:137:5:137:10 | call to insert | TAINT | | set.cpp:138:2:138:3 | ref arg s6 | set.cpp:144:7:144:8 | s6 | | | set.cpp:138:2:138:3 | ref arg s6 | set.cpp:150:7:150:8 | s6 | | | set.cpp:138:2:138:3 | ref arg s6 | set.cpp:238:1:238:1 | s6 | | @@ -2433,6 +2511,7 @@ | set.cpp:138:12:138:13 | ref arg s2 | set.cpp:173:12:173:13 | s2 | | | set.cpp:138:12:138:13 | ref arg s2 | set.cpp:173:30:173:31 | s2 | | | set.cpp:138:12:138:13 | ref arg s2 | set.cpp:238:1:238:1 | s2 | | +| set.cpp:138:12:138:13 | s2 | set.cpp:138:15:138:19 | call to begin | TAINT | | set.cpp:138:24:138:25 | ref arg s2 | set.cpp:140:7:140:8 | s2 | | | set.cpp:138:24:138:25 | ref arg s2 | set.cpp:146:7:146:8 | s2 | | | set.cpp:138:24:138:25 | ref arg s2 | set.cpp:153:32:153:33 | s2 | | @@ -2443,6 +2522,9 @@ | set.cpp:138:24:138:25 | ref arg s2 | set.cpp:173:12:173:13 | s2 | | | set.cpp:138:24:138:25 | ref arg s2 | set.cpp:173:30:173:31 | s2 | | | set.cpp:138:24:138:25 | ref arg s2 | set.cpp:238:1:238:1 | s2 | | +| set.cpp:138:24:138:25 | s2 | set.cpp:138:27:138:29 | call to end | TAINT | +| set.cpp:138:27:138:29 | call to end | set.cpp:138:2:138:3 | ref arg s6 | TAINT | +| set.cpp:138:27:138:29 | call to end | set.cpp:138:5:138:10 | call to insert | TAINT | | set.cpp:139:7:139:8 | s1 | set.cpp:139:7:139:8 | call to unordered_set | | | set.cpp:140:7:140:8 | s2 | set.cpp:140:7:140:8 | call to unordered_set | | | set.cpp:141:7:141:8 | s3 | set.cpp:141:7:141:8 | call to unordered_set | | @@ -2452,6 +2534,7 @@ | set.cpp:145:7:145:8 | ref arg s1 | set.cpp:169:12:169:13 | s1 | | | set.cpp:145:7:145:8 | ref arg s1 | set.cpp:169:30:169:31 | s1 | | | set.cpp:145:7:145:8 | ref arg s1 | set.cpp:238:1:238:1 | s1 | | +| set.cpp:145:7:145:8 | s1 | set.cpp:145:10:145:13 | call to find | TAINT | | set.cpp:146:7:146:8 | ref arg s2 | set.cpp:153:32:153:33 | s2 | | | set.cpp:146:7:146:8 | ref arg s2 | set.cpp:154:34:154:35 | s2 | | | set.cpp:146:7:146:8 | ref arg s2 | set.cpp:155:32:155:33 | s2 | | @@ -2460,10 +2543,15 @@ | set.cpp:146:7:146:8 | ref arg s2 | set.cpp:173:12:173:13 | s2 | | | set.cpp:146:7:146:8 | ref arg s2 | set.cpp:173:30:173:31 | s2 | | | set.cpp:146:7:146:8 | ref arg s2 | set.cpp:238:1:238:1 | s2 | | +| set.cpp:146:7:146:8 | s2 | set.cpp:146:10:146:13 | call to find | TAINT | | set.cpp:147:7:147:8 | ref arg s3 | set.cpp:238:1:238:1 | s3 | | +| set.cpp:147:7:147:8 | s3 | set.cpp:147:10:147:13 | call to find | TAINT | | set.cpp:148:7:148:8 | ref arg s4 | set.cpp:238:1:238:1 | s4 | | +| set.cpp:148:7:148:8 | s4 | set.cpp:148:10:148:13 | call to find | TAINT | | set.cpp:149:7:149:8 | ref arg s5 | set.cpp:238:1:238:1 | s5 | | +| set.cpp:149:7:149:8 | s5 | set.cpp:149:10:149:13 | call to find | TAINT | | set.cpp:150:7:150:8 | ref arg s6 | set.cpp:238:1:238:1 | s6 | | +| set.cpp:150:7:150:8 | s6 | set.cpp:150:10:150:13 | call to find | TAINT | | set.cpp:153:32:153:33 | s2 | set.cpp:153:32:153:34 | call to unordered_set | | | set.cpp:153:32:153:34 | call to unordered_set | set.cpp:158:7:158:8 | s7 | | | set.cpp:153:32:153:34 | call to unordered_set | set.cpp:162:7:162:8 | s7 | | @@ -2477,6 +2565,7 @@ | set.cpp:155:32:155:33 | ref arg s2 | set.cpp:173:12:173:13 | s2 | | | set.cpp:155:32:155:33 | ref arg s2 | set.cpp:173:30:173:31 | s2 | | | set.cpp:155:32:155:33 | ref arg s2 | set.cpp:238:1:238:1 | s2 | | +| set.cpp:155:32:155:33 | s2 | set.cpp:155:35:155:39 | call to begin | TAINT | | set.cpp:155:32:155:52 | call to unordered_set | set.cpp:160:7:160:8 | s9 | | | set.cpp:155:32:155:52 | call to unordered_set | set.cpp:164:7:164:8 | s9 | | | set.cpp:155:32:155:52 | call to unordered_set | set.cpp:238:1:238:1 | s9 | | @@ -2484,6 +2573,7 @@ | set.cpp:155:44:155:45 | ref arg s2 | set.cpp:173:12:173:13 | s2 | | | set.cpp:155:44:155:45 | ref arg s2 | set.cpp:173:30:173:31 | s2 | | | set.cpp:155:44:155:45 | ref arg s2 | set.cpp:238:1:238:1 | s2 | | +| set.cpp:155:44:155:45 | s2 | set.cpp:155:47:155:49 | call to end | TAINT | | set.cpp:156:29:156:31 | call to unordered_set | set.cpp:157:2:157:4 | s10 | | | set.cpp:156:29:156:31 | call to unordered_set | set.cpp:161:7:161:9 | s10 | | | set.cpp:156:29:156:31 | call to unordered_set | set.cpp:165:7:165:9 | s10 | | @@ -2498,17 +2588,23 @@ | set.cpp:160:7:160:8 | s9 | set.cpp:160:7:160:8 | call to unordered_set | | | set.cpp:161:7:161:9 | s10 | set.cpp:161:7:161:9 | call to unordered_set | | | set.cpp:162:7:162:8 | ref arg s7 | set.cpp:238:1:238:1 | s7 | | +| set.cpp:162:7:162:8 | s7 | set.cpp:162:10:162:13 | call to find | TAINT | | set.cpp:163:7:163:8 | ref arg s8 | set.cpp:238:1:238:1 | s8 | | +| set.cpp:163:7:163:8 | s8 | set.cpp:163:10:163:13 | call to find | TAINT | | set.cpp:164:7:164:8 | ref arg s9 | set.cpp:238:1:238:1 | s9 | | +| set.cpp:164:7:164:8 | s9 | set.cpp:164:10:164:13 | call to find | TAINT | | set.cpp:165:7:165:9 | ref arg s10 | set.cpp:238:1:238:1 | s10 | | +| set.cpp:165:7:165:9 | s10 | set.cpp:165:11:165:14 | call to find | TAINT | | set.cpp:169:12:169:13 | ref arg s1 | set.cpp:169:30:169:31 | s1 | | | set.cpp:169:12:169:13 | ref arg s1 | set.cpp:238:1:238:1 | s1 | | +| set.cpp:169:12:169:13 | s1 | set.cpp:169:15:169:19 | call to begin | TAINT | | set.cpp:169:15:169:19 | call to begin | set.cpp:169:7:169:21 | ... = ... | | | set.cpp:169:15:169:19 | call to begin | set.cpp:169:24:169:25 | i1 | | | set.cpp:169:15:169:19 | call to begin | set.cpp:169:40:169:41 | i1 | | | set.cpp:169:15:169:19 | call to begin | set.cpp:171:9:171:10 | i1 | | | set.cpp:169:30:169:31 | ref arg s1 | set.cpp:169:30:169:31 | s1 | | | set.cpp:169:30:169:31 | ref arg s1 | set.cpp:238:1:238:1 | s1 | | +| set.cpp:169:30:169:31 | s1 | set.cpp:169:33:169:35 | call to end | TAINT | | set.cpp:169:40:169:41 | i1 | set.cpp:169:42:169:42 | call to operator++ | | | set.cpp:169:40:169:41 | ref arg i1 | set.cpp:169:24:169:25 | i1 | | | set.cpp:169:40:169:41 | ref arg i1 | set.cpp:169:40:169:41 | i1 | | @@ -2516,12 +2612,14 @@ | set.cpp:171:9:171:10 | i1 | set.cpp:171:8:171:8 | call to operator* | TAINT | | set.cpp:173:12:173:13 | ref arg s2 | set.cpp:173:30:173:31 | s2 | | | set.cpp:173:12:173:13 | ref arg s2 | set.cpp:238:1:238:1 | s2 | | +| set.cpp:173:12:173:13 | s2 | set.cpp:173:15:173:19 | call to begin | TAINT | | set.cpp:173:15:173:19 | call to begin | set.cpp:173:7:173:21 | ... = ... | | | set.cpp:173:15:173:19 | call to begin | set.cpp:173:24:173:25 | i2 | | | set.cpp:173:15:173:19 | call to begin | set.cpp:173:40:173:41 | i2 | | | set.cpp:173:15:173:19 | call to begin | set.cpp:175:9:175:10 | i2 | | | set.cpp:173:30:173:31 | ref arg s2 | set.cpp:173:30:173:31 | s2 | | | set.cpp:173:30:173:31 | ref arg s2 | set.cpp:238:1:238:1 | s2 | | +| set.cpp:173:30:173:31 | s2 | set.cpp:173:33:173:35 | call to end | TAINT | | set.cpp:173:40:173:41 | i2 | set.cpp:173:42:173:42 | call to operator++ | | | set.cpp:173:40:173:41 | ref arg i2 | set.cpp:173:24:173:25 | i2 | | | set.cpp:173:40:173:41 | ref arg i2 | set.cpp:173:40:173:41 | i2 | | @@ -2538,13 +2636,19 @@ | set.cpp:180:2:180:4 | ref arg s11 | set.cpp:183:7:183:9 | s11 | | | set.cpp:180:2:180:4 | ref arg s11 | set.cpp:184:7:184:9 | s11 | | | set.cpp:180:2:180:4 | ref arg s11 | set.cpp:238:1:238:1 | s11 | | +| set.cpp:180:13:180:15 | a | set.cpp:180:2:180:4 | ref arg s11 | TAINT | +| set.cpp:180:13:180:15 | a | set.cpp:180:6:180:11 | call to insert | TAINT | | set.cpp:181:2:181:4 | ref arg s11 | set.cpp:182:2:182:4 | s11 | | | set.cpp:181:2:181:4 | ref arg s11 | set.cpp:183:7:183:9 | s11 | | | set.cpp:181:2:181:4 | ref arg s11 | set.cpp:184:7:184:9 | s11 | | | set.cpp:181:2:181:4 | ref arg s11 | set.cpp:238:1:238:1 | s11 | | +| set.cpp:181:13:181:18 | call to source | set.cpp:181:2:181:4 | ref arg s11 | TAINT | +| set.cpp:181:13:181:18 | call to source | set.cpp:181:6:181:11 | call to insert | TAINT | | set.cpp:182:2:182:4 | ref arg s11 | set.cpp:183:7:183:9 | s11 | | | set.cpp:182:2:182:4 | ref arg s11 | set.cpp:184:7:184:9 | s11 | | | set.cpp:182:2:182:4 | ref arg s11 | set.cpp:238:1:238:1 | s11 | | +| set.cpp:182:13:182:15 | c | set.cpp:182:2:182:4 | ref arg s11 | TAINT | +| set.cpp:182:13:182:15 | c | set.cpp:182:6:182:11 | call to insert | TAINT | | set.cpp:183:7:183:9 | ref arg s11 | set.cpp:184:7:184:9 | s11 | | | set.cpp:183:7:183:9 | ref arg s11 | set.cpp:238:1:238:1 | s11 | | | set.cpp:183:28:183:32 | first | set.cpp:183:7:183:32 | call to iterator | | @@ -2572,22 +2676,30 @@ | set.cpp:188:2:188:4 | ref arg s12 | set.cpp:194:2:194:4 | s12 | | | set.cpp:188:2:188:4 | ref arg s12 | set.cpp:196:7:196:9 | s12 | | | set.cpp:188:2:188:4 | ref arg s12 | set.cpp:238:1:238:1 | s12 | | +| set.cpp:188:13:188:18 | call to source | set.cpp:188:2:188:4 | ref arg s12 | TAINT | +| set.cpp:188:13:188:18 | call to source | set.cpp:188:6:188:11 | call to insert | TAINT | | set.cpp:189:2:189:4 | ref arg s15 | set.cpp:193:7:193:9 | s15 | | | set.cpp:189:2:189:4 | ref arg s15 | set.cpp:195:11:195:13 | s15 | | | set.cpp:189:2:189:4 | ref arg s15 | set.cpp:199:7:199:9 | s15 | | | set.cpp:189:2:189:4 | ref arg s15 | set.cpp:238:1:238:1 | s15 | | +| set.cpp:189:13:189:18 | call to source | set.cpp:189:2:189:4 | ref arg s15 | TAINT | +| set.cpp:189:13:189:18 | call to source | set.cpp:189:6:189:11 | call to insert | TAINT | | set.cpp:190:7:190:9 | s12 | set.cpp:190:7:190:9 | call to unordered_set | | | set.cpp:191:7:191:9 | s13 | set.cpp:191:7:191:9 | call to unordered_set | | | set.cpp:192:7:192:9 | s14 | set.cpp:192:7:192:9 | call to unordered_set | | | set.cpp:193:7:193:9 | s15 | set.cpp:193:7:193:9 | call to unordered_set | | | set.cpp:194:2:194:4 | ref arg s12 | set.cpp:196:7:196:9 | s12 | | | set.cpp:194:2:194:4 | ref arg s12 | set.cpp:238:1:238:1 | s12 | | +| set.cpp:194:2:194:4 | s12 | set.cpp:194:11:194:13 | ref arg s13 | TAINT | | set.cpp:194:11:194:13 | ref arg s13 | set.cpp:197:7:197:9 | s13 | | | set.cpp:194:11:194:13 | ref arg s13 | set.cpp:238:1:238:1 | s13 | | +| set.cpp:194:11:194:13 | s13 | set.cpp:194:2:194:4 | ref arg s12 | TAINT | | set.cpp:195:2:195:4 | ref arg s14 | set.cpp:198:7:198:9 | s14 | | | set.cpp:195:2:195:4 | ref arg s14 | set.cpp:238:1:238:1 | s14 | | +| set.cpp:195:2:195:4 | s14 | set.cpp:195:11:195:13 | ref arg s15 | TAINT | | set.cpp:195:11:195:13 | ref arg s15 | set.cpp:199:7:199:9 | s15 | | | set.cpp:195:11:195:13 | ref arg s15 | set.cpp:238:1:238:1 | s15 | | +| set.cpp:195:11:195:13 | s15 | set.cpp:195:2:195:4 | ref arg s14 | TAINT | | set.cpp:196:7:196:9 | s12 | set.cpp:196:7:196:9 | call to unordered_set | | | set.cpp:197:7:197:9 | s13 | set.cpp:197:7:197:9 | call to unordered_set | | | set.cpp:198:7:198:9 | s14 | set.cpp:198:7:198:9 | call to unordered_set | | @@ -2616,18 +2728,26 @@ | set.cpp:203:2:203:4 | ref arg s16 | set.cpp:211:2:211:4 | s16 | | | set.cpp:203:2:203:4 | ref arg s16 | set.cpp:213:7:213:9 | s16 | | | set.cpp:203:2:203:4 | ref arg s16 | set.cpp:238:1:238:1 | s16 | | +| set.cpp:203:13:203:18 | call to source | set.cpp:203:2:203:4 | ref arg s16 | TAINT | +| set.cpp:203:13:203:18 | call to source | set.cpp:203:6:203:11 | call to insert | TAINT | | set.cpp:204:2:204:4 | ref arg s17 | set.cpp:208:7:208:9 | s17 | | | set.cpp:204:2:204:4 | ref arg s17 | set.cpp:211:12:211:14 | s17 | | | set.cpp:204:2:204:4 | ref arg s17 | set.cpp:214:7:214:9 | s17 | | | set.cpp:204:2:204:4 | ref arg s17 | set.cpp:238:1:238:1 | s17 | | +| set.cpp:204:13:204:17 | abc | set.cpp:204:2:204:4 | ref arg s17 | TAINT | +| set.cpp:204:13:204:17 | abc | set.cpp:204:6:204:11 | call to insert | TAINT | | set.cpp:205:2:205:4 | ref arg s18 | set.cpp:209:7:209:9 | s18 | | | set.cpp:205:2:205:4 | ref arg s18 | set.cpp:212:2:212:4 | s18 | | | set.cpp:205:2:205:4 | ref arg s18 | set.cpp:215:7:215:9 | s18 | | | set.cpp:205:2:205:4 | ref arg s18 | set.cpp:238:1:238:1 | s18 | | +| set.cpp:205:13:205:17 | def | set.cpp:205:2:205:4 | ref arg s18 | TAINT | +| set.cpp:205:13:205:17 | def | set.cpp:205:6:205:11 | call to insert | TAINT | | set.cpp:206:2:206:4 | ref arg s19 | set.cpp:210:7:210:9 | s19 | | | set.cpp:206:2:206:4 | ref arg s19 | set.cpp:212:12:212:14 | s19 | | | set.cpp:206:2:206:4 | ref arg s19 | set.cpp:216:7:216:9 | s19 | | | set.cpp:206:2:206:4 | ref arg s19 | set.cpp:238:1:238:1 | s19 | | +| set.cpp:206:13:206:18 | call to source | set.cpp:206:2:206:4 | ref arg s19 | TAINT | +| set.cpp:206:13:206:18 | call to source | set.cpp:206:6:206:11 | call to insert | TAINT | | set.cpp:207:7:207:9 | s16 | set.cpp:207:7:207:9 | call to unordered_set | | | set.cpp:208:7:208:9 | s17 | set.cpp:208:7:208:9 | call to unordered_set | | | set.cpp:209:7:209:9 | s18 | set.cpp:209:7:209:9 | call to unordered_set | | @@ -2661,6 +2781,8 @@ | set.cpp:220:2:220:4 | ref arg s20 | set.cpp:225:2:225:4 | s20 | | | set.cpp:220:2:220:4 | ref arg s20 | set.cpp:226:7:226:9 | s20 | | | set.cpp:220:2:220:4 | ref arg s20 | set.cpp:238:1:238:1 | s20 | | +| set.cpp:220:13:220:18 | call to source | set.cpp:220:2:220:4 | ref arg s20 | TAINT | +| set.cpp:220:13:220:18 | call to source | set.cpp:220:6:220:11 | call to insert | TAINT | | set.cpp:221:2:221:4 | ref arg s20 | set.cpp:222:7:222:9 | s20 | | | set.cpp:221:2:221:4 | ref arg s20 | set.cpp:223:7:223:9 | s20 | | | set.cpp:221:2:221:4 | ref arg s20 | set.cpp:223:17:223:19 | s20 | | @@ -2668,16 +2790,20 @@ | set.cpp:221:2:221:4 | ref arg s20 | set.cpp:225:2:225:4 | s20 | | | set.cpp:221:2:221:4 | ref arg s20 | set.cpp:226:7:226:9 | s20 | | | set.cpp:221:2:221:4 | ref arg s20 | set.cpp:238:1:238:1 | s20 | | +| set.cpp:221:13:221:18 | call to source | set.cpp:221:2:221:4 | ref arg s20 | TAINT | +| set.cpp:221:13:221:18 | call to source | set.cpp:221:6:221:11 | call to insert | TAINT | | set.cpp:222:7:222:9 | s20 | set.cpp:222:7:222:9 | call to unordered_set | | | set.cpp:223:7:223:9 | ref arg s20 | set.cpp:224:7:224:9 | s20 | | | set.cpp:223:7:223:9 | ref arg s20 | set.cpp:225:2:225:4 | s20 | | | set.cpp:223:7:223:9 | ref arg s20 | set.cpp:226:7:226:9 | s20 | | | set.cpp:223:7:223:9 | ref arg s20 | set.cpp:238:1:238:1 | s20 | | +| set.cpp:223:7:223:9 | s20 | set.cpp:223:11:223:15 | call to erase | TAINT | | set.cpp:223:17:223:19 | ref arg s20 | set.cpp:223:7:223:9 | s20 | | | set.cpp:223:17:223:19 | ref arg s20 | set.cpp:224:7:224:9 | s20 | | | set.cpp:223:17:223:19 | ref arg s20 | set.cpp:225:2:225:4 | s20 | | | set.cpp:223:17:223:19 | ref arg s20 | set.cpp:226:7:226:9 | s20 | | | set.cpp:223:17:223:19 | ref arg s20 | set.cpp:238:1:238:1 | s20 | | +| set.cpp:223:17:223:19 | s20 | set.cpp:223:21:223:25 | call to begin | TAINT | | set.cpp:224:7:224:9 | s20 | set.cpp:224:7:224:9 | call to unordered_set | | | set.cpp:225:2:225:4 | ref arg s20 | set.cpp:226:7:226:9 | s20 | | | set.cpp:225:2:225:4 | ref arg s20 | set.cpp:238:1:238:1 | s20 | | @@ -2715,6 +2841,7 @@ | set.cpp:234:24:234:26 | ref arg s22 | set.cpp:236:24:236:26 | s22 | | | set.cpp:234:24:234:26 | ref arg s22 | set.cpp:237:7:237:9 | s22 | | | set.cpp:234:24:234:26 | ref arg s22 | set.cpp:238:1:238:1 | s22 | | +| set.cpp:234:24:234:26 | s22 | set.cpp:234:28:234:32 | call to begin | TAINT | | set.cpp:234:28:234:32 | call to begin | set.cpp:234:24:234:34 | call to iterator | TAINT | | set.cpp:235:7:235:9 | s22 | set.cpp:235:7:235:9 | call to unordered_set | | | set.cpp:236:7:236:9 | ref arg s22 | set.cpp:237:7:237:9 | s22 | | @@ -2722,6 +2849,7 @@ | set.cpp:236:24:236:26 | ref arg s22 | set.cpp:236:7:236:9 | s22 | | | set.cpp:236:24:236:26 | ref arg s22 | set.cpp:237:7:237:9 | s22 | | | set.cpp:236:24:236:26 | ref arg s22 | set.cpp:238:1:238:1 | s22 | | +| set.cpp:236:24:236:26 | s22 | set.cpp:236:28:236:32 | call to begin | TAINT | | set.cpp:236:28:236:32 | call to begin | set.cpp:236:24:236:34 | call to iterator | TAINT | | set.cpp:237:7:237:9 | s22 | set.cpp:237:7:237:9 | call to unordered_set | | | smart_pointer.cpp:11:30:11:50 | call to make_shared | smart_pointer.cpp:12:11:12:11 | p | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/set.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/set.cpp index 585ed398358..f2c07e48d60 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/set.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/set.cpp @@ -17,23 +17,23 @@ void test_set() std::set s1, s2, s3, s4, s5, s6; sink(s1.insert("abc").first); - sink(s2.insert(source()).first); // tainted [NOT DETECTED] + sink(s2.insert(source()).first); // tainted sink(s3.insert(s3.begin(), "abc")); - sink(s4.insert(s4.begin(), source())); // tainted [NOT DETECTED] + sink(s4.insert(s4.begin(), source())); // tainted s5.insert(s1.begin(), s1.end()); s6.insert(s2.begin(), s2.end()); sink(s1); - sink(s2); // tainted [NOT DETECTED] + sink(s2); // tainted sink(s3); - sink(s4); // tainted [NOT DETECTED] + sink(s4); // tainted sink(s5); - sink(s6); // tainted [NOT DETECTED] + sink(s6); // tainted sink(s1.find("abc")); - sink(s2.find("abc")); // tainted [NOT DETECTED] + sink(s2.find("abc")); // tainted sink(s3.find("abc")); - sink(s4.find("abc")); // tainted [NOT DETECTED] + sink(s4.find("abc")); // tainted sink(s5.find("abc")); - sink(s6.find("abc")); // tainted [NOT DETECTED] + sink(s6.find("abc")); // tainted // copy constructors and assignment std::set s7(s2); @@ -41,14 +41,14 @@ void test_set() std::set s9(s2.begin(), s2.end()); std::set s10; s10 = s2; - sink(s7); // tainted [NOT DETECTED] - sink(s8); // tainted [NOT DETECTED] + sink(s7); // tainted + sink(s8); // tainted sink(s9); // tainted [NOT DETECTED] - sink(s10); // tainted [NOT DETECTED] - sink(s7.find("abc")); // tainted [NOT DETECTED] - sink(s8.find("abc")); // tainted [NOT DETECTED] + sink(s10); // tainted + sink(s7.find("abc")); // tainted + sink(s8.find("abc")); // tainted sink(s9.find("abc")); // tainted [NOT DETECTED] - sink(s10.find("abc")); // tainted [NOT DETECTED] + sink(s10.find("abc")); // tainted // iterators std::set::iterator i1, i2; @@ -58,7 +58,7 @@ void test_set() } for (i2 = s2.begin(); i2 != s2.end(); i2++) { - sink(*i2); // tainted [NOT DETECTED] + sink(*i2); // tainted } // ranges @@ -75,16 +75,16 @@ void test_set() std::set s12, s13, s14, s15; s12.insert(source()); s15.insert(source()); - sink(s12); // tainted [NOT DETECTED] + sink(s12); // tainted sink(s13); sink(s14); - sink(s15); // tainted [NOT DETECTED] + sink(s15); // tainted s12.swap(s13); s14.swap(s15); - sink(s12); - sink(s13); // tainted [NOT DETECTED] - sink(s14); // tainted [NOT DETECTED] - sink(s15); + sink(s12); // [FALSE POSITIVE] + sink(s13); // tainted + sink(s14); // tainted + sink(s15); // [FALSE POSITIVE] // merge std::set s16, s17, s18, s19; @@ -92,26 +92,26 @@ void test_set() s17.insert("abc"); s18.insert("def"); s19.insert(source()); - sink(s16); // tainted [NOT DETECTED] + sink(s16); // tainted sink(s17); sink(s18); - sink(s19); // tainted [NOT DETECTED] + sink(s19); // tainted s16.merge(s17); s18.merge(s19); - sink(s16); // tainted [NOT DETECTED] + sink(s16); // tainted sink(s17); // tainted [NOT DETECTED] sink(s18); // tainted [NOT DETECTED] - sink(s19); // tainted [NOT DETECTED] + sink(s19); // tainted // erase, clear std::set s20; s20.insert(source()); s20.insert(source()); - sink(s20); // tainted [NOT DETECTED] - sink(s20.erase(s20.begin())); // tainted [NOT DETECTED] - sink(s20); // tainted [NOT DETECTED] + sink(s20); // tainted + sink(s20.erase(s20.begin())); // tainted + sink(s20); // tainted s20.clear(); - sink(s20); + sink(s20); // [FALSE POSITIVE] // emplace, emplace_hint std::set s21, s22; @@ -131,23 +131,23 @@ void test_unordered_set() std::unordered_set s1, s2, s3, s4, s5, s6; sink(s1.insert("abc").first); - sink(s2.insert(source()).first); // tainted [NOT DETECTED] + sink(s2.insert(source()).first); // tainted sink(s3.insert(s3.begin(), "abc")); - sink(s4.insert(s4.begin(), source())); // tainted [NOT DETECTED] + sink(s4.insert(s4.begin(), source())); // tainted s5.insert(s1.begin(), s1.end()); s6.insert(s2.begin(), s2.end()); sink(s1); - sink(s2); // tainted [NOT DETECTED] + sink(s2); // tainted sink(s3); - sink(s4); // tainted [NOT DETECTED] + sink(s4); // tainted sink(s5); - sink(s6); // tainted [NOT DETECTED] + sink(s6); // tainted sink(s1.find("abc")); - sink(s2.find("abc")); // tainted [NOT DETECTED] + sink(s2.find("abc")); // tainted sink(s3.find("abc")); - sink(s4.find("abc")); // tainted [NOT DETECTED] + sink(s4.find("abc")); // tainted sink(s5.find("abc")); - sink(s6.find("abc")); // tainted [NOT DETECTED] + sink(s6.find("abc")); // tainted // copy constructors and assignment std::unordered_set s7(s2); @@ -155,14 +155,14 @@ void test_unordered_set() std::unordered_set s9(s2.begin(), s2.end()); std::unordered_set s10; s10 = s2; - sink(s7); // tainted [NOT DETECTED] - sink(s8); // tainted [NOT DETECTED] + sink(s7); // tainted + sink(s8); // tainted sink(s9); // tainted [NOT DETECTED] - sink(s10); // tainted [NOT DETECTED] - sink(s7.find("abc")); // tainted [NOT DETECTED] - sink(s8.find("abc")); // tainted [NOT DETECTED] + sink(s10); // tainted + sink(s7.find("abc")); // tainted + sink(s8.find("abc")); // tainted sink(s9.find("abc")); // tainted [NOT DETECTED] - sink(s10.find("abc")); // tainted [NOT DETECTED] + sink(s10.find("abc")); // tainted // iterators std::unordered_set::iterator i1, i2; @@ -172,7 +172,7 @@ void test_unordered_set() } for (i2 = s2.begin(); i2 != s2.end(); i2++) { - sink(*i2); // tainted [NOT DETECTED] + sink(*i2); // tainted } // ranges @@ -187,16 +187,16 @@ void test_unordered_set() std::unordered_set s12, s13, s14, s15; s12.insert(source()); s15.insert(source()); - sink(s12); // tainted [NOT DETECTED] + sink(s12); // tainted sink(s13); sink(s14); - sink(s15); // tainted [NOT DETECTED] + sink(s15); // tainted s12.swap(s13); s14.swap(s15); - sink(s12); - sink(s13); // tainted [NOT DETECTED] - sink(s14); // tainted [NOT DETECTED] - sink(s15); + sink(s12); // [FALSE POSITIVE] + sink(s13); // tainted + sink(s14); // tainted + sink(s15); // [FALSE POSITIVE] // merge std::unordered_set s16, s17, s18, s19; @@ -204,26 +204,26 @@ void test_unordered_set() s17.insert("abc"); s18.insert("def"); s19.insert(source()); - sink(s16); // tainted [NOT DETECTED] + sink(s16); // tainted sink(s17); sink(s18); - sink(s19); // tainted [NOT DETECTED] + sink(s19); // tainted s16.merge(s17); s18.merge(s19); - sink(s16); // tainted [NOT DETECTED] + sink(s16); // tainted sink(s17); // tainted [NOT DETECTED] sink(s18); // tainted [NOT DETECTED] - sink(s19); // tainted [NOT DETECTED] + sink(s19); // tainted // erase, clear std::unordered_set s20; s20.insert(source()); s20.insert(source()); - sink(s20); // tainted [NOT DETECTED] - sink(s20.erase(s20.begin())); // tainted [NOT DETECTED] - sink(s20); // tainted [NOT DETECTED] + sink(s20); // tainted + sink(s20.erase(s20.begin())); // tainted + sink(s20); // tainted s20.clear(); - sink(s20); + sink(s20); // [FALSE POSITIVE] // emplace, emplace_hint std::unordered_set s21, s22; 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 2293eb4edf4..37e89c28fcf 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -189,6 +189,70 @@ | movableclass.cpp:55:8:55:9 | s2 | movableclass.cpp:52:23:52:28 | call to source | | movableclass.cpp:64:8:64:9 | s2 | movableclass.cpp:23:55:23:60 | call to source | | movableclass.cpp:65:11:65:11 | call to operator= | movableclass.cpp:65:13:65:18 | call to source | +| set.cpp:22:10:22:15 | call to insert | set.cpp:22:29:22:34 | call to source | +| set.cpp:26:7:26:8 | call to set | set.cpp:20:17:20:22 | call to source | +| set.cpp:28:7:28:8 | call to set | set.cpp:22:29:22:34 | call to source | +| set.cpp:30:7:30:8 | call to set | set.cpp:20:17:20:22 | call to source | +| set.cpp:32:10:32:13 | call to find | set.cpp:20:17:20:22 | call to source | +| set.cpp:34:10:34:13 | call to find | set.cpp:22:29:22:34 | call to source | +| set.cpp:36:10:36:13 | call to find | set.cpp:20:17:20:22 | call to source | +| set.cpp:44:7:44:8 | call to set | set.cpp:20:17:20:22 | call to source | +| set.cpp:45:7:45:8 | call to set | set.cpp:20:17:20:22 | call to source | +| set.cpp:47:7:47:9 | call to set | set.cpp:20:17:20:22 | call to source | +| set.cpp:48:10:48:13 | call to find | set.cpp:20:17:20:22 | call to source | +| set.cpp:49:10:49:13 | call to find | set.cpp:20:17:20:22 | call to source | +| set.cpp:51:11:51:14 | call to find | set.cpp:20:17:20:22 | call to source | +| set.cpp:61:8:61:8 | call to operator* | set.cpp:20:17:20:22 | call to source | +| set.cpp:78:7:78:9 | call to set | set.cpp:76:13:76:18 | call to source | +| set.cpp:81:7:81:9 | call to set | set.cpp:77:13:77:18 | call to source | +| set.cpp:84:7:84:9 | call to set | set.cpp:76:13:76:18 | call to source | +| set.cpp:85:7:85:9 | call to set | set.cpp:76:13:76:18 | call to source | +| set.cpp:86:7:86:9 | call to set | set.cpp:77:13:77:18 | call to source | +| set.cpp:87:7:87:9 | call to set | set.cpp:77:13:77:18 | call to source | +| set.cpp:95:7:95:9 | call to set | set.cpp:91:13:91:18 | call to source | +| set.cpp:98:7:98:9 | call to set | set.cpp:94:13:94:18 | call to source | +| set.cpp:101:7:101:9 | call to set | set.cpp:91:13:91:18 | call to source | +| set.cpp:104:7:104:9 | call to set | set.cpp:94:13:94:18 | call to source | +| set.cpp:110:7:110:9 | call to set | set.cpp:108:13:108:18 | call to source | +| set.cpp:110:7:110:9 | call to set | set.cpp:109:13:109:18 | call to source | +| set.cpp:111:11:111:15 | call to erase | set.cpp:108:13:108:18 | call to source | +| set.cpp:111:11:111:15 | call to erase | set.cpp:109:13:109:18 | call to source | +| set.cpp:112:7:112:9 | call to set | set.cpp:108:13:108:18 | call to source | +| set.cpp:112:7:112:9 | call to set | set.cpp:109:13:109:18 | call to source | +| set.cpp:114:7:114:9 | call to set | set.cpp:108:13:108:18 | call to source | +| set.cpp:114:7:114:9 | call to set | set.cpp:109:13:109:18 | call to source | +| set.cpp:136:10:136:15 | call to insert | set.cpp:136:29:136:34 | call to source | +| set.cpp:140:7:140:8 | call to unordered_set | set.cpp:134:17:134:22 | call to source | +| set.cpp:142:7:142:8 | call to unordered_set | set.cpp:136:29:136:34 | call to source | +| set.cpp:144:7:144:8 | call to unordered_set | set.cpp:134:17:134:22 | call to source | +| set.cpp:146:10:146:13 | call to find | set.cpp:134:17:134:22 | call to source | +| set.cpp:148:10:148:13 | call to find | set.cpp:136:29:136:34 | call to source | +| set.cpp:150:10:150:13 | call to find | set.cpp:134:17:134:22 | call to source | +| set.cpp:158:7:158:8 | call to unordered_set | set.cpp:134:17:134:22 | call to source | +| set.cpp:159:7:159:8 | call to unordered_set | set.cpp:134:17:134:22 | call to source | +| set.cpp:161:7:161:9 | call to unordered_set | set.cpp:134:17:134:22 | call to source | +| set.cpp:162:10:162:13 | call to find | set.cpp:134:17:134:22 | call to source | +| set.cpp:163:10:163:13 | call to find | set.cpp:134:17:134:22 | call to source | +| set.cpp:165:11:165:14 | call to find | set.cpp:134:17:134:22 | call to source | +| set.cpp:175:8:175:8 | call to operator* | set.cpp:134:17:134:22 | call to source | +| set.cpp:190:7:190:9 | call to unordered_set | set.cpp:188:13:188:18 | call to source | +| set.cpp:193:7:193:9 | call to unordered_set | set.cpp:189:13:189:18 | call to source | +| set.cpp:196:7:196:9 | call to unordered_set | set.cpp:188:13:188:18 | call to source | +| set.cpp:197:7:197:9 | call to unordered_set | set.cpp:188:13:188:18 | call to source | +| set.cpp:198:7:198:9 | call to unordered_set | set.cpp:189:13:189:18 | call to source | +| set.cpp:199:7:199:9 | call to unordered_set | set.cpp:189:13:189:18 | call to source | +| set.cpp:207:7:207:9 | call to unordered_set | set.cpp:203:13:203:18 | call to source | +| set.cpp:210:7:210:9 | call to unordered_set | set.cpp:206:13:206:18 | call to source | +| set.cpp:213:7:213:9 | call to unordered_set | set.cpp:203:13:203:18 | call to source | +| set.cpp:216:7:216:9 | call to unordered_set | set.cpp:206:13:206:18 | call to source | +| set.cpp:222:7:222:9 | call to unordered_set | set.cpp:220:13:220:18 | call to source | +| set.cpp:222:7:222:9 | call to unordered_set | set.cpp:221:13:221:18 | call to source | +| set.cpp:223:11:223:15 | call to erase | set.cpp:220:13:220:18 | call to source | +| set.cpp:223:11:223:15 | call to erase | set.cpp:221:13:221:18 | call to source | +| set.cpp:224:7:224:9 | call to unordered_set | set.cpp:220:13:220:18 | call to source | +| set.cpp:224:7:224:9 | call to unordered_set | set.cpp:221:13:221:18 | call to source | +| set.cpp:226:7:226:9 | call to unordered_set | set.cpp:220:13:220:18 | call to source | +| set.cpp:226:7:226:9 | call to unordered_set | set.cpp:221:13:221:18 | call to source | | smart_pointer.cpp:12:10:12:10 | call to operator* | smart_pointer.cpp:11:52:11:57 | call to source | | smart_pointer.cpp:13:10:13:10 | p | smart_pointer.cpp:11:52:11:57 | call to source | | smart_pointer.cpp:24:10:24:10 | call to operator* | smart_pointer.cpp:23:52:23:57 | 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 bc8a843de51..d3d13dd9b55 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 @@ -148,6 +148,58 @@ | map.cpp:375:7:375:9 | map.cpp:370:49:370:54 | AST only | | movableclass.cpp:65:11:65:11 | movableclass.cpp:65:13:65:18 | AST only | | movableclass.cpp:65:11:65:21 | movableclass.cpp:65:13:65:18 | IR only | +| set.cpp:20:7:20:31 | set.cpp:20:17:20:22 | IR only | +| set.cpp:26:7:26:8 | set.cpp:20:17:20:22 | AST only | +| set.cpp:28:7:28:8 | set.cpp:22:29:22:34 | AST only | +| set.cpp:30:7:30:8 | set.cpp:20:17:20:22 | AST only | +| set.cpp:44:7:44:8 | set.cpp:20:17:20:22 | AST only | +| set.cpp:45:7:45:8 | set.cpp:20:17:20:22 | AST only | +| set.cpp:47:7:47:9 | set.cpp:20:17:20:22 | AST only | +| set.cpp:48:10:48:13 | set.cpp:20:17:20:22 | AST only | +| set.cpp:49:10:49:13 | set.cpp:20:17:20:22 | AST only | +| set.cpp:61:8:61:11 | set.cpp:20:17:20:22 | IR only | +| set.cpp:78:7:78:9 | set.cpp:76:13:76:18 | AST only | +| set.cpp:81:7:81:9 | set.cpp:77:13:77:18 | AST only | +| set.cpp:84:7:84:9 | set.cpp:76:13:76:18 | AST only | +| set.cpp:85:7:85:9 | set.cpp:76:13:76:18 | AST only | +| set.cpp:86:7:86:9 | set.cpp:77:13:77:18 | AST only | +| set.cpp:87:7:87:9 | set.cpp:77:13:77:18 | AST only | +| set.cpp:95:7:95:9 | set.cpp:91:13:91:18 | AST only | +| set.cpp:98:7:98:9 | set.cpp:94:13:94:18 | AST only | +| set.cpp:101:7:101:9 | set.cpp:91:13:91:18 | AST only | +| set.cpp:104:7:104:9 | set.cpp:94:13:94:18 | AST only | +| set.cpp:110:7:110:9 | set.cpp:108:13:108:18 | AST only | +| set.cpp:110:7:110:9 | set.cpp:109:13:109:18 | AST only | +| set.cpp:112:7:112:9 | set.cpp:108:13:108:18 | AST only | +| set.cpp:112:7:112:9 | set.cpp:109:13:109:18 | AST only | +| set.cpp:114:7:114:9 | set.cpp:108:13:108:18 | AST only | +| set.cpp:114:7:114:9 | set.cpp:109:13:109:18 | AST only | +| set.cpp:134:7:134:31 | set.cpp:134:17:134:22 | IR only | +| set.cpp:140:7:140:8 | set.cpp:134:17:134:22 | AST only | +| set.cpp:142:7:142:8 | set.cpp:136:29:136:34 | AST only | +| set.cpp:144:7:144:8 | set.cpp:134:17:134:22 | AST only | +| set.cpp:158:7:158:8 | set.cpp:134:17:134:22 | AST only | +| set.cpp:159:7:159:8 | set.cpp:134:17:134:22 | AST only | +| set.cpp:161:7:161:9 | set.cpp:134:17:134:22 | AST only | +| set.cpp:162:10:162:13 | set.cpp:134:17:134:22 | AST only | +| set.cpp:163:10:163:13 | set.cpp:134:17:134:22 | AST only | +| set.cpp:175:8:175:11 | set.cpp:134:17:134:22 | IR only | +| set.cpp:190:7:190:9 | set.cpp:188:13:188:18 | AST only | +| set.cpp:193:7:193:9 | set.cpp:189:13:189:18 | AST only | +| set.cpp:196:7:196:9 | set.cpp:188:13:188:18 | AST only | +| set.cpp:197:7:197:9 | set.cpp:188:13:188:18 | AST only | +| set.cpp:198:7:198:9 | set.cpp:189:13:189:18 | AST only | +| set.cpp:199:7:199:9 | set.cpp:189:13:189:18 | AST only | +| set.cpp:207:7:207:9 | set.cpp:203:13:203:18 | AST only | +| set.cpp:210:7:210:9 | set.cpp:206:13:206:18 | AST only | +| set.cpp:213:7:213:9 | set.cpp:203:13:203:18 | AST only | +| set.cpp:216:7:216:9 | set.cpp:206:13:206:18 | AST only | +| set.cpp:222:7:222:9 | set.cpp:220:13:220:18 | AST only | +| set.cpp:222:7:222:9 | set.cpp:221:13:221:18 | AST only | +| set.cpp:224:7:224:9 | set.cpp:220:13:220:18 | AST only | +| set.cpp:224:7:224:9 | set.cpp:221:13:221:18 | AST only | +| set.cpp:226:7:226:9 | set.cpp:220:13:220:18 | AST only | +| set.cpp:226:7:226:9 | set.cpp:221:13:221:18 | AST only | | smart_pointer.cpp:12:10:12:10 | smart_pointer.cpp:11:52:11:57 | AST only | | smart_pointer.cpp:24:10:24:10 | smart_pointer.cpp:23:52:23:57 | AST only | | standalone_iterators.cpp:41:10:41:10 | standalone_iterators.cpp:39:45:39:51 | 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 3536273a806..6ac824277a3 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 @@ -133,6 +133,26 @@ | movableclass.cpp:55:8:55:9 | s2 | movableclass.cpp:52:23:52:28 | call to source | | movableclass.cpp:64:8:64:9 | s2 | movableclass.cpp:23:55:23:60 | call to source | | movableclass.cpp:65:11:65:21 | (reference dereference) | movableclass.cpp:65:13:65:18 | call to source | +| set.cpp:20:7:20:31 | call to iterator | set.cpp:20:17:20:22 | call to source | +| set.cpp:22:10:22:15 | call to insert | set.cpp:22:29:22:34 | call to source | +| set.cpp:32:10:32:13 | call to find | set.cpp:20:17:20:22 | call to source | +| set.cpp:34:10:34:13 | call to find | set.cpp:22:29:22:34 | call to source | +| set.cpp:36:10:36:13 | call to find | set.cpp:20:17:20:22 | call to source | +| set.cpp:51:11:51:14 | call to find | set.cpp:20:17:20:22 | call to source | +| set.cpp:61:8:61:8 | call to operator* | set.cpp:20:17:20:22 | call to source | +| set.cpp:61:8:61:11 | (reference dereference) | set.cpp:20:17:20:22 | call to source | +| set.cpp:111:11:111:15 | call to erase | set.cpp:108:13:108:18 | call to source | +| set.cpp:111:11:111:15 | call to erase | set.cpp:109:13:109:18 | call to source | +| set.cpp:134:7:134:31 | call to iterator | set.cpp:134:17:134:22 | call to source | +| set.cpp:136:10:136:15 | call to insert | set.cpp:136:29:136:34 | call to source | +| set.cpp:146:10:146:13 | call to find | set.cpp:134:17:134:22 | call to source | +| set.cpp:148:10:148:13 | call to find | set.cpp:136:29:136:34 | call to source | +| set.cpp:150:10:150:13 | call to find | set.cpp:134:17:134:22 | call to source | +| set.cpp:165:11:165:14 | call to find | set.cpp:134:17:134:22 | call to source | +| set.cpp:175:8:175:8 | call to operator* | set.cpp:134:17:134:22 | call to source | +| set.cpp:175:8:175:11 | (reference dereference) | set.cpp:134:17:134:22 | call to source | +| set.cpp:223:11:223:15 | call to erase | set.cpp:220:13:220:18 | call to source | +| set.cpp:223:11:223:15 | call to erase | set.cpp:221:13:221:18 | call to source | | smart_pointer.cpp:13:10:13:10 | Argument 0 indirection | smart_pointer.cpp:11:52:11:57 | call to source | | smart_pointer.cpp:25:10:25:10 | Argument 0 indirection | smart_pointer.cpp:23:52:23:57 | call to source | | smart_pointer.cpp:52:12:52:14 | call to get | smart_pointer.cpp:51:52:51:57 | call to source | From cafd32095326e867e817b3935f156a30b85d1141 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 30 Sep 2020 17:37:56 +0100 Subject: [PATCH 144/411] C++: Add set/map constructor models. --- .../cpp/models/implementations/StdMap.qll | 27 ++++++++++++++++ .../cpp/models/implementations/StdSet.qll | 31 +++++++++++++++++-- .../dataflow/taint-tests/localTaint.expected | 4 +++ .../dataflow/taint-tests/set.cpp | 8 ++--- .../dataflow/taint-tests/taint.expected | 4 +++ .../dataflow/taint-tests/test_diff.expected | 2 ++ .../dataflow/taint-tests/test_ir.expected | 2 ++ 7 files changed, 71 insertions(+), 7 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll index 7f2f3a1f4eb..3fee914f749 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll @@ -5,6 +5,33 @@ import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.implementations.Iterator +/** + * Additional model for map constructors using iterator inputs. + */ +class StdMapConstructor extends Constructor, TaintFunction { + StdMapConstructor() { + this.hasQualifiedName("std", "map", "map") or + this.hasQualifiedName("std", "unordered_map", "unordered_map") + } + + /** + * Gets the index of a parameter to this function that is an iterator. + */ + int getAnIteratorParameterIndex() { + getParameter(result).getUnspecifiedType() instanceof Iterator + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // taint flow from any parameter of an iterator type to the qualifier + input.isParameterDeref(getAnIteratorParameterIndex()) and + ( + output.isReturnValue() // TODO: this is only needed for AST data flow, which treats constructors as returning the new object + or + output.isQualifierObject() + ) + } +} + /** * The standard map `insert` and `insert_or_assign` functions. */ diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll index 9101745219a..891c282dda7 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll @@ -5,13 +5,38 @@ import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.implementations.Iterator +/** + * Additional model for set constructors using iterator inputs. + */ +class StdSetConstructor extends Constructor, TaintFunction { + StdSetConstructor() { + this.hasQualifiedName("std", "set", "set") or + this.hasQualifiedName("std", "unordered_set", "unordered_set") + } + + /** + * Gets the index of a parameter to this function that is an iterator. + */ + int getAnIteratorParameterIndex() { + getParameter(result).getUnspecifiedType() instanceof Iterator + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // taint flow from any parameter of an iterator type to the qualifier + input.isParameterDeref(getAnIteratorParameterIndex()) and + ( + output.isReturnValue() // TODO: this is only needed for AST data flow, which treats constructors as returning the new object + or + output.isQualifierObject() + ) + } +} + /** * The standard set `insert` and `insert_or_assign` functions. */ class StdSetInsert extends TaintFunction { - StdSetInsert() { - this.hasQualifiedName("std", ["set", "unordered_set"], "insert") - } + StdSetInsert() { this.hasQualifiedName("std", ["set", "unordered_set"], "insert") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { // flow from last parameter to qualifier and return value 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 144fd743cab..5db2f3458f3 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -2095,11 +2095,13 @@ | set.cpp:41:22:41:42 | call to set | set.cpp:46:7:46:8 | s9 | | | set.cpp:41:22:41:42 | call to set | set.cpp:50:7:50:8 | s9 | | | set.cpp:41:22:41:42 | call to set | set.cpp:126:1:126:1 | s9 | | +| set.cpp:41:25:41:29 | call to begin | set.cpp:41:22:41:42 | call to set | TAINT | | set.cpp:41:34:41:35 | ref arg s2 | set.cpp:43:8:43:9 | s2 | | | set.cpp:41:34:41:35 | ref arg s2 | set.cpp:59:12:59:13 | s2 | | | set.cpp:41:34:41:35 | ref arg s2 | set.cpp:59:30:59:31 | s2 | | | set.cpp:41:34:41:35 | ref arg s2 | set.cpp:126:1:126:1 | s2 | | | set.cpp:41:34:41:35 | s2 | set.cpp:41:37:41:39 | call to end | TAINT | +| set.cpp:41:37:41:39 | call to end | set.cpp:41:22:41:42 | call to set | TAINT | | set.cpp:42:19:42:21 | call to set | set.cpp:43:2:43:4 | s10 | | | set.cpp:42:19:42:21 | call to set | set.cpp:47:7:47:9 | s10 | | | set.cpp:42:19:42:21 | call to set | set.cpp:51:7:51:9 | s10 | | @@ -2569,11 +2571,13 @@ | set.cpp:155:32:155:52 | call to unordered_set | set.cpp:160:7:160:8 | s9 | | | set.cpp:155:32:155:52 | call to unordered_set | set.cpp:164:7:164:8 | s9 | | | set.cpp:155:32:155:52 | call to unordered_set | set.cpp:238:1:238:1 | s9 | | +| set.cpp:155:35:155:39 | call to begin | set.cpp:155:32:155:52 | call to unordered_set | TAINT | | set.cpp:155:44:155:45 | ref arg s2 | set.cpp:157:8:157:9 | s2 | | | set.cpp:155:44:155:45 | ref arg s2 | set.cpp:173:12:173:13 | s2 | | | set.cpp:155:44:155:45 | ref arg s2 | set.cpp:173:30:173:31 | s2 | | | set.cpp:155:44:155:45 | ref arg s2 | set.cpp:238:1:238:1 | s2 | | | set.cpp:155:44:155:45 | s2 | set.cpp:155:47:155:49 | call to end | TAINT | +| set.cpp:155:47:155:49 | call to end | set.cpp:155:32:155:52 | call to unordered_set | TAINT | | set.cpp:156:29:156:31 | call to unordered_set | set.cpp:157:2:157:4 | s10 | | | set.cpp:156:29:156:31 | call to unordered_set | set.cpp:161:7:161:9 | s10 | | | set.cpp:156:29:156:31 | call to unordered_set | set.cpp:165:7:165:9 | s10 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/set.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/set.cpp index f2c07e48d60..b6d19ab1647 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/set.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/set.cpp @@ -43,11 +43,11 @@ void test_set() s10 = s2; sink(s7); // tainted sink(s8); // tainted - sink(s9); // tainted [NOT DETECTED] + sink(s9); // tainted sink(s10); // tainted sink(s7.find("abc")); // tainted sink(s8.find("abc")); // tainted - sink(s9.find("abc")); // tainted [NOT DETECTED] + sink(s9.find("abc")); // tainted sink(s10.find("abc")); // tainted // iterators @@ -157,11 +157,11 @@ void test_unordered_set() s10 = s2; sink(s7); // tainted sink(s8); // tainted - sink(s9); // tainted [NOT DETECTED] + sink(s9); // tainted sink(s10); // tainted sink(s7.find("abc")); // tainted sink(s8.find("abc")); // tainted - sink(s9.find("abc")); // tainted [NOT DETECTED] + sink(s9.find("abc")); // tainted sink(s10.find("abc")); // tainted // iterators 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 37e89c28fcf..3148ca962cc 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -198,9 +198,11 @@ | set.cpp:36:10:36:13 | call to find | set.cpp:20:17:20:22 | call to source | | set.cpp:44:7:44:8 | call to set | set.cpp:20:17:20:22 | call to source | | set.cpp:45:7:45:8 | call to set | set.cpp:20:17:20:22 | call to source | +| set.cpp:46:7:46:8 | call to set | set.cpp:20:17:20:22 | call to source | | set.cpp:47:7:47:9 | call to set | set.cpp:20:17:20:22 | call to source | | set.cpp:48:10:48:13 | call to find | set.cpp:20:17:20:22 | call to source | | set.cpp:49:10:49:13 | call to find | set.cpp:20:17:20:22 | call to source | +| set.cpp:50:10:50:13 | call to find | set.cpp:20:17:20:22 | call to source | | set.cpp:51:11:51:14 | call to find | set.cpp:20:17:20:22 | call to source | | set.cpp:61:8:61:8 | call to operator* | set.cpp:20:17:20:22 | call to source | | set.cpp:78:7:78:9 | call to set | set.cpp:76:13:76:18 | call to source | @@ -230,9 +232,11 @@ | set.cpp:150:10:150:13 | call to find | set.cpp:134:17:134:22 | call to source | | set.cpp:158:7:158:8 | call to unordered_set | set.cpp:134:17:134:22 | call to source | | set.cpp:159:7:159:8 | call to unordered_set | set.cpp:134:17:134:22 | call to source | +| set.cpp:160:7:160:8 | call to unordered_set | set.cpp:134:17:134:22 | call to source | | set.cpp:161:7:161:9 | call to unordered_set | set.cpp:134:17:134:22 | call to source | | set.cpp:162:10:162:13 | call to find | set.cpp:134:17:134:22 | call to source | | set.cpp:163:10:163:13 | call to find | set.cpp:134:17:134:22 | call to source | +| set.cpp:164:10:164:13 | call to find | set.cpp:134:17:134:22 | call to source | | set.cpp:165:11:165:14 | call to find | set.cpp:134:17:134:22 | call to source | | set.cpp:175:8:175:8 | call to operator* | set.cpp:134:17:134:22 | call to source | | set.cpp:190:7:190:9 | call to unordered_set | set.cpp:188:13:188:18 | 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 d3d13dd9b55..0381fc18c7d 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 @@ -154,6 +154,7 @@ | set.cpp:30:7:30:8 | set.cpp:20:17:20:22 | AST only | | set.cpp:44:7:44:8 | set.cpp:20:17:20:22 | AST only | | set.cpp:45:7:45:8 | set.cpp:20:17:20:22 | AST only | +| set.cpp:46:7:46:8 | set.cpp:20:17:20:22 | AST only | | set.cpp:47:7:47:9 | set.cpp:20:17:20:22 | AST only | | set.cpp:48:10:48:13 | set.cpp:20:17:20:22 | AST only | | set.cpp:49:10:49:13 | set.cpp:20:17:20:22 | AST only | @@ -180,6 +181,7 @@ | set.cpp:144:7:144:8 | set.cpp:134:17:134:22 | AST only | | set.cpp:158:7:158:8 | set.cpp:134:17:134:22 | AST only | | set.cpp:159:7:159:8 | set.cpp:134:17:134:22 | AST only | +| set.cpp:160:7:160:8 | set.cpp:134:17:134:22 | AST only | | set.cpp:161:7:161:9 | set.cpp:134:17:134:22 | AST only | | set.cpp:162:10:162:13 | set.cpp:134:17:134:22 | AST only | | set.cpp:163:10:163:13 | set.cpp:134:17:134:22 | 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 6ac824277a3..d585743f243 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 @@ -138,6 +138,7 @@ | set.cpp:32:10:32:13 | call to find | set.cpp:20:17:20:22 | call to source | | set.cpp:34:10:34:13 | call to find | set.cpp:22:29:22:34 | call to source | | set.cpp:36:10:36:13 | call to find | set.cpp:20:17:20:22 | call to source | +| set.cpp:50:10:50:13 | call to find | set.cpp:20:17:20:22 | call to source | | set.cpp:51:11:51:14 | call to find | set.cpp:20:17:20:22 | call to source | | set.cpp:61:8:61:8 | call to operator* | set.cpp:20:17:20:22 | call to source | | set.cpp:61:8:61:11 | (reference dereference) | set.cpp:20:17:20:22 | call to source | @@ -148,6 +149,7 @@ | set.cpp:146:10:146:13 | call to find | set.cpp:134:17:134:22 | call to source | | set.cpp:148:10:148:13 | call to find | set.cpp:136:29:136:34 | call to source | | set.cpp:150:10:150:13 | call to find | set.cpp:134:17:134:22 | call to source | +| set.cpp:164:10:164:13 | call to find | set.cpp:134:17:134:22 | call to source | | set.cpp:165:11:165:14 | call to find | set.cpp:134:17:134:22 | call to source | | set.cpp:175:8:175:8 | call to operator* | set.cpp:134:17:134:22 | call to source | | set.cpp:175:8:175:11 | (reference dereference) | set.cpp:134:17:134:22 | call to source | From e712d16e7e31273e397d88299f635d22c75aef9c Mon Sep 17 00:00:00 2001 From: Aditya Sharad Date: Wed, 30 Sep 2020 15:10:49 -0700 Subject: [PATCH 145/411] JavaScript: Track taint through RegExp.prototype.exec for URL redirection Regexp literals are currently handled, but not `RegExp` objects. --- .../ClientSideUrlRedirectCustomizations.qll | 2 +- .../ClientSideUrlRedirect.expected | 48 +++++++++++++++++++ .../CWE-601/ClientSideUrlRedirect/tst.js | 16 +++++++ 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll index 64c76a84b82..a74a9f58a0f 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll @@ -65,7 +65,7 @@ module ClientSideUrlRedirect { or exists(MethodCallExpr mce | queryAccess.asExpr() = mce and - mce = any(RegExpLiteral re).flow().(DataFlow::SourceNode).getAMethodCall("exec").asExpr() and + mce = any(DataFlow::RegExpCreationNode re).getAMethodCall("exec").asExpr() and nd.asExpr() = mce.getArgument(0) ) } diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/ClientSideUrlRedirect.expected b/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/ClientSideUrlRedirect.expected index b7dca317a88..b5621666d73 100644 --- a/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/ClientSideUrlRedirect.expected +++ b/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/ClientSideUrlRedirect.expected @@ -133,6 +133,30 @@ nodes | tst.js:6:34:6:50 | document.location | | tst.js:6:34:6:50 | document.location | | tst.js:6:34:6:55 | documen ... on.href | +| tst.js:10:19:10:81 | new Reg ... n.href) | +| tst.js:10:19:10:84 | new Reg ... ref)[1] | +| tst.js:10:19:10:84 | new Reg ... ref)[1] | +| tst.js:10:59:10:75 | document.location | +| tst.js:10:59:10:75 | document.location | +| tst.js:10:59:10:80 | documen ... on.href | +| tst.js:14:20:14:56 | indirec ... n.href) | +| tst.js:14:20:14:59 | indirec ... ref)[1] | +| tst.js:14:20:14:59 | indirec ... ref)[1] | +| tst.js:14:34:14:50 | document.location | +| tst.js:14:34:14:50 | document.location | +| tst.js:14:34:14:55 | documen ... on.href | +| tst.js:18:19:18:81 | new Reg ... n.href) | +| tst.js:18:19:18:84 | new Reg ... ref)[1] | +| tst.js:18:19:18:84 | new Reg ... ref)[1] | +| tst.js:18:59:18:75 | document.location | +| tst.js:18:59:18:75 | document.location | +| tst.js:18:59:18:80 | documen ... on.href | +| tst.js:22:20:22:56 | indirec ... n.href) | +| tst.js:22:20:22:59 | indirec ... ref)[1] | +| tst.js:22:20:22:59 | indirec ... ref)[1] | +| tst.js:22:34:22:50 | document.location | +| tst.js:22:34:22:50 | document.location | +| tst.js:22:34:22:55 | documen ... on.href | edges | sanitizer.js:2:9:2:25 | url | sanitizer.js:4:27:4:29 | url | | sanitizer.js:2:9:2:25 | url | sanitizer.js:4:27:4:29 | url | @@ -260,6 +284,26 @@ edges | tst.js:6:34:6:50 | document.location | tst.js:6:34:6:55 | documen ... on.href | | tst.js:6:34:6:50 | document.location | tst.js:6:34:6:55 | documen ... on.href | | tst.js:6:34:6:55 | documen ... on.href | tst.js:6:20:6:56 | indirec ... n.href) | +| tst.js:10:19:10:81 | new Reg ... n.href) | tst.js:10:19:10:84 | new Reg ... ref)[1] | +| tst.js:10:19:10:81 | new Reg ... n.href) | tst.js:10:19:10:84 | new Reg ... ref)[1] | +| tst.js:10:59:10:75 | document.location | tst.js:10:59:10:80 | documen ... on.href | +| tst.js:10:59:10:75 | document.location | tst.js:10:59:10:80 | documen ... on.href | +| tst.js:10:59:10:80 | documen ... on.href | tst.js:10:19:10:81 | new Reg ... n.href) | +| tst.js:14:20:14:56 | indirec ... n.href) | tst.js:14:20:14:59 | indirec ... ref)[1] | +| tst.js:14:20:14:56 | indirec ... n.href) | tst.js:14:20:14:59 | indirec ... ref)[1] | +| tst.js:14:34:14:50 | document.location | tst.js:14:34:14:55 | documen ... on.href | +| tst.js:14:34:14:50 | document.location | tst.js:14:34:14:55 | documen ... on.href | +| tst.js:14:34:14:55 | documen ... on.href | tst.js:14:20:14:56 | indirec ... n.href) | +| tst.js:18:19:18:81 | new Reg ... n.href) | tst.js:18:19:18:84 | new Reg ... ref)[1] | +| tst.js:18:19:18:81 | new Reg ... n.href) | tst.js:18:19:18:84 | new Reg ... ref)[1] | +| tst.js:18:59:18:75 | document.location | tst.js:18:59:18:80 | documen ... on.href | +| tst.js:18:59:18:75 | document.location | tst.js:18:59:18:80 | documen ... on.href | +| tst.js:18:59:18:80 | documen ... on.href | tst.js:18:19:18:81 | new Reg ... n.href) | +| tst.js:22:20:22:56 | indirec ... n.href) | tst.js:22:20:22:59 | indirec ... ref)[1] | +| tst.js:22:20:22:56 | indirec ... n.href) | tst.js:22:20:22:59 | indirec ... ref)[1] | +| tst.js:22:34:22:50 | document.location | tst.js:22:34:22:55 | documen ... on.href | +| tst.js:22:34:22:50 | document.location | tst.js:22:34:22:55 | documen ... on.href | +| tst.js:22:34:22:55 | documen ... on.href | tst.js:22:20:22:56 | indirec ... n.href) | #select | sanitizer.js:4:27:4:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:4:27:4:29 | url | Untrusted URL redirection due to $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value | | sanitizer.js:16:27:16:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:16:27:16:29 | url | Untrusted URL redirection due to $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value | @@ -296,3 +340,7 @@ edges | tst13.js:53:28:53:28 | e | tst13.js:52:34:52:34 | e | tst13.js:53:28:53:28 | e | Untrusted URL redirection due to $@. | tst13.js:52:34:52:34 | e | user-provided value | | tst.js:2:19:2:72 | /.*redi ... ref)[1] | tst.js:2:47:2:63 | document.location | tst.js:2:19:2:72 | /.*redi ... ref)[1] | Untrusted URL redirection due to $@. | tst.js:2:47:2:63 | document.location | user-provided value | | tst.js:6:20:6:59 | indirec ... ref)[1] | tst.js:6:34:6:50 | document.location | tst.js:6:20:6:59 | indirec ... ref)[1] | Untrusted URL redirection due to $@. | tst.js:6:34:6:50 | document.location | user-provided value | +| tst.js:10:19:10:84 | new Reg ... ref)[1] | tst.js:10:59:10:75 | document.location | tst.js:10:19:10:84 | new Reg ... ref)[1] | Untrusted URL redirection due to $@. | tst.js:10:59:10:75 | document.location | user-provided value | +| tst.js:14:20:14:59 | indirec ... ref)[1] | tst.js:14:34:14:50 | document.location | tst.js:14:20:14:59 | indirec ... ref)[1] | Untrusted URL redirection due to $@. | tst.js:14:34:14:50 | document.location | user-provided value | +| tst.js:18:19:18:84 | new Reg ... ref)[1] | tst.js:18:59:18:75 | document.location | tst.js:18:19:18:84 | new Reg ... ref)[1] | Untrusted URL redirection due to $@. | tst.js:18:59:18:75 | document.location | user-provided value | +| tst.js:22:20:22:59 | indirec ... ref)[1] | tst.js:22:34:22:50 | document.location | tst.js:22:20:22:59 | indirec ... ref)[1] | Untrusted URL redirection due to $@. | tst.js:22:34:22:50 | document.location | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/tst.js b/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/tst.js index a77903120ab..7994c1e3558 100644 --- a/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/tst.js @@ -5,3 +5,19 @@ window.location = /.*redirect=([^&]*).*/.exec(document.location.href)[1]; var indirect = /.*redirect=([^&]*).*/; window.location = indirect.exec(document.location.href)[1]; }); + +// NOT OK +window.location = new RegExp('.*redirect=([^&]*).*').exec(document.location.href)[1]; + +(function(){ + var indirect = new RegExp('.*redirect=([^&]*).*') + window.location = indirect.exec(document.location.href)[1]; +}); + +// NOT OK +window.location = new RegExp(/.*redirect=([^&]*).*/).exec(document.location.href)[1]; + +(function(){ + var indirect = new RegExp(/.*redirect=([^&]*).*/) + window.location = indirect.exec(document.location.href)[1]; +}); From f65ba114859fc1c134692e36e9f422cac8650b01 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 30 Sep 2020 15:13:17 +0200 Subject: [PATCH 146/411] use Parameter instead of SimpleParameter in AMD.qll --- javascript/ql/src/semmle/javascript/AMD.qll | 8 ++++---- .../ql/test/library-tests/AMD/AmdModule.expected | 1 + .../library-tests/AMD/AmdModuleDefinition.expected | 13 +++++++++++++ .../test/library-tests/AMD/AmdModuleDefinition.ql | 4 ++++ .../AMD/AmdModuleDependencies.expected | 2 ++ .../AMD/AmdModuleExportedSymbol.expected | 2 ++ .../test/library-tests/AMD/AmdModuleExpr.expected | 1 + .../AMD/AmdModuleImportedModule.expected | 2 ++ .../library-tests/AMD/AmdModule_exports.expected | 2 ++ javascript/ql/test/library-tests/AMD/tst5.js | 6 ++++++ 10 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 javascript/ql/test/library-tests/AMD/tst5.js diff --git a/javascript/ql/src/semmle/javascript/AMD.qll b/javascript/ql/src/semmle/javascript/AMD.qll index 49e0d8a9c39..5edf7fd3dfe 100644 --- a/javascript/ql/src/semmle/javascript/AMD.qll +++ b/javascript/ql/src/semmle/javascript/AMD.qll @@ -113,14 +113,14 @@ class AmdModuleDefinition extends CallExpr { /** * Gets the `i`th parameter of the factory function of this module. */ - private SimpleParameter getFactoryParameter(int i) { + private Parameter getFactoryParameter(int i) { getFactoryNodeInternal().asExpr().(Function).getParameter(i) = result } /** * Gets the parameter corresponding to the pseudo-dependency `require`. */ - SimpleParameter getRequireParameter() { + Parameter getRequireParameter() { result = getDependencyParameter("require") or // if no dependencies are listed, the first parameter is assumed to be `require` @@ -133,7 +133,7 @@ class AmdModuleDefinition extends CallExpr { /** * Gets the parameter corresponding to the pseudo-dependency `exports`. */ - SimpleParameter getExportsParameter() { + Parameter getExportsParameter() { result = getDependencyParameter("exports") or // if no dependencies are listed, the second parameter is assumed to be `exports` @@ -143,7 +143,7 @@ class AmdModuleDefinition extends CallExpr { /** * Gets the parameter corresponding to the pseudo-dependency `module`. */ - SimpleParameter getModuleParameter() { + Parameter getModuleParameter() { result = getDependencyParameter("module") or // if no dependencies are listed, the third parameter is assumed to be `module` diff --git a/javascript/ql/test/library-tests/AMD/AmdModule.expected b/javascript/ql/test/library-tests/AMD/AmdModule.expected index fe2959ab871..492b2cdfa00 100644 --- a/javascript/ql/test/library-tests/AMD/AmdModule.expected +++ b/javascript/ql/test/library-tests/AMD/AmdModule.expected @@ -6,5 +6,6 @@ | tst2.js:1:1:3:3 | | tst2.js:1:1:3:2 | define( ... 42;\\n}) | | tst3.js:1:1:3:3 | | tst3.js:1:1:3:2 | define( ... 42;\\n}) | | tst4.js:1:1:11:3 | | tst4.js:1:1:11:2 | define( ... };\\n}) | +| tst5.js:1:1:6:3 | | tst5.js:1:1:6:2 | define( ... };\\n}) | | tst.js:1:1:6:3 | | tst.js:1:1:6:2 | define( ... };\\n}) | | umd.js:1:1:14:4 | | umd.js:4:9:4:43 | define( ... actory) | diff --git a/javascript/ql/test/library-tests/AMD/AmdModuleDefinition.expected b/javascript/ql/test/library-tests/AMD/AmdModuleDefinition.expected index 4d2e9e836ad..6f890918eb6 100644 --- a/javascript/ql/test/library-tests/AMD/AmdModuleDefinition.expected +++ b/javascript/ql/test/library-tests/AMD/AmdModuleDefinition.expected @@ -1,3 +1,15 @@ +getDependencyParameter +| tst2.js:1:1:3:2 | define( ... 42;\\n}) | exports | tst2.js:1:30:1:36 | exports | +| tst4.js:1:1:11:2 | define( ... };\\n}) | a.js | tst4.js:6:20:6:20 | a | +| tst4.js:1:1:11:2 | define( ... };\\n}) | foo | tst4.js:6:23:6:23 | b | +| tst4.js:1:1:11:2 | define( ... };\\n}) | nested/a | tst4.js:6:26:6:32 | exports | +| tst5.js:1:1:6:2 | define( ... };\\n}) | ./a | tst5.js:1:37:1:37 | a | +| tst5.js:1:1:6:2 | define( ... };\\n}) | ./dir/b | tst5.js:1:40:1:44 | {bar} | +| tst.js:1:1:6:2 | define( ... };\\n}) | ./a | tst.js:1:37:1:37 | a | +| tst.js:1:1:6:2 | define( ... };\\n}) | ./dir/b | tst.js:1:40:1:40 | b | +| umd.js:4:9:4:43 | define( ... actory) | ./a | umd.js:9:19:9:19 | a | +| umd.js:4:9:4:43 | define( ... actory) | ./dir/b | umd.js:9:22:9:22 | b | +#select | a.js:1:1:3:2 | define( ... 2 };\\n}) | a.js:1:8:3:1 | functio ... 42 };\\n} | | dir/b.js:1:1:3:2 | define( ... : 42\\n}) | dir/b.js:1:8:3:1 | {\\n bar: 42\\n} | | lib/a.js:1:1:3:2 | define( ... 2 };\\n}) | lib/a.js:1:8:3:1 | functio ... 42 };\\n} | @@ -6,6 +18,7 @@ | tst2.js:1:1:3:2 | define( ... 42;\\n}) | tst2.js:1:21:3:1 | functio ... = 42;\\n} | | tst3.js:1:1:3:2 | define( ... 42;\\n}) | tst3.js:1:8:3:1 | functio ... = 42;\\n} | | tst4.js:1:1:11:2 | define( ... };\\n}) | tst4.js:6:11:11:1 | functio ... };\\n} | +| tst5.js:1:1:6:2 | define( ... };\\n}) | tst5.js:1:28:6:1 | functio ... };\\n} | | tst.js:1:1:6:2 | define( ... };\\n}) | tst.js:1:28:6:1 | functio ... };\\n} | | umd.js:4:9:4:43 | define( ... actory) | umd.js:1:18:1:24 | factory | | umd.js:4:9:4:43 | define( ... actory) | umd.js:9:9:14:1 | functio ... };\\n} | diff --git a/javascript/ql/test/library-tests/AMD/AmdModuleDefinition.ql b/javascript/ql/test/library-tests/AMD/AmdModuleDefinition.ql index 88b6aae102a..32fe2bce188 100644 --- a/javascript/ql/test/library-tests/AMD/AmdModuleDefinition.ql +++ b/javascript/ql/test/library-tests/AMD/AmdModuleDefinition.ql @@ -1,4 +1,8 @@ import javascript +query Parameter getDependencyParameter(AmdModuleDefinition mod, string name) { + result = mod.getDependencyParameter(name) +} + from AmdModuleDefinition d select d, d.getFactoryNode() diff --git a/javascript/ql/test/library-tests/AMD/AmdModuleDependencies.expected b/javascript/ql/test/library-tests/AMD/AmdModuleDependencies.expected index c3fc8fb4a61..11c4793860c 100644 --- a/javascript/ql/test/library-tests/AMD/AmdModuleDependencies.expected +++ b/javascript/ql/test/library-tests/AMD/AmdModuleDependencies.expected @@ -4,6 +4,8 @@ | tst4.js:1:1:11:2 | define( ... };\\n}) | tst4.js:3:9:3:13 | 'foo' | | tst4.js:1:1:11:2 | define( ... };\\n}) | tst4.js:4:9:4:18 | 'nested/a' | | tst4.js:1:1:11:2 | define( ... };\\n}) | tst4.js:5:9:5:20 | 'lib/foo.js' | +| tst5.js:1:1:6:2 | define( ... };\\n}) | tst5.js:1:9:1:13 | './a' | +| tst5.js:1:1:6:2 | define( ... };\\n}) | tst5.js:1:16:1:24 | './dir/b' | | tst.js:1:1:6:2 | define( ... };\\n}) | tst.js:1:9:1:13 | './a' | | tst.js:1:1:6:2 | define( ... };\\n}) | tst.js:1:16:1:24 | './dir/b' | | umd.js:4:9:4:43 | define( ... actory) | umd.js:4:17:4:21 | './a' | diff --git a/javascript/ql/test/library-tests/AMD/AmdModuleExportedSymbol.expected b/javascript/ql/test/library-tests/AMD/AmdModuleExportedSymbol.expected index 298c93e7aa3..4d41acc3403 100644 --- a/javascript/ql/test/library-tests/AMD/AmdModuleExportedSymbol.expected +++ b/javascript/ql/test/library-tests/AMD/AmdModuleExportedSymbol.expected @@ -7,6 +7,8 @@ | tst3.js:1:1:3:3 | | foo | | tst4.js:1:1:11:3 | | bar | | tst4.js:1:1:11:3 | | foo | +| tst5.js:1:1:6:3 | | bar | +| tst5.js:1:1:6:3 | | foo | | tst.js:1:1:6:3 | | bar | | tst.js:1:1:6:3 | | foo | | umd.js:1:1:14:4 | | bar | diff --git a/javascript/ql/test/library-tests/AMD/AmdModuleExpr.expected b/javascript/ql/test/library-tests/AMD/AmdModuleExpr.expected index 59ecf8ae8c2..d16cb95c4c0 100644 --- a/javascript/ql/test/library-tests/AMD/AmdModuleExpr.expected +++ b/javascript/ql/test/library-tests/AMD/AmdModuleExpr.expected @@ -4,6 +4,7 @@ | lib/foo.js:1:1:3:2 | define( ... : 23\\n}) | lib/foo.js:1:8:3:1 | {\\n foo: 23\\n} | lib/foo.js:1:8:3:1 | {\\n foo: 23\\n} | | lib/nested/a.js:1:1:3:2 | define( ... 2 };\\n}) | lib/nested/a.js:2:12:2:22 | { foo: 42 } | lib/nested/a.js:2:12:2:22 | { foo: 42 } | | tst4.js:1:1:11:2 | define( ... };\\n}) | tst4.js:7:12:10:5 | {\\n ... r\\n } | tst4.js:7:12:10:5 | {\\n ... r\\n } | +| tst5.js:1:1:6:2 | define( ... };\\n}) | tst5.js:2:12:5:5 | {\\n ... r\\n } | tst5.js:2:12:5:5 | {\\n ... r\\n } | | tst.js:1:1:6:2 | define( ... };\\n}) | tst.js:2:12:5:5 | {\\n ... r\\n } | tst.js:2:12:5:5 | {\\n ... r\\n } | | umd.js:4:9:4:43 | define( ... actory) | umd.js:1:18:1:24 | factory | umd.js:1:18:1:24 | factory | | umd.js:4:9:4:43 | define( ... actory) | umd.js:1:18:1:24 | factory | umd.js:9:9:14:1 | functio ... };\\n} | diff --git a/javascript/ql/test/library-tests/AMD/AmdModuleImportedModule.expected b/javascript/ql/test/library-tests/AMD/AmdModuleImportedModule.expected index a92b85c3b84..4a09d177e2d 100644 --- a/javascript/ql/test/library-tests/AMD/AmdModuleImportedModule.expected +++ b/javascript/ql/test/library-tests/AMD/AmdModuleImportedModule.expected @@ -2,6 +2,8 @@ | tst4.js:1:1:11:3 | | tst4.js:3:9:3:13 | 'foo' | lib/foo.js:1:1:4:0 | | | tst4.js:1:1:11:3 | | tst4.js:4:9:4:18 | 'nested/a' | lib/nested/a.js:1:1:3:3 | | | tst4.js:1:1:11:3 | | tst4.js:5:9:5:20 | 'lib/foo.js' | lib/foo.js:1:1:4:0 | | +| tst5.js:1:1:6:3 | | tst5.js:1:9:1:13 | './a' | a.js:1:1:3:3 | | +| tst5.js:1:1:6:3 | | tst5.js:1:16:1:24 | './dir/b' | dir/b.js:1:1:3:3 | | | tst.js:1:1:6:3 | | tst.js:1:9:1:13 | './a' | a.js:1:1:3:3 | | | tst.js:1:1:6:3 | | tst.js:1:16:1:24 | './dir/b' | dir/b.js:1:1:3:3 | | | umd.js:1:1:14:4 | | umd.js:4:17:4:21 | './a' | a.js:1:1:3:3 | | diff --git a/javascript/ql/test/library-tests/AMD/AmdModule_exports.expected b/javascript/ql/test/library-tests/AMD/AmdModule_exports.expected index a860e264404..935299f3df5 100644 --- a/javascript/ql/test/library-tests/AMD/AmdModule_exports.expected +++ b/javascript/ql/test/library-tests/AMD/AmdModule_exports.expected @@ -7,6 +7,8 @@ | tst3.js:1:1:3:3 | | foo | tst3.js:2:29:2:39 | exports.foo | | tst4.js:1:1:11:3 | | bar | tst4.js:9:9:9:18 | bar: b.bar | | tst4.js:1:1:11:3 | | foo | tst4.js:8:9:8:18 | foo: a.foo | +| tst5.js:1:1:6:3 | | bar | tst5.js:4:9:4:16 | bar: bar | +| tst5.js:1:1:6:3 | | foo | tst5.js:3:9:3:18 | foo: a.foo | | tst.js:1:1:6:3 | | bar | tst.js:4:9:4:18 | bar: b.bar | | tst.js:1:1:6:3 | | foo | tst.js:3:9:3:18 | foo: a.foo | | umd.js:1:1:14:4 | | bar | umd.js:11:9:11:18 | bar: a.foo | diff --git a/javascript/ql/test/library-tests/AMD/tst5.js b/javascript/ql/test/library-tests/AMD/tst5.js new file mode 100644 index 00000000000..f068dce0746 --- /dev/null +++ b/javascript/ql/test/library-tests/AMD/tst5.js @@ -0,0 +1,6 @@ +define(['./a', './dir/b'], function(a, {bar}, exports) { + return { + foo: a.foo, + bar: bar + }; +}); \ No newline at end of file From c675d72629b5d9f87a6c141aa5fc41c2014f0b0d Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 30 Sep 2020 15:55:26 +0200 Subject: [PATCH 147/411] use Parameter instead of SimpleParameter in remaining route-handler models --- .../ql/src/semmle/javascript/frameworks/Connect.qll | 10 +++++----- .../ql/src/semmle/javascript/frameworks/Firebase.qll | 2 +- .../ql/src/semmle/javascript/frameworks/Hapi.qll | 2 +- javascript/ql/src/semmle/javascript/frameworks/Koa.qll | 2 +- .../ql/src/semmle/javascript/frameworks/NodeJSLib.qll | 4 ++-- .../ql/src/semmle/javascript/frameworks/Restify.qll | 4 ++-- .../javascript/heuristics/AdditionalRouteHandlers.qll | 4 ++-- .../library-tests/frameworks/Express/RouteHandler.qll | 2 +- .../test/library-tests/frameworks/connect/src/test.js | 4 ++++ .../library-tests/frameworks/connect/tests.expected | 8 ++++++++ 10 files changed, 27 insertions(+), 15 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Connect.qll b/javascript/ql/src/semmle/javascript/frameworks/Connect.qll index bd2c17589d8..5d1e36369a7 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Connect.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Connect.qll @@ -30,17 +30,17 @@ module Connect { * * `kind` is one of: "error", "request", "response", "next". */ - abstract SimpleParameter getRouteHandlerParameter(string kind); + abstract Parameter getRouteHandlerParameter(string kind); /** * Gets the parameter of the route handler that contains the request object. */ - SimpleParameter getRequestParameter() { result = getRouteHandlerParameter("request") } + Parameter getRequestParameter() { result = getRouteHandlerParameter("request") } /** * Gets the parameter of the route handler that contains the response object. */ - SimpleParameter getResponseParameter() { result = getRouteHandlerParameter("response") } + Parameter getResponseParameter() { result = getRouteHandlerParameter("response") } } /** @@ -51,7 +51,7 @@ module Connect { StandardRouteHandler() { this = any(RouteSetup setup).getARouteHandler() } - override SimpleParameter getRouteHandlerParameter(string kind) { + override Parameter getRouteHandlerParameter(string kind) { result = getRouteHandlerParameter(astNode, kind) } } @@ -180,7 +180,7 @@ module Connect { HTTP::Servers::StandardRouteHandler, DataFlow::FunctionNode { TrackedRouteHandlerCandidateWithSetup() { this = any(RouteSetup s).getARouteHandler() } - override SimpleParameter getRouteHandlerParameter(string kind) { + override Parameter getRouteHandlerParameter(string kind) { result = getRouteHandlerParameter(astNode, kind) } } diff --git a/javascript/ql/src/semmle/javascript/frameworks/Firebase.qll b/javascript/ql/src/semmle/javascript/frameworks/Firebase.qll index f25d08683c1..9d2c1c6e656 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Firebase.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Firebase.qll @@ -223,7 +223,7 @@ module Firebase { RouteHandler() { this = any(RouteSetup setup).getARouteHandler() } - override SimpleParameter getRouteHandlerParameter(string kind) { + override Parameter getRouteHandlerParameter(string kind) { kind = "request" and result = astNode.getParameter(0) or kind = "response" and result = astNode.getParameter(1) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Hapi.qll b/javascript/ql/src/semmle/javascript/frameworks/Hapi.qll index a04cb79c73b..3d9e08a9ceb 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Hapi.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Hapi.qll @@ -30,7 +30,7 @@ module Hapi { /** * Gets the parameter of the route handler that contains the request object. */ - SimpleParameter getRequestParameter() { result = function.getParameter(0) } + Parameter getRequestParameter() { result = function.getParameter(0) } } /** diff --git a/javascript/ql/src/semmle/javascript/frameworks/Koa.qll b/javascript/ql/src/semmle/javascript/frameworks/Koa.qll index 15378dc507d..1970ab527ef 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Koa.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Koa.qll @@ -47,7 +47,7 @@ module Koa { /** * Gets the parameter of the route handler that contains the context object. */ - SimpleParameter getContextParameter() { result = function.getParameter(0) } + Parameter getContextParameter() { result = function.getParameter(0) } /** * Gets an expression that contains the "context" object of diff --git a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll index 58224c4b51d..f7db714ad89 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll @@ -91,12 +91,12 @@ module NodeJSLib { /** * Gets the parameter of the route handler that contains the request object. */ - SimpleParameter getRequestParameter() { result = getFunction().getParameter(0) } + Parameter getRequestParameter() { result = getFunction().getParameter(0) } /** * Gets the parameter of the route handler that contains the response object. */ - SimpleParameter getResponseParameter() { result = getFunction().getParameter(1) } + Parameter getResponseParameter() { result = getFunction().getParameter(1) } } /** diff --git a/javascript/ql/src/semmle/javascript/frameworks/Restify.qll b/javascript/ql/src/semmle/javascript/frameworks/Restify.qll index 98751256f24..0cd6cbcf436 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Restify.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Restify.qll @@ -30,12 +30,12 @@ module Restify { /** * Gets the parameter of the route handler that contains the request object. */ - SimpleParameter getRequestParameter() { result = function.getParameter(0) } + Parameter getRequestParameter() { result = function.getParameter(0) } /** * Gets the parameter of the route handler that contains the response object. */ - SimpleParameter getResponseParameter() { result = function.getParameter(1) } + Parameter getResponseParameter() { result = function.getParameter(1) } } /** diff --git a/javascript/ql/src/semmle/javascript/heuristics/AdditionalRouteHandlers.qll b/javascript/ql/src/semmle/javascript/heuristics/AdditionalRouteHandlers.qll index aa1a3e859f5..3b9c3b1bb79 100644 --- a/javascript/ql/src/semmle/javascript/heuristics/AdditionalRouteHandlers.qll +++ b/javascript/ql/src/semmle/javascript/heuristics/AdditionalRouteHandlers.qll @@ -29,7 +29,7 @@ private class PromotedExpressCandidate extends Express::RouteHandler, HTTP::Servers::StandardRouteHandler { PromotedExpressCandidate() { this instanceof ConnectExpressShared::RouteHandlerCandidate } - override SimpleParameter getRouteHandlerParameter(string kind) { + override Parameter getRouteHandlerParameter(string kind) { result = ConnectExpressShared::getRouteHandlerParameter(getAstNode(), kind) } } @@ -41,7 +41,7 @@ private class PromotedConnectCandidate extends Connect::RouteHandler, HTTP::Servers::StandardRouteHandler { PromotedConnectCandidate() { this instanceof ConnectExpressShared::RouteHandlerCandidate } - override SimpleParameter getRouteHandlerParameter(string kind) { + override Parameter getRouteHandlerParameter(string kind) { result = ConnectExpressShared::getRouteHandlerParameter(getAstNode(), kind) } } diff --git a/javascript/ql/test/library-tests/frameworks/Express/RouteHandler.qll b/javascript/ql/test/library-tests/frameworks/Express/RouteHandler.qll index 3641504de53..e1afccf99d5 100644 --- a/javascript/ql/test/library-tests/frameworks/Express/RouteHandler.qll +++ b/javascript/ql/test/library-tests/frameworks/Express/RouteHandler.qll @@ -1,7 +1,7 @@ import javascript query predicate test_RouteHandler( - Express::RouteHandler rh, SimpleParameter res0, SimpleParameter res1 + Express::RouteHandler rh, Parameter res0, Parameter res1 ) { res0 = rh.getRequestParameter() and res1 = rh.getResponseParameter() } diff --git a/javascript/ql/test/library-tests/frameworks/connect/src/test.js b/javascript/ql/test/library-tests/frameworks/connect/src/test.js index e4a7bee2fc5..3bdc40a9e9a 100644 --- a/javascript/ql/test/library-tests/frameworks/connect/src/test.js +++ b/javascript/ql/test/library-tests/frameworks/connect/src/test.js @@ -24,3 +24,7 @@ app.use(function(req,res){}) app.use(function (error, req, res, next){ res.setHeader('HEADER2', ''); }); + +app.use(function ({url, query, cookies}, res){ + cookies.get(query.foobar); +}); diff --git a/javascript/ql/test/library-tests/frameworks/connect/tests.expected b/javascript/ql/test/library-tests/frameworks/connect/tests.expected index 78bfe6107e8..474d6aaeb53 100644 --- a/javascript/ql/test/library-tests/frameworks/connect/tests.expected +++ b/javascript/ql/test/library-tests/frameworks/connect/tests.expected @@ -5,6 +5,7 @@ test_RouteSetup | src/test.js:19:1:19:28 | app.use ... res){}) | | src/test.js:19:1:20:29 | app.use ... res){}) | | src/test.js:24:1:26:2 | app.use ... '');\\n}) | +| src/test.js:28:1:30:2 | app.use ... ar);\\n}) | test_RequestInputAccess | src/test.js:8:5:8:26 | req.coo ... ('foo') | cookie | src/test.js:6:9:9:1 | functio ... oo');\\n} | test_RouteHandler_getAResponseHeader @@ -21,6 +22,7 @@ test_ResponseExpr | src/test.js:20:23:20:25 | res | src/test.js:20:10:20:28 | function(req,res){} | | src/test.js:24:31:24:33 | res | src/test.js:24:9:26:1 | functio ... '');\\n} | | src/test.js:25:5:25:7 | res | src/test.js:24:9:26:1 | functio ... '');\\n} | +| src/test.js:28:42:28:44 | res | src/test.js:28:9:30:1 | functio ... bar);\\n} | test_HeaderDefinition | src/test.js:7:5:7:32 | res.set ... 1', '') | src/test.js:6:9:9:1 | functio ... oo');\\n} | | src/test.js:25:5:25:32 | res.set ... 2', '') | src/test.js:24:9:26:1 | functio ... '');\\n} | @@ -31,6 +33,7 @@ test_RouteSetup_getServer | src/test.js:19:1:19:28 | app.use ... res){}) | src/test.js:4:11:4:19 | connect() | | src/test.js:19:1:20:29 | app.use ... res){}) | src/test.js:4:11:4:19 | connect() | | src/test.js:24:1:26:2 | app.use ... '');\\n}) | src/test.js:4:11:4:19 | connect() | +| src/test.js:28:1:30:2 | app.use ... ar);\\n}) | src/test.js:4:11:4:19 | connect() | test_HeaderDefinition_getAHeaderName | src/test.js:7:5:7:32 | res.set ... 1', '') | header1 | | src/test.js:25:5:25:32 | res.set ... 2', '') | header2 | @@ -44,6 +47,7 @@ test_RouteHandler_getAResponseExpr | src/test.js:20:10:20:28 | function(req,res){} | src/test.js:20:23:20:25 | res | | src/test.js:24:9:26:1 | functio ... '');\\n} | src/test.js:24:31:24:33 | res | | src/test.js:24:9:26:1 | functio ... '');\\n} | src/test.js:25:5:25:7 | res | +| src/test.js:28:9:30:1 | functio ... bar);\\n} | src/test.js:28:42:28:44 | res | test_RouteSetup_getARouteHandler | src/test.js:6:1:9:2 | app.use ... o');\\n}) | src/test.js:6:9:9:1 | functio ... oo');\\n} | | src/test.js:12:1:12:42 | app.use ... word')) | src/test.js:12:9:12:41 | basicAu ... sword') | @@ -53,12 +57,14 @@ test_RouteSetup_getARouteHandler | src/test.js:19:1:19:28 | app.use ... res){}) | src/test.js:19:9:19:27 | function(req,res){} | | src/test.js:19:1:20:29 | app.use ... res){}) | src/test.js:20:10:20:28 | function(req,res){} | | src/test.js:24:1:26:2 | app.use ... '');\\n}) | src/test.js:24:9:26:1 | functio ... '');\\n} | +| src/test.js:28:1:30:2 | app.use ... ar);\\n}) | src/test.js:28:9:30:1 | functio ... bar);\\n} | test_RouteHandler | src/test.js:6:9:9:1 | functio ... oo');\\n} | src/test.js:4:11:4:19 | connect() | | src/test.js:15:12:15:32 | functio ... res){} | src/test.js:4:11:4:19 | connect() | | src/test.js:19:9:19:27 | function(req,res){} | src/test.js:4:11:4:19 | connect() | | src/test.js:20:10:20:28 | function(req,res){} | src/test.js:4:11:4:19 | connect() | | src/test.js:24:9:26:1 | functio ... '');\\n} | src/test.js:4:11:4:19 | connect() | +| src/test.js:28:9:30:1 | functio ... bar);\\n} | src/test.js:4:11:4:19 | connect() | test_RequestExpr | src/test.js:6:27:6:29 | req | src/test.js:6:9:9:1 | functio ... oo');\\n} | | src/test.js:8:5:8:7 | req | src/test.js:6:9:9:1 | functio ... oo');\\n} | @@ -66,6 +72,7 @@ test_RequestExpr | src/test.js:19:18:19:20 | req | src/test.js:19:9:19:27 | function(req,res){} | | src/test.js:20:19:20:21 | req | src/test.js:20:10:20:28 | function(req,res){} | | src/test.js:24:26:24:28 | req | src/test.js:24:9:26:1 | functio ... '');\\n} | +| src/test.js:28:19:28:39 | {url, q ... ookies} | src/test.js:28:9:30:1 | functio ... bar);\\n} | test_Credentials | src/test.js:12:19:12:28 | 'username' | user name | | src/test.js:12:31:12:40 | 'password' | password | @@ -76,3 +83,4 @@ test_RouteHandler_getARequestExpr | src/test.js:19:9:19:27 | function(req,res){} | src/test.js:19:18:19:20 | req | | src/test.js:20:10:20:28 | function(req,res){} | src/test.js:20:19:20:21 | req | | src/test.js:24:9:26:1 | functio ... '');\\n} | src/test.js:24:26:24:28 | req | +| src/test.js:28:9:30:1 | functio ... bar);\\n} | src/test.js:28:19:28:39 | {url, q ... ookies} | From 75b9237b81db3de31f4066e548bc505c8efd59c5 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 1 Oct 2020 10:26:34 +0200 Subject: [PATCH 148/411] use Parameter instead of SimpleParameter in the AngularJS model --- .../frameworks/AngularJS/AngularJSCore.qll | 14 +++++++------- .../frameworks/AngularJS/DependencyInjections.qll | 14 +++++++------- .../frameworks/AngularJS/ServiceDefinitions.qll | 6 +++--- .../dependencies/DependencyKinds.expected | 1 + .../AngularJS/dependencies/dependency-kinds.js | 4 ++++ 5 files changed, 22 insertions(+), 17 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll b/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll index 15dfa0c68a3..dbf50cd675e 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll @@ -819,27 +819,27 @@ class LinkFunction extends Function { /** * Gets the scope parameter of this function. */ - SimpleParameter getScopeParameter() { result = getParameter(0) } + Parameter getScopeParameter() { result = getParameter(0) } /** * Gets the element parameter of this function (contains a jqLite-wrapped DOM element). */ - SimpleParameter getElementParameter() { result = getParameter(1) } + Parameter getElementParameter() { result = getParameter(1) } /** * Gets the attributes parameter of this function. */ - SimpleParameter getAttributesParameter() { result = getParameter(2) } + Parameter getAttributesParameter() { result = getParameter(2) } /** * Gets the controller parameter of this function. */ - SimpleParameter getControllerParameter() { result = getParameter(3) } + Parameter getControllerParameter() { result = getParameter(3) } /** * Gets the transclude-function parameter of this function. */ - SimpleParameter getTranscludeFnParameter() { result = getParameter(4) } + Parameter getTranscludeFnParameter() { result = getParameter(4) } } /** @@ -868,7 +868,7 @@ class AngularScope extends TAngularScope { */ Expr getAnAccess() { exists(CustomDirective d | this = d.getAScope() | - exists(SimpleParameter p | + exists(Parameter p | p = d.getController().getDependencyParameter("$scope") or p = d.getALinkFunction().getParameter(0) | @@ -884,7 +884,7 @@ class AngularScope extends TAngularScope { d.hasIsolateScope() and result = d.getMember("scope").asExpr() ) or - exists(DirectiveController c, DOM::ElementDefinition elem, SimpleParameter p | + exists(DirectiveController c, DOM::ElementDefinition elem, Parameter p | c.boundTo(elem) and this.mayApplyTo(elem) and p = c.getFactoryFunction().getDependencyParameter("$scope") and diff --git a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll b/javascript/ql/src/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll index 247b133fdf6..4919490f52d 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll @@ -41,7 +41,7 @@ abstract class DependencyInjection extends DataFlow::ValueNode { */ abstract class InjectableFunction extends DataFlow::ValueNode { /** Gets the parameter corresponding to dependency `name`. */ - abstract SimpleParameter getDependencyParameter(string name); + abstract Parameter getDependencyParameter(string name); /** * Gets the `i`th dependency declaration, which is also named `name`. @@ -67,7 +67,7 @@ abstract class InjectableFunction extends DataFlow::ValueNode { /** * Gets a service corresponding to the dependency-injected `parameter`. */ - ServiceReference getAResolvedDependency(SimpleParameter parameter) { + ServiceReference getAResolvedDependency(Parameter parameter) { exists(string name, InjectableFunctionServiceRequest request | this = request.getAnInjectedFunction() and parameter = getDependencyParameter(name) and @@ -79,7 +79,7 @@ abstract class InjectableFunction extends DataFlow::ValueNode { * Gets a Custom service corresponding to the dependency-injected `parameter`. * (this is a convenience variant of `getAResolvedDependency`) */ - DataFlow::Node getCustomServiceDependency(SimpleParameter parameter) { + DataFlow::Node getCustomServiceDependency(Parameter parameter) { exists(CustomServiceDefinition custom | custom.getServiceReference() = getAResolvedDependency(parameter) and result = custom.getAService() @@ -99,11 +99,11 @@ private class FunctionWithImplicitDependencyAnnotation extends InjectableFunctio not exists(getAPropertyDependencyInjection(astNode)) } - override SimpleParameter getDependencyParameter(string name) { + override Parameter getDependencyParameter(string name) { result = astNode.getParameterByName(name) } - override SimpleParameter getDependencyDeclaration(int i, string name) { + override Parameter getDependencyDeclaration(int i, string name) { result.getName() = name and result = astNode.getParameter(i) } @@ -139,7 +139,7 @@ private class FunctionWithInjectProperty extends InjectableFunction { ) } - override SimpleParameter getDependencyParameter(string name) { + override Parameter getDependencyParameter(string name) { exists(int i | exists(getDependencyDeclaration(i, name)) | result = astNode.getParameter(i)) } @@ -170,7 +170,7 @@ private class FunctionWithExplicitDependencyAnnotation extends InjectableFunctio function.flowsToExpr(astNode.getElement(astNode.getSize() - 1)) } - override SimpleParameter getDependencyParameter(string name) { + override Parameter getDependencyParameter(string name) { exists(int i | astNode.getElement(i).mayHaveStringValue(name) | result = asFunction().getParameter(i) ) diff --git a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll b/javascript/ql/src/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll index 4bc6ef185b5..efd54236029 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll @@ -479,7 +479,7 @@ abstract class ServiceRequest extends Expr { /** * Gets the parameter of this request into which `service` is injected. */ - abstract SimpleParameter getDependencyParameter(ServiceReference service); + abstract Parameter getDependencyParameter(ServiceReference service); } /** @@ -488,7 +488,7 @@ abstract class ServiceRequest extends Expr { private class LinkFunctionWithScopeInjection extends ServiceRequest { LinkFunctionWithScopeInjection() { this instanceof LinkFunction } - override SimpleParameter getDependencyParameter(ServiceReference service) { + override Parameter getDependencyParameter(ServiceReference service) { service instanceof ScopeServiceReference and result = this.(LinkFunction).getScopeParameter() } @@ -521,7 +521,7 @@ class InjectableFunctionServiceRequest extends ServiceRequest { result.isInjectable() } - override SimpleParameter getDependencyParameter(ServiceReference service) { + override Parameter getDependencyParameter(ServiceReference service) { service = injectedFunction.getAResolvedDependency(result) } } diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/dependencies/DependencyKinds.expected b/javascript/ql/test/library-tests/frameworks/AngularJS/dependencies/DependencyKinds.expected index 10f109f316a..e002f6f03ba 100644 --- a/javascript/ql/test/library-tests/frameworks/AngularJS/dependencies/DependencyKinds.expected +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/dependencies/DependencyKinds.expected @@ -34,3 +34,4 @@ | dependency-kinds.js:98:33:98:63 | functio ... ency){} | animationDependency | | dependency-kinds.js:111:17:117:9 | functio ... } | $routeProvider | | dependency-kinds.js:114:33:115:21 | functio ... } | routeControllerDependency | +| dependency-kinds.js:121:14:123:10 | ['modul ... }] | moduleRunService | diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/dependencies/dependency-kinds.js b/javascript/ql/test/library-tests/frameworks/AngularJS/dependencies/dependency-kinds.js index f7607249dcd..f7ef63fa40e 100644 --- a/javascript/ql/test/library-tests/frameworks/AngularJS/dependencies/dependency-kinds.js +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/dependencies/dependency-kinds.js @@ -117,4 +117,8 @@ }) ; + angular.module('myModule', []) + .run(['moduleRunService', function({foo, bar}) { + // ... + }]) })(); From fbd62abd64307acd1e1e3a3eb72335afa4d66a98 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 1 Oct 2020 11:24:54 +0200 Subject: [PATCH 149/411] prevent crash when TemplateLiteral is used in import --- .../js/parser/TypeScriptASTConverter.java | 13 +- .../tests/ts/input/importNonStrings.ts | 3 + .../ts/output/trap/importNonStrings.ts.trap | 252 ++++++++++++++++++ 3 files changed, 267 insertions(+), 1 deletion(-) create mode 100644 javascript/extractor/tests/ts/input/importNonStrings.ts create mode 100644 javascript/extractor/tests/ts/output/trap/importNonStrings.ts.trap diff --git a/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java b/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java index 0e7031c4f9a..d2e5a0448c3 100644 --- a/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java +++ b/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java @@ -1421,8 +1421,19 @@ public class TypeScriptASTConverter { importStart = advance(importStart, m.group(0)); } } + + Node rawPath = convertChild(node, "argument"); + ITypeExpression path; + if (rawPath instanceof ITypeExpression) { + path = (ITypeExpression)rawPath; + } else if (rawPath instanceof TemplateLiteral) { + // this is a type-error, so we just fall back to some behavior that does not crash the extractor. + path = new Literal(rawPath.getLoc(), TokenType.string, ((TemplateLiteral)rawPath).getQuasis().stream().map(q -> q.getRaw()).collect(Collectors.joining(""))); + } else { + throw new ParseError("Unsupported syntax in import", getSourceLocation(node).getStart()); + } + // Find the ending parenthesis in `import(path)` by skipping whitespace after `path`. - ITypeExpression path = convertChild(node, "argument"); String endSrc = loc.getSource().substring(path.getLoc().getEnd().getOffset() - loc.getStart().getOffset()); Matcher m = WHITESPACE_END_PAREN.matcher(endSrc); diff --git a/javascript/extractor/tests/ts/input/importNonStrings.ts b/javascript/extractor/tests/ts/input/importNonStrings.ts new file mode 100644 index 00000000000..6ab15963636 --- /dev/null +++ b/javascript/extractor/tests/ts/input/importNonStrings.ts @@ -0,0 +1,3 @@ +type X = import(3); +type Y = import(`Foo`); +type Z = import(Y); diff --git a/javascript/extractor/tests/ts/output/trap/importNonStrings.ts.trap b/javascript/extractor/tests/ts/output/trap/importNonStrings.ts.trap new file mode 100644 index 00000000000..fdcbc0d00a1 --- /dev/null +++ b/javascript/extractor/tests/ts/output/trap/importNonStrings.ts.trap @@ -0,0 +1,252 @@ +#10000=@"/importNonStrings.ts;sourcefile" +files(#10000,"/importNonStrings.ts","importNonStrings","ts",0) +#10001=@"/;folder" +folders(#10001,"/","") +containerparent(#10001,#10000) +#10002=@"loc,{#10000},0,0,0,0" +locations_default(#10002,#10000,0,0,0,0) +hasLocation(#10000,#10002) +#20000=@"global_scope" +scopes(#20000,0) +#20001=@"script;{#10000},1,1" +#20002=* +lines(#20002,#20001,"type X = import(3);"," +") +#20003=@"loc,{#10000},1,1,1,19" +locations_default(#20003,#10000,1,1,1,19) +hasLocation(#20002,#20003) +#20004=* +lines(#20004,#20001,"type Y = import(`Foo`);"," +") +#20005=@"loc,{#10000},2,1,2,23" +locations_default(#20005,#10000,2,1,2,23) +hasLocation(#20004,#20005) +#20006=* +lines(#20006,#20001,"type Z = import(Y);"," +") +#20007=@"loc,{#10000},3,1,3,19" +locations_default(#20007,#10000,3,1,3,19) +hasLocation(#20006,#20007) +numlines(#20001,3,3,0) +#20008=* +tokeninfo(#20008,7,#20001,0,"type") +#20009=@"loc,{#10000},1,1,1,4" +locations_default(#20009,#10000,1,1,1,4) +hasLocation(#20008,#20009) +#20010=* +tokeninfo(#20010,6,#20001,1,"X") +#20011=@"loc,{#10000},1,6,1,6" +locations_default(#20011,#10000,1,6,1,6) +hasLocation(#20010,#20011) +#20012=* +tokeninfo(#20012,8,#20001,2,"=") +#20013=@"loc,{#10000},1,8,1,8" +locations_default(#20013,#10000,1,8,1,8) +hasLocation(#20012,#20013) +#20014=* +tokeninfo(#20014,7,#20001,3,"import") +#20015=@"loc,{#10000},1,10,1,15" +locations_default(#20015,#10000,1,10,1,15) +hasLocation(#20014,#20015) +#20016=* +tokeninfo(#20016,8,#20001,4,"(") +#20017=@"loc,{#10000},1,16,1,16" +locations_default(#20017,#10000,1,16,1,16) +hasLocation(#20016,#20017) +#20018=* +tokeninfo(#20018,3,#20001,5,"3") +#20019=@"loc,{#10000},1,17,1,17" +locations_default(#20019,#10000,1,17,1,17) +hasLocation(#20018,#20019) +#20020=* +tokeninfo(#20020,8,#20001,6,")") +#20021=@"loc,{#10000},1,18,1,18" +locations_default(#20021,#10000,1,18,1,18) +hasLocation(#20020,#20021) +#20022=* +tokeninfo(#20022,8,#20001,7,";") +#20023=@"loc,{#10000},1,19,1,19" +locations_default(#20023,#10000,1,19,1,19) +hasLocation(#20022,#20023) +#20024=* +tokeninfo(#20024,7,#20001,8,"type") +#20025=@"loc,{#10000},2,1,2,4" +locations_default(#20025,#10000,2,1,2,4) +hasLocation(#20024,#20025) +#20026=* +tokeninfo(#20026,6,#20001,9,"Y") +#20027=@"loc,{#10000},2,6,2,6" +locations_default(#20027,#10000,2,6,2,6) +hasLocation(#20026,#20027) +#20028=* +tokeninfo(#20028,8,#20001,10,"=") +#20029=@"loc,{#10000},2,8,2,8" +locations_default(#20029,#10000,2,8,2,8) +hasLocation(#20028,#20029) +#20030=* +tokeninfo(#20030,7,#20001,11,"import") +#20031=@"loc,{#10000},2,10,2,15" +locations_default(#20031,#10000,2,10,2,15) +hasLocation(#20030,#20031) +#20032=* +tokeninfo(#20032,8,#20001,12,"(") +#20033=@"loc,{#10000},2,16,2,16" +locations_default(#20033,#10000,2,16,2,16) +hasLocation(#20032,#20033) +#20034=* +tokeninfo(#20034,4,#20001,13,"`Foo`") +#20035=@"loc,{#10000},2,17,2,21" +locations_default(#20035,#10000,2,17,2,21) +hasLocation(#20034,#20035) +#20036=* +tokeninfo(#20036,8,#20001,14,")") +#20037=@"loc,{#10000},2,22,2,22" +locations_default(#20037,#10000,2,22,2,22) +hasLocation(#20036,#20037) +#20038=* +tokeninfo(#20038,8,#20001,15,";") +#20039=@"loc,{#10000},2,23,2,23" +locations_default(#20039,#10000,2,23,2,23) +hasLocation(#20038,#20039) +#20040=* +tokeninfo(#20040,7,#20001,16,"type") +#20041=@"loc,{#10000},3,1,3,4" +locations_default(#20041,#10000,3,1,3,4) +hasLocation(#20040,#20041) +#20042=* +tokeninfo(#20042,6,#20001,17,"Z") +#20043=@"loc,{#10000},3,6,3,6" +locations_default(#20043,#10000,3,6,3,6) +hasLocation(#20042,#20043) +#20044=* +tokeninfo(#20044,8,#20001,18,"=") +#20045=@"loc,{#10000},3,8,3,8" +locations_default(#20045,#10000,3,8,3,8) +hasLocation(#20044,#20045) +#20046=* +tokeninfo(#20046,7,#20001,19,"import") +#20047=@"loc,{#10000},3,10,3,15" +locations_default(#20047,#10000,3,10,3,15) +hasLocation(#20046,#20047) +#20048=* +tokeninfo(#20048,8,#20001,20,"(") +#20049=@"loc,{#10000},3,16,3,16" +locations_default(#20049,#10000,3,16,3,16) +hasLocation(#20048,#20049) +#20050=* +tokeninfo(#20050,6,#20001,21,"Y") +#20051=@"loc,{#10000},3,17,3,17" +locations_default(#20051,#10000,3,17,3,17) +hasLocation(#20050,#20051) +#20052=* +tokeninfo(#20052,8,#20001,22,")") +#20053=@"loc,{#10000},3,18,3,18" +locations_default(#20053,#10000,3,18,3,18) +hasLocation(#20052,#20053) +#20054=* +tokeninfo(#20054,8,#20001,23,";") +#20055=@"loc,{#10000},3,19,3,19" +locations_default(#20055,#10000,3,19,3,19) +hasLocation(#20054,#20055) +#20056=* +tokeninfo(#20056,0,#20001,24,"") +#20057=@"loc,{#10000},4,1,4,0" +locations_default(#20057,#10000,4,1,4,0) +hasLocation(#20056,#20057) +toplevels(#20001,0) +#20058=@"loc,{#10000},1,1,4,0" +locations_default(#20058,#10000,1,1,4,0) +hasLocation(#20001,#20058) +#20059=@"local_type_name;{X};{#20000}" +local_type_names(#20059,"X",#20000) +#20060=@"local_type_name;{Y};{#20000}" +local_type_names(#20060,"Y",#20000) +#20061=@"local_type_name;{Z};{#20000}" +local_type_names(#20061,"Z",#20000) +#20062=* +stmts(#20062,35,#20001,0,"type X = import(3);") +hasLocation(#20062,#20003) +stmt_containers(#20062,#20001) +#20063=* +typeexprs(#20063,1,#20062,0,"X") +hasLocation(#20063,#20011) +enclosing_stmt(#20063,#20062) +expr_containers(#20063,#20001) +literals("X","X",#20063) +typedecl(#20063,#20059) +#20064=* +typeexprs(#20064,30,#20062,1,"import(3)") +#20065=@"loc,{#10000},1,10,1,18" +locations_default(#20065,#10000,1,10,1,18) +hasLocation(#20064,#20065) +enclosing_stmt(#20064,#20062) +expr_containers(#20064,#20001) +#20066=* +typeexprs(#20066,4,#20064,0,"3") +hasLocation(#20066,#20019) +enclosing_stmt(#20066,#20062) +expr_containers(#20066,#20001) +literals("3","3",#20066) +#20067=* +stmts(#20067,35,#20001,1,"type Y ... `Foo`);") +hasLocation(#20067,#20005) +stmt_containers(#20067,#20001) +#20068=* +typeexprs(#20068,1,#20067,0,"Y") +hasLocation(#20068,#20027) +enclosing_stmt(#20068,#20067) +expr_containers(#20068,#20001) +literals("Y","Y",#20068) +typedecl(#20068,#20060) +#20069=* +typeexprs(#20069,30,#20067,1,"import(`Foo`)") +#20070=@"loc,{#10000},2,10,2,22" +locations_default(#20070,#10000,2,10,2,22) +hasLocation(#20069,#20070) +enclosing_stmt(#20069,#20067) +expr_containers(#20069,#20001) +#20071=* +typeexprs(#20071,3,#20069,0,"`Foo`") +hasLocation(#20071,#20035) +enclosing_stmt(#20071,#20067) +expr_containers(#20071,#20001) +literals("Foo","`Foo`",#20071) +#20072=* +stmts(#20072,35,#20001,2,"type Z = import(Y);") +hasLocation(#20072,#20007) +stmt_containers(#20072,#20001) +#20073=* +typeexprs(#20073,1,#20072,0,"Z") +hasLocation(#20073,#20043) +enclosing_stmt(#20073,#20072) +expr_containers(#20073,#20001) +literals("Z","Z",#20073) +typedecl(#20073,#20061) +#20074=* +typeexprs(#20074,30,#20072,1,"import(Y)") +#20075=@"loc,{#10000},3,10,3,18" +locations_default(#20075,#10000,3,10,3,18) +hasLocation(#20074,#20075) +enclosing_stmt(#20074,#20072) +expr_containers(#20074,#20001) +#20076=* +typeexprs(#20076,0,#20074,0,"Y") +hasLocation(#20076,#20051) +enclosing_stmt(#20076,#20072) +expr_containers(#20076,#20001) +literals("Y","Y",#20076) +typebind(#20076,#20060) +#20077=* +entry_cfg_node(#20077,#20001) +#20078=@"loc,{#10000},1,1,1,0" +locations_default(#20078,#10000,1,1,1,0) +hasLocation(#20077,#20078) +#20079=* +exit_cfg_node(#20079,#20001) +hasLocation(#20079,#20057) +successor(#20072,#20079) +successor(#20067,#20072) +successor(#20062,#20067) +successor(#20077,#20062) +numlines(#10000,3,3,0) +filetype(#10000,"typescript") From 9b3509f0ba20c4ad0ffd31dd8f88be4b2e55e874 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 1 Oct 2020 12:51:44 +0200 Subject: [PATCH 150/411] Python: Highlight problem with missing use-use flow --- .../CWE-078/CommandInjection.expected | 8 ++++++ .../CWE-078/command_injection.py | 26 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected b/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected index 665617aa713..288508c23d4 100644 --- a/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected +++ b/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected @@ -3,6 +3,8 @@ edges | command_injection.py:17:13:17:24 | ControlFlowNode for Attribute | command_injection.py:19:22:19:34 | ControlFlowNode for BinaryExpr | | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | +| command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | command_injection.py:39:15:39:21 | ControlFlowNode for command | +| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:53:15:53:21 | ControlFlowNode for command | nodes | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | @@ -12,8 +14,14 @@ nodes | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd | | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| command_injection.py:39:15:39:21 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | +| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| command_injection.py:53:15:53:21 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | #select | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:19:22:19:34 | ControlFlowNode for BinaryExpr | command_injection.py:17:13:17:24 | ControlFlowNode for Attribute | command_injection.py:19:22:19:34 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:17:13:17:24 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | This command depends on $@. | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:39:15:39:21 | ControlFlowNode for command | command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | command_injection.py:39:15:39:21 | ControlFlowNode for command | This command depends on $@. | command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:53:15:53:21 | ControlFlowNode for command | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:53:15:53:21 | ControlFlowNode for command | This command depends on $@. | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | a user-provided value | diff --git a/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/command_injection.py b/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/command_injection.py index ce533b5e1ee..d92690c57fe 100644 --- a/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/command_injection.py +++ b/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/command_injection.py @@ -31,5 +31,31 @@ def others(): # Don't let files be `; rm -rf /` os.popen("ls " + files) +@app.route("/multiple") +def multiple(): + command = request.args.get('command', '') + # We should mark flow to both calls here, which conflicts with removing flow out of + # a sink due to use-use flow. + os.system(command) + os.system(command) + + +@app.route("/not-into-sink-impl") +def not_into_sink_impl(): + """When there is flow to a sink such as `os.popen(cmd)`, we don't want to highlight that there is also + flow through the actual `popen` function to the internal call to `subprocess.Popen` -- we would usually + see that flow since we extract the `os.py` file from the standard library. + + os.popen implementation: + https://github.com/python/cpython/blob/fa7ce080175f65d678a7d5756c94f82887fc9803/Lib/os.py#L974 + """ + command = request.args.get('command', '') + os.system(command) + os.popen(command) + subprocess.call(command) + subprocess.check_call(command) + subprocess.run(command) + + # TODO: popen2 module for Python 2 only https://devdocs.io/python~2.7/library/popen2 # (deprecated since Python 2.6, but still functional in Python 2.7.17) From 3247b300aeea54f6a167f488559634485ecd30b1 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 1 Oct 2020 12:55:11 +0200 Subject: [PATCH 151/411] Python: Fix problem with missing use-use flow --- .../CWE-078/CommandInjection.ql | 35 ++++++++++++------- .../CWE-078/CommandInjection.expected | 15 ++++++++ 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/python/ql/src/experimental/Security-new-dataflow/CWE-078/CommandInjection.ql b/python/ql/src/experimental/Security-new-dataflow/CWE-078/CommandInjection.ql index 6e241a81a6a..1f826acb932 100755 --- a/python/ql/src/experimental/Security-new-dataflow/CWE-078/CommandInjection.ql +++ b/python/ql/src/experimental/Security-new-dataflow/CWE-078/CommandInjection.ql @@ -27,19 +27,30 @@ class CommandInjectionConfiguration extends TaintTracking::Configuration { override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } override predicate isSink(DataFlow::Node sink) { - sink = any(SystemCommandExecution e).getCommand() + sink = any(SystemCommandExecution e).getCommand() and + // Since the implementation of os.popen looks like + // ```py + // def popen(cmd, mode="r", buffering=-1): + // ... + // proc = subprocess.Popen(cmd, ...) + // ``` + // any time we would report flow to the `os.popen` sink, we can ALSO report the flow + // from the `cmd` parameter to the `subprocess.Popen` sink -- obviously we don't want + // that. + // + // However, simply removing taint edges out of a sink is not a good enough solution, + // since we would only flag one of the `os.system` calls in the following example due + // to use-use flow + // ```py + // os.system(cmd) + // os.system(cmd) + // ``` + // + // Best solution I could come up with is to exclude all sinks inside the standard + // library -- this does have a downside: If we have overlooked a function in the + // standard library that internally runs a command, we no longer give an alert :| + not sink.getLocation().getFile().inStdlib() } - - // Since the implementation of os.popen looks like - // ```py - // def popen(cmd, mode="r", buffering=-1): - // ... - // proc = subprocess.Popen(cmd, ...) - // ``` - // any time we would report flow to the `os.popen` sink, we can ALSO report the flow - // from the `cmd` parameter to the `subprocess.Popen` sink -- obviously we don't want - // that, so to prevent that we remove any taint edges out of a sink. - override predicate isSanitizerOut(DataFlow::Node node) { isSink(node) } } from CommandInjectionConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected b/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected index 288508c23d4..03748127520 100644 --- a/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected +++ b/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/CommandInjection.expected @@ -4,7 +4,12 @@ edges | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | | command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | command_injection.py:39:15:39:21 | ControlFlowNode for command | +| command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | command_injection.py:40:15:40:21 | ControlFlowNode for command | | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:53:15:53:21 | ControlFlowNode for command | +| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:54:14:54:20 | ControlFlowNode for command | +| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:55:21:55:27 | ControlFlowNode for command | +| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:56:27:56:33 | ControlFlowNode for command | +| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:57:20:57:26 | ControlFlowNode for command | nodes | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | @@ -16,12 +21,22 @@ nodes | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | command_injection.py:39:15:39:21 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | +| command_injection.py:40:15:40:21 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | command_injection.py:53:15:53:21 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | +| command_injection.py:54:14:54:20 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | +| command_injection.py:55:21:55:27 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | +| command_injection.py:56:27:56:33 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | +| command_injection.py:57:20:57:26 | ControlFlowNode for command | semmle.label | ControlFlowNode for command | #select | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:19:22:19:34 | ControlFlowNode for BinaryExpr | command_injection.py:17:13:17:24 | ControlFlowNode for Attribute | command_injection.py:19:22:19:34 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:17:13:17:24 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | This command depends on $@. | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:39:15:39:21 | ControlFlowNode for command | command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | command_injection.py:39:15:39:21 | ControlFlowNode for command | This command depends on $@. | command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:40:15:40:21 | ControlFlowNode for command | command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | command_injection.py:40:15:40:21 | ControlFlowNode for command | This command depends on $@. | command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | a user-provided value | | command_injection.py:53:15:53:21 | ControlFlowNode for command | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:53:15:53:21 | ControlFlowNode for command | This command depends on $@. | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:54:14:54:20 | ControlFlowNode for command | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:54:14:54:20 | ControlFlowNode for command | This command depends on $@. | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:55:21:55:27 | ControlFlowNode for command | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:55:21:55:27 | ControlFlowNode for command | This command depends on $@. | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:56:27:56:33 | ControlFlowNode for command | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:56:27:56:33 | ControlFlowNode for command | This command depends on $@. | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | a user-provided value | +| command_injection.py:57:20:57:26 | ControlFlowNode for command | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:57:20:57:26 | ControlFlowNode for command | This command depends on $@. | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | a user-provided value | From 4dec2171dabf38374b13d25c755e48bc7bb1e841 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 1 Oct 2020 13:21:56 +0200 Subject: [PATCH 152/411] add http request server data as a RemoteFlowSource --- .../src/semmle/javascript/frameworks/HTTP.qll | 17 +++++++++++++++++ .../frameworks/NodeJSLib/src/http.js | 6 ++++++ .../frameworks/NodeJSLib/tests.expected | 15 +++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll b/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll index b3faa55501a..044ad8b0cd7 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll @@ -470,6 +470,23 @@ module HTTP { */ abstract Expr getServer(); } + + /** + * A parameter containing data received by a NodeJS HTTP server. + * E.g. `chunk` in: `http.createServer().on('request', (req, res) => req.on("data", (chunk) => ...))`. + */ + private class ServerRequestDataEvent extends RemoteFlowSource, DataFlow::ParameterNode { + RequestSource req; + + ServerRequestDataEvent() { + exists(DataFlow::MethodCallNode mcn | mcn = req.ref().getAMethodCall(EventEmitter::on()) | + mcn.getArgument(0).mayHaveStringValue("data") and + this = mcn.getABoundCallbackParameter(1, 0) + ) + } + + override string getSourceType() { result = "NodeJS HTTP server data event" } + } } /** diff --git a/javascript/ql/test/library-tests/frameworks/NodeJSLib/src/http.js b/javascript/ql/test/library-tests/frameworks/NodeJSLib/src/http.js index 11a52f701f9..12dc11efcaf 100644 --- a/javascript/ql/test/library-tests/frameworks/NodeJSLib/src/http.js +++ b/javascript/ql/test/library-tests/frameworks/NodeJSLib/src/http.js @@ -68,3 +68,9 @@ function getArrowHandler() { return (req,res) => f(); } http.createServer(getArrowHandler()); + +http.createServer(function (req, res) { + req.on("data", chunk => { // RemoteFlowSource + res.send(chunk); + }) +}); \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected b/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected index 6234075f5f1..2e048dc43b8 100644 --- a/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected +++ b/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected @@ -8,6 +8,7 @@ test_isCreateServer | src/http.js:60:1:60:33 | createS ... res){}) | | src/http.js:62:1:65:2 | http.cr ... 2");\\n}) | | src/http.js:70:1:70:36 | http.cr ... dler()) | +| src/http.js:72:1:76:2 | http.cr ... })\\n}) | | src/https.js:4:14:10:2 | https.c ... foo;\\n}) | | src/https.js:12:1:16:2 | https.c ... r");\\n}) | | src/indirect2.js:18:14:18:35 | http.cr ... er(get) | @@ -53,6 +54,8 @@ test_ResponseExpr | src/http.js:63:3:63:5 | res | src/http.js:62:19:65:1 | functio ... r2");\\n} | | src/http.js:64:3:64:5 | res | src/http.js:62:19:65:1 | functio ... r2");\\n} | | src/http.js:68:17:68:19 | res | src/http.js:68:12:68:27 | (req,res) => f() | +| src/http.js:72:34:72:36 | res | src/http.js:72:19:76:1 | functio ... \\n })\\n} | +| src/http.js:74:5:74:7 | res | src/http.js:72:19:76:1 | functio ... \\n })\\n} | | src/https.js:4:47:4:49 | res | src/https.js:4:33:10:1 | functio ... .foo;\\n} | | src/https.js:7:3:7:5 | res | src/https.js:4:33:10:1 | functio ... .foo;\\n} | | src/https.js:12:34:12:36 | res | src/https.js:12:20:16:1 | functio ... ar");\\n} | @@ -87,6 +90,7 @@ test_RouteSetup_getServer | src/http.js:60:1:60:33 | createS ... res){}) | src/http.js:60:1:60:33 | createS ... res){}) | | src/http.js:62:1:65:2 | http.cr ... 2");\\n}) | src/http.js:62:1:65:2 | http.cr ... 2");\\n}) | | src/http.js:70:1:70:36 | http.cr ... dler()) | src/http.js:70:1:70:36 | http.cr ... dler()) | +| src/http.js:72:1:76:2 | http.cr ... })\\n}) | src/http.js:72:1:76:2 | http.cr ... })\\n}) | | src/https.js:4:14:10:2 | https.c ... foo;\\n}) | src/https.js:4:14:10:2 | https.c ... foo;\\n}) | | src/https.js:12:1:16:2 | https.c ... r");\\n}) | src/https.js:12:1:16:2 | https.c ... r");\\n}) | | src/indirect2.js:18:14:18:35 | http.cr ... er(get) | src/indirect2.js:18:14:18:35 | http.cr ... er(get) | @@ -112,6 +116,7 @@ test_ServerDefinition | src/http.js:60:1:60:33 | createS ... res){}) | | src/http.js:62:1:65:2 | http.cr ... 2");\\n}) | | src/http.js:70:1:70:36 | http.cr ... dler()) | +| src/http.js:72:1:76:2 | http.cr ... })\\n}) | | src/https.js:4:14:10:2 | https.c ... foo;\\n}) | | src/https.js:12:1:16:2 | https.c ... r");\\n}) | | src/indirect2.js:18:14:18:35 | http.cr ... er(get) | @@ -142,6 +147,8 @@ test_RouteHandler_getAResponseExpr | src/http.js:62:19:65:1 | functio ... r2");\\n} | src/http.js:63:3:63:5 | res | | src/http.js:62:19:65:1 | functio ... r2");\\n} | src/http.js:64:3:64:5 | res | | src/http.js:68:12:68:27 | (req,res) => f() | src/http.js:68:17:68:19 | res | +| src/http.js:72:19:76:1 | functio ... \\n })\\n} | src/http.js:72:34:72:36 | res | +| src/http.js:72:19:76:1 | functio ... \\n })\\n} | src/http.js:74:5:74:7 | res | | src/https.js:4:33:10:1 | functio ... .foo;\\n} | src/https.js:4:47:4:49 | res | | src/https.js:4:33:10:1 | functio ... .foo;\\n} | src/https.js:7:3:7:5 | res | | src/https.js:12:20:16:1 | functio ... ar");\\n} | src/https.js:12:34:12:36 | res | @@ -169,6 +176,7 @@ test_ServerDefinition_getARouteHandler | src/http.js:60:1:60:33 | createS ... res){}) | src/http.js:60:14:60:32 | function(req,res){} | | src/http.js:62:1:65:2 | http.cr ... 2");\\n}) | src/http.js:62:19:65:1 | functio ... r2");\\n} | | src/http.js:70:1:70:36 | http.cr ... dler()) | src/http.js:68:12:68:27 | (req,res) => f() | +| src/http.js:72:1:76:2 | http.cr ... })\\n}) | src/http.js:72:19:76:1 | functio ... \\n })\\n} | | src/https.js:4:14:10:2 | https.c ... foo;\\n}) | src/https.js:4:33:10:1 | functio ... .foo;\\n} | | src/https.js:12:1:16:2 | https.c ... r");\\n}) | src/https.js:12:20:16:1 | functio ... ar");\\n} | | src/indirect2.js:18:14:18:35 | http.cr ... er(get) | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | @@ -198,6 +206,7 @@ test_RouteSetup_getARouteHandler | src/http.js:70:1:70:36 | http.cr ... dler()) | src/http.js:67:1:69:1 | return of function getArrowHandler | | src/http.js:70:1:70:36 | http.cr ... dler()) | src/http.js:68:12:68:27 | (req,res) => f() | | src/http.js:70:1:70:36 | http.cr ... dler()) | src/http.js:70:19:70:35 | getArrowHandler() | +| src/http.js:72:1:76:2 | http.cr ... })\\n}) | src/http.js:72:19:76:1 | functio ... \\n })\\n} | | src/https.js:4:14:10:2 | https.c ... foo;\\n}) | src/https.js:4:33:10:1 | functio ... .foo;\\n} | | src/https.js:12:1:16:2 | https.c ... r");\\n}) | src/https.js:12:20:16:1 | functio ... ar");\\n} | | src/indirect2.js:18:14:18:35 | http.cr ... er(get) | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | @@ -224,6 +233,7 @@ test_RemoteFlowSources | src/http.js:30:28:30:32 | chunk | | src/http.js:40:23:40:30 | authInfo | | src/http.js:45:23:45:27 | error | +| src/http.js:73:18:73:22 | chunk | | src/https.js:6:26:6:32 | req.url | | src/https.js:8:3:8:20 | req.headers.cookie | | src/https.js:9:3:9:17 | req.headers.foo | @@ -238,6 +248,7 @@ test_RouteHandler | src/http.js:60:14:60:32 | function(req,res){} | src/http.js:60:1:60:33 | createS ... res){}) | | src/http.js:62:19:65:1 | functio ... r2");\\n} | src/http.js:62:1:65:2 | http.cr ... 2");\\n}) | | src/http.js:68:12:68:27 | (req,res) => f() | src/http.js:70:1:70:36 | http.cr ... dler()) | +| src/http.js:72:19:76:1 | functio ... \\n })\\n} | src/http.js:72:1:76:2 | http.cr ... })\\n}) | | src/https.js:4:33:10:1 | functio ... .foo;\\n} | src/https.js:4:14:10:2 | https.c ... foo;\\n}) | | src/https.js:12:20:16:1 | functio ... ar");\\n} | src/https.js:12:1:16:2 | https.c ... r");\\n}) | | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:18:14:18:35 | http.cr ... er(get) | @@ -259,6 +270,8 @@ test_RequestExpr | src/http.js:62:28:62:30 | req | src/http.js:62:19:65:1 | functio ... r2");\\n} | | src/http.js:63:17:63:19 | req | src/http.js:62:19:65:1 | functio ... r2");\\n} | | src/http.js:68:13:68:15 | req | src/http.js:68:12:68:27 | (req,res) => f() | +| src/http.js:72:29:72:31 | req | src/http.js:72:19:76:1 | functio ... \\n })\\n} | +| src/http.js:73:3:73:5 | req | src/http.js:72:19:76:1 | functio ... \\n })\\n} | | src/https.js:4:42:4:44 | req | src/https.js:4:33:10:1 | functio ... .foo;\\n} | | src/https.js:6:26:6:28 | req | src/https.js:4:33:10:1 | functio ... .foo;\\n} | | src/https.js:8:3:8:5 | req | src/https.js:4:33:10:1 | functio ... .foo;\\n} | @@ -296,6 +309,8 @@ test_RouteHandler_getARequestExpr | src/http.js:62:19:65:1 | functio ... r2");\\n} | src/http.js:62:28:62:30 | req | | src/http.js:62:19:65:1 | functio ... r2");\\n} | src/http.js:63:17:63:19 | req | | src/http.js:68:12:68:27 | (req,res) => f() | src/http.js:68:13:68:15 | req | +| src/http.js:72:19:76:1 | functio ... \\n })\\n} | src/http.js:72:29:72:31 | req | +| src/http.js:72:19:76:1 | functio ... \\n })\\n} | src/http.js:73:3:73:5 | req | | src/https.js:4:33:10:1 | functio ... .foo;\\n} | src/https.js:4:42:4:44 | req | | src/https.js:4:33:10:1 | functio ... .foo;\\n} | src/https.js:6:26:6:28 | req | | src/https.js:4:33:10:1 | functio ... .foo;\\n} | src/https.js:8:3:8:5 | req | From 18f7f2b559cbe1fadf4cf748582b78fc483b7bf6 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 1 Oct 2020 13:49:31 +0200 Subject: [PATCH 153/411] autoformat --- .../ql/test/library-tests/frameworks/Express/RouteHandler.qll | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/javascript/ql/test/library-tests/frameworks/Express/RouteHandler.qll b/javascript/ql/test/library-tests/frameworks/Express/RouteHandler.qll index e1afccf99d5..4873bcf2d99 100644 --- a/javascript/ql/test/library-tests/frameworks/Express/RouteHandler.qll +++ b/javascript/ql/test/library-tests/frameworks/Express/RouteHandler.qll @@ -1,7 +1,5 @@ import javascript -query predicate test_RouteHandler( - Express::RouteHandler rh, Parameter res0, Parameter res1 -) { +query predicate test_RouteHandler(Express::RouteHandler rh, Parameter res0, Parameter res1) { res0 = rh.getRequestParameter() and res1 = rh.getResponseParameter() } From 578ea1ae43950adea8082fd7bb4eac65463b5d62 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 1 Oct 2020 13:09:52 +0100 Subject: [PATCH 154/411] Fix OWASP broken links --- cpp/ql/src/Security/CWE/CWE-022/TaintedPath.qhelp | 2 +- csharp/ql/src/Security Features/CWE-022/TaintedPath.qhelp | 2 +- csharp/ql/src/Security Features/CWE-022/ZipSlip.qhelp | 2 +- csharp/ql/src/Security Features/CWE-643/XPathInjection.qhelp | 2 +- csharp/ql/src/experimental/CWE-099/TaintedWebClient.qhelp | 2 +- java/ql/src/Security/CWE/CWE-022/TaintedPath.qhelp | 2 +- java/ql/src/Security/CWE/CWE-022/ZipSlip.qhelp | 2 +- java/ql/src/Security/CWE/CWE-209/StackTraceExposure.qhelp | 2 +- .../src/experimental/Security/CWE/CWE-643/XPathInjection.qhelp | 2 +- javascript/ql/src/Security/CWE-022/TaintedPath.qhelp | 2 +- javascript/ql/src/Security/CWE-022/ZipSlip.qhelp | 2 +- javascript/ql/src/Security/CWE-209/StackTraceExposure.qhelp | 2 +- javascript/ql/src/Security/CWE-643/XpathInjection.qhelp | 2 +- python/ql/src/Security/CWE-022/PathInjection.qhelp | 2 +- python/ql/src/Security/CWE-022/TarSlip.qhelp | 2 +- python/ql/src/Security/CWE-209/StackTraceExposure.qhelp | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.qhelp b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.qhelp index d7432369f0e..eba2ede58f5 100644 --- a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.qhelp +++ b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.qhelp @@ -39,7 +39,7 @@ access all the system's passwords.

  • OWASP: -Path Traversal. +Path Traversal.
  • diff --git a/csharp/ql/src/Security Features/CWE-022/TaintedPath.qhelp b/csharp/ql/src/Security Features/CWE-022/TaintedPath.qhelp index fec61771992..e838d8c56a4 100644 --- a/csharp/ql/src/Security Features/CWE-022/TaintedPath.qhelp +++ b/csharp/ql/src/Security Features/CWE-022/TaintedPath.qhelp @@ -41,7 +41,7 @@ sent back to the user, giving them access to all the system's passwords.

  • OWASP: -Path Traversal. +Path Traversal.
  • diff --git a/csharp/ql/src/Security Features/CWE-022/ZipSlip.qhelp b/csharp/ql/src/Security Features/CWE-022/ZipSlip.qhelp index 9ee9ce6d0a1..bee5d819836 100644 --- a/csharp/ql/src/Security Features/CWE-022/ZipSlip.qhelp +++ b/csharp/ql/src/Security Features/CWE-022/ZipSlip.qhelp @@ -71,7 +71,7 @@ Snyk:
  • OWASP: -Path Traversal. +Path Traversal.
  • diff --git a/csharp/ql/src/Security Features/CWE-643/XPathInjection.qhelp b/csharp/ql/src/Security Features/CWE-643/XPathInjection.qhelp index 7241f6f97c4..cf50b4ee174 100644 --- a/csharp/ql/src/Security Features/CWE-643/XPathInjection.qhelp +++ b/csharp/ql/src/Security Features/CWE-643/XPathInjection.qhelp @@ -42,7 +42,7 @@ variables in an XsltArgumentList. -
  • OWASP: Testing for XPath Injection.
  • +
  • OWASP: Testing for XPath Injection.
  • OWASP: XPath Injection.
  • MSDN: User Defined Functions and Variables.
  • diff --git a/csharp/ql/src/experimental/CWE-099/TaintedWebClient.qhelp b/csharp/ql/src/experimental/CWE-099/TaintedWebClient.qhelp index 77721307eda..d7f195905a8 100644 --- a/csharp/ql/src/experimental/CWE-099/TaintedWebClient.qhelp +++ b/csharp/ql/src/experimental/CWE-099/TaintedWebClient.qhelp @@ -51,7 +51,7 @@ system's passwords.

  • OWASP: -Path Traversal. +Path Traversal.
  • diff --git a/java/ql/src/Security/CWE/CWE-022/TaintedPath.qhelp b/java/ql/src/Security/CWE/CWE-022/TaintedPath.qhelp index 29bab0e42d2..b32d3c65039 100644 --- a/java/ql/src/Security/CWE/CWE-022/TaintedPath.qhelp +++ b/java/ql/src/Security/CWE/CWE-022/TaintedPath.qhelp @@ -39,7 +39,7 @@ giving them access to all the system's passwords.

  • OWASP: -Path Traversal. +Path Traversal.
  • diff --git a/java/ql/src/Security/CWE/CWE-022/ZipSlip.qhelp b/java/ql/src/Security/CWE/CWE-022/ZipSlip.qhelp index 97c389508b3..adea1b89c49 100644 --- a/java/ql/src/Security/CWE/CWE-022/ZipSlip.qhelp +++ b/java/ql/src/Security/CWE/CWE-022/ZipSlip.qhelp @@ -63,7 +63,7 @@ Snyk:
  • OWASP: -Path Traversal. +Path Traversal.
  • diff --git a/java/ql/src/Security/CWE/CWE-209/StackTraceExposure.qhelp b/java/ql/src/Security/CWE/CWE-209/StackTraceExposure.qhelp index b772b7e3c57..d0d7e1b0e50 100644 --- a/java/ql/src/Security/CWE/CWE-209/StackTraceExposure.qhelp +++ b/java/ql/src/Security/CWE/CWE-209/StackTraceExposure.qhelp @@ -38,7 +38,7 @@ information.

    -
  • OWASP: Information Leak.
  • +
  • OWASP: Improper Error Handling.
  • CERT Java Coding Standard: ERR01-J. diff --git a/java/ql/src/experimental/Security/CWE/CWE-643/XPathInjection.qhelp b/java/ql/src/experimental/Security/CWE/CWE-643/XPathInjection.qhelp index 555a6f7fb95..91d110b80aa 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-643/XPathInjection.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-643/XPathInjection.qhelp @@ -38,7 +38,7 @@ The fifth example is a dom4j XPath injection example. -
  • OWASP: Testing for XPath Injection.
  • +
  • OWASP: Testing for XPath Injection.
  • OWASP: XPath Injection.
  • diff --git a/javascript/ql/src/Security/CWE-022/TaintedPath.qhelp b/javascript/ql/src/Security/CWE-022/TaintedPath.qhelp index b9cb415a018..8dab2fcc4fc 100644 --- a/javascript/ql/src/Security/CWE-022/TaintedPath.qhelp +++ b/javascript/ql/src/Security/CWE-022/TaintedPath.qhelp @@ -50,7 +50,7 @@ system's passwords. -
  • OWASP: Path Traversal.
  • +
  • OWASP: Path Traversal.
  • npm: sanitize-filename package.
  • diff --git a/javascript/ql/src/Security/CWE-022/ZipSlip.qhelp b/javascript/ql/src/Security/CWE-022/ZipSlip.qhelp index 7a361947216..d9dc0fb67a8 100644 --- a/javascript/ql/src/Security/CWE-022/ZipSlip.qhelp +++ b/javascript/ql/src/Security/CWE-022/ZipSlip.qhelp @@ -60,7 +60,7 @@ Snyk:
  • OWASP: -Path Traversal. +Path Traversal.
  • diff --git a/javascript/ql/src/Security/CWE-209/StackTraceExposure.qhelp b/javascript/ql/src/Security/CWE-209/StackTraceExposure.qhelp index ea37581a799..20a9c65cbc7 100644 --- a/javascript/ql/src/Security/CWE-209/StackTraceExposure.qhelp +++ b/javascript/ql/src/Security/CWE-209/StackTraceExposure.qhelp @@ -52,6 +52,6 @@ will not see the information: -
  • OWASP: Information Leak.
  • +
  • OWASP: Improper Error Handling.
  • diff --git a/javascript/ql/src/Security/CWE-643/XpathInjection.qhelp b/javascript/ql/src/Security/CWE-643/XpathInjection.qhelp index 346b213d180..3378b9b4078 100644 --- a/javascript/ql/src/Security/CWE-643/XpathInjection.qhelp +++ b/javascript/ql/src/Security/CWE-643/XpathInjection.qhelp @@ -33,7 +33,7 @@ by xpath: -
  • OWASP: Testing for XPath Injection.
  • +
  • OWASP: Testing for XPath Injection.
  • OWASP: XPath Injection.
  • npm: xpath.
  • diff --git a/python/ql/src/Security/CWE-022/PathInjection.qhelp b/python/ql/src/Security/CWE-022/PathInjection.qhelp index 0abc683b4ca..200a4e78f98 100644 --- a/python/ql/src/Security/CWE-022/PathInjection.qhelp +++ b/python/ql/src/Security/CWE-022/PathInjection.qhelp @@ -55,7 +55,7 @@ known prefix. This ensures that regardless of the user input, the resulting path -
  • OWASP: Path Traversal.
  • +
  • OWASP: Path Traversal.
  • npm: werkzeug.utils.secure_filename.
  • diff --git a/python/ql/src/Security/CWE-022/TarSlip.qhelp b/python/ql/src/Security/CWE-022/TarSlip.qhelp index a2fbc5dfdc6..07bab31a6ce 100644 --- a/python/ql/src/Security/CWE-022/TarSlip.qhelp +++ b/python/ql/src/Security/CWE-022/TarSlip.qhelp @@ -60,7 +60,7 @@ Snyk:
  • OWASP: -Path Traversal. +Path Traversal.
  • Python Library Reference: diff --git a/python/ql/src/Security/CWE-209/StackTraceExposure.qhelp b/python/ql/src/Security/CWE-209/StackTraceExposure.qhelp index 86ecdbdc0d8..6670aa08284 100644 --- a/python/ql/src/Security/CWE-209/StackTraceExposure.qhelp +++ b/python/ql/src/Security/CWE-209/StackTraceExposure.qhelp @@ -47,6 +47,6 @@ log, but remote users will not see the information. -
  • OWASP: Information Leak.
  • +
  • OWASP: Improper Error Handling.
  • From 5ce0974eb2d4501fcd4eff872416f033bd1319de Mon Sep 17 00:00:00 2001 From: Alexander Eyers-Taylor Date: Thu, 1 Oct 2020 14:40:45 +0100 Subject: [PATCH 155/411] Fix the name of the vscode extension recommendation The name is case sensitive so it didn't work before. --- .vscode/extensions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 8465a7c2f86..8eec4887a1e 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -3,8 +3,8 @@ // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp // List of extensions which should be recommended for users of this workspace. "recommendations": [ - "github.vscode-codeql" + "GitHub.vscode-codeql" ], // List of extensions recommended by VS Code that should not be recommended for users of this workspace. "unwantedRecommendations": [] -} \ No newline at end of file +} From ca4781eb78e572fd9e18d8e3bb7c2155d2fd7f37 Mon Sep 17 00:00:00 2001 From: Joe Date: Thu, 1 Oct 2020 15:58:32 +0100 Subject: [PATCH 156/411] Java: Remove use of StringFormatMethod in TaintTrackingUtils --- .../dataflow/internal/TaintTrackingUtil.qll | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index f9da6342b35..8ce4ca66ec6 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -13,7 +13,6 @@ private import semmle.code.java.frameworks.spring.SpringHttp private import semmle.code.java.Maps private import semmle.code.java.dataflow.internal.ContainerFlow private import semmle.code.java.frameworks.jackson.JacksonSerializability -private import semmle.code.java.StringFormat /** * Holds if taint can flow from `src` to `sink` in zero or more @@ -391,10 +390,8 @@ private predicate taintPreservingQualifierToMethod(Method m) { ) ) or - m instanceof StringFormatMethod - or m.getDeclaringType() instanceof TypeFormatter and - m.hasName("out") + m.hasName(["format", "out"]) } private class StringReplaceMethod extends Method { @@ -454,10 +451,10 @@ private predicate argToMethodStep(Expr tracked, MethodAccess sink) { */ private predicate taintPreservingArgumentToMethod(Method method) { method.getDeclaringType() instanceof TypeString and - method.hasName("join") + (method.hasName("format") or method.hasName("formatted") or method.hasName("join")) or - method instanceof StringFormatMethod and - not method.getDeclaringType().hasQualifiedName("java.io", "Console") + method.getDeclaringType() instanceof TypeFormatter and + method.hasName("format") } /** @@ -637,9 +634,8 @@ private predicate argToQualifierStep(Expr tracked, Expr sink) { sink = ma.getQualifier() ) or - exists(Method m, MethodAccess ma | - taintPreservingArgumentToQualifier(m) and - ma.getMethod() = m and + exists(MethodAccess ma | + taintPreservingArgumentToQualifier(ma.getMethod()) and tracked = ma.getAnArgument() and sink = ma.getQualifier() ) @@ -649,9 +645,8 @@ private predicate argToQualifierStep(Expr tracked, Expr sink) { * Holds if `method` is a method that transfers taint from any of its arguments to its qualifier. */ private predicate taintPreservingArgumentToQualifier(Method method) { - method instanceof StringFormatMethod and - not method.getDeclaringType() instanceof TypeString and - not method.getDeclaringType().hasQualifiedName("java.io", "Console") + method.getDeclaringType() instanceof TypeFormatter and + method.hasName("format") } /** From 75f4051cb5bcc9302fcffe0486d635c6dd843d6c Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Thu, 1 Oct 2020 17:21:53 +0200 Subject: [PATCH 157/411] Python: Fix `hasLocationInfo` for packages --- python/ql/src/semmle/python/Files.qll | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/python/ql/src/semmle/python/Files.qll b/python/ql/src/semmle/python/Files.qll index 22aad6ad0a3..ef6484fbdc6 100644 --- a/python/ql/src/semmle/python/Files.qll +++ b/python/ql/src/semmle/python/Files.qll @@ -415,6 +415,12 @@ class Location extends @location { locations_ast(this, m, startline, startcolumn, endline, endcolumn) ) ) + or + // Packages have no suitable filepath, so we use just the path instead. + exists(Module m | not exists(m.getFile()) | + filepath = m.getPath().getAbsolutePath() and + locations_ast(this, m, startline, startcolumn, endline, endcolumn) + ) } } From ad9f306352625297ef678ef2e742ec04b95dc9e1 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 1 Oct 2020 17:38:09 +0100 Subject: [PATCH 158/411] C++: Model taint flow only when the second component of a pair would be tainted. --- .../cpp/models/implementations/StdPair.qll | 9 ++-- .../dataflow/taint-tests/localTaint.expected | 50 ------------------- .../dataflow/taint-tests/map.cpp | 34 ++++++------- .../dataflow/taint-tests/taint.expected | 47 ----------------- .../dataflow/taint-tests/test_diff.expected | 44 ---------------- .../dataflow/taint-tests/test_ir.expected | 21 -------- 6 files changed, 22 insertions(+), 183 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll index 8b80d9d224d..7b17ec05800 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll @@ -20,8 +20,9 @@ class StdPairConstructor extends Constructor, TaintFunction { } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // taint flow from any parameter of a value type to the qualifier - input.isParameterDeref(getAValueTypeParameterIndex()) and + // taint flow from second parameter of a value type to the qualifier + getAValueTypeParameterIndex() = 1 and + input.isParameterDeref(1) and ( output.isReturnValue() // TODO: this is only needed for AST data flow, which treats constructors as returning the new object or @@ -37,8 +38,8 @@ class StdMakePair extends TaintFunction { StdMakePair() { this.hasQualifiedName("std", "make_pair") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // taint flow from any parameter to the returned object - input.isParameterDeref([0, 1]) and + // taint flow from first parameter to the returned object + input.isParameterDeref(1) and output.isReturnValue() } } 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 7ec322ae15b..d719c453705 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -429,7 +429,6 @@ | map.cpp:31:7:31:7 | c [post update] | map.cpp:32:7:32:7 | c | | | map.cpp:31:7:31:7 | c [post update] | map.cpp:33:7:33:7 | c | | | map.cpp:32:7:32:7 | c [post update] | map.cpp:33:7:33:7 | c | | -| map.cpp:35:30:35:34 | 123 | map.cpp:35:30:35:42 | call to pair | TAINT | | map.cpp:35:30:35:42 | call to pair | map.cpp:36:7:36:7 | d | | | map.cpp:35:30:35:42 | call to pair | map.cpp:37:7:37:7 | d | | | map.cpp:35:30:35:42 | call to pair | map.cpp:38:7:38:7 | d | | @@ -437,7 +436,6 @@ | map.cpp:36:7:36:7 | d [post update] | map.cpp:37:7:37:7 | d | | | map.cpp:36:7:36:7 | d [post update] | map.cpp:38:7:38:7 | d | | | map.cpp:37:7:37:7 | d [post update] | map.cpp:38:7:38:7 | d | | -| map.cpp:40:30:40:35 | call to source | map.cpp:40:30:40:45 | call to pair | TAINT | | map.cpp:40:30:40:45 | call to pair | map.cpp:41:7:41:7 | e | | | map.cpp:40:30:40:45 | call to pair | map.cpp:42:7:42:7 | e | | | map.cpp:40:30:40:45 | call to pair | map.cpp:43:7:43:7 | e | | @@ -445,7 +443,6 @@ | map.cpp:41:7:41:7 | e [post update] | map.cpp:42:7:42:7 | e | | | map.cpp:41:7:41:7 | e [post update] | map.cpp:43:7:43:7 | e | | | map.cpp:42:7:42:7 | e [post update] | map.cpp:43:7:43:7 | e | | -| map.cpp:45:30:45:34 | 123 | map.cpp:45:30:45:45 | call to pair | TAINT | | map.cpp:45:30:45:45 | call to pair | map.cpp:46:7:46:7 | f | | | map.cpp:45:30:45:45 | call to pair | map.cpp:47:7:47:7 | f | | | map.cpp:45:30:45:45 | call to pair | map.cpp:48:7:48:7 | f | | @@ -472,25 +469,21 @@ | map.cpp:57:7:57:7 | h [post update] | map.cpp:58:7:58:7 | h | | | map.cpp:57:7:57:7 | h [post update] | map.cpp:59:7:59:7 | h | | | map.cpp:58:7:58:7 | h [post update] | map.cpp:59:7:59:7 | h | | -| map.cpp:61:30:61:34 | 123 | map.cpp:61:30:61:42 | call to pair | TAINT | | map.cpp:61:30:61:42 | call to pair | map.cpp:65:3:65:3 | i | | | map.cpp:61:30:61:42 | call to pair | map.cpp:67:7:67:7 | i | | | map.cpp:61:30:61:42 | call to pair | map.cpp:68:7:68:7 | i | | | map.cpp:61:30:61:42 | call to pair | map.cpp:69:7:69:7 | i | | | map.cpp:61:37:61:41 | 456 | map.cpp:61:30:61:42 | call to pair | TAINT | -| map.cpp:62:30:62:34 | 123 | map.cpp:62:30:62:45 | call to pair | TAINT | | map.cpp:62:30:62:45 | call to pair | map.cpp:65:10:65:10 | j | | | map.cpp:62:30:62:45 | call to pair | map.cpp:70:7:70:7 | j | | | map.cpp:62:30:62:45 | call to pair | map.cpp:71:7:71:7 | j | | | map.cpp:62:30:62:45 | call to pair | map.cpp:72:7:72:7 | j | | | map.cpp:62:37:62:42 | call to source | map.cpp:62:30:62:45 | call to pair | TAINT | -| map.cpp:63:30:63:34 | 123 | map.cpp:63:30:63:45 | call to pair | TAINT | | map.cpp:63:30:63:45 | call to pair | map.cpp:66:2:66:2 | k | | | map.cpp:63:30:63:45 | call to pair | map.cpp:73:7:73:7 | k | | | map.cpp:63:30:63:45 | call to pair | map.cpp:74:7:74:7 | k | | | map.cpp:63:30:63:45 | call to pair | map.cpp:75:7:75:7 | k | | | map.cpp:63:37:63:42 | call to source | map.cpp:63:30:63:45 | call to pair | TAINT | -| map.cpp:64:30:64:34 | 123 | map.cpp:64:30:64:42 | call to pair | TAINT | | map.cpp:64:30:64:42 | call to pair | map.cpp:66:9:66:9 | l | | | map.cpp:64:30:64:42 | call to pair | map.cpp:76:7:76:7 | l | | | map.cpp:64:30:64:42 | call to pair | map.cpp:77:7:77:7 | l | | @@ -525,25 +518,16 @@ | map.cpp:76:7:76:7 | l [post update] | map.cpp:78:7:78:7 | l | | | map.cpp:77:7:77:7 | l [post update] | map.cpp:78:7:78:7 | l | | | map.cpp:80:7:80:15 | call to make_pair | map.cpp:80:7:80:29 | call to pair | TAINT | -| map.cpp:80:17:80:21 | 123 | map.cpp:80:7:80:15 | call to make_pair | TAINT | | map.cpp:80:24:80:28 | 456 | map.cpp:80:7:80:15 | call to make_pair | TAINT | -| map.cpp:81:17:81:21 | 123 | map.cpp:81:7:81:15 | call to make_pair | TAINT | | map.cpp:81:24:81:28 | 456 | map.cpp:81:7:81:15 | call to make_pair | TAINT | -| map.cpp:82:17:82:21 | 123 | map.cpp:82:7:82:15 | call to make_pair | TAINT | | map.cpp:82:24:82:28 | 456 | map.cpp:82:7:82:15 | call to make_pair | TAINT | | map.cpp:83:7:83:15 | call to make_pair | map.cpp:83:7:83:32 | call to pair | TAINT | -| map.cpp:83:17:83:22 | call to source | map.cpp:83:7:83:15 | call to make_pair | TAINT | | map.cpp:83:27:83:31 | 456 | map.cpp:83:7:83:15 | call to make_pair | TAINT | -| map.cpp:84:17:84:22 | call to source | map.cpp:84:7:84:15 | call to make_pair | TAINT | | map.cpp:84:27:84:31 | 456 | map.cpp:84:7:84:15 | call to make_pair | TAINT | -| map.cpp:85:17:85:22 | call to source | map.cpp:85:7:85:15 | call to make_pair | TAINT | | map.cpp:85:27:85:31 | 456 | map.cpp:85:7:85:15 | call to make_pair | TAINT | | map.cpp:86:7:86:15 | call to make_pair | map.cpp:86:7:86:32 | call to pair | TAINT | -| map.cpp:86:17:86:21 | 123 | map.cpp:86:7:86:15 | call to make_pair | TAINT | | map.cpp:86:24:86:29 | call to source | map.cpp:86:7:86:15 | call to make_pair | TAINT | -| map.cpp:87:17:87:21 | 123 | map.cpp:87:7:87:15 | call to make_pair | TAINT | | map.cpp:87:24:87:29 | call to source | map.cpp:87:7:87:15 | call to make_pair | TAINT | -| map.cpp:88:17:88:21 | 123 | map.cpp:88:7:88:15 | call to make_pair | TAINT | | map.cpp:88:24:88:29 | call to source | map.cpp:88:7:88:15 | call to make_pair | TAINT | | map.cpp:91:6:91:14 | call to make_pair | map.cpp:91:6:91:49 | call to pair | TAINT | | map.cpp:91:6:91:49 | call to pair | map.cpp:91:2:91:49 | ... = ... | | @@ -552,8 +536,6 @@ | map.cpp:91:6:91:49 | call to pair | map.cpp:94:7:94:7 | m | | | map.cpp:91:6:91:49 | call to pair | map.cpp:95:7:95:7 | m | | | map.cpp:91:6:91:49 | call to pair | map.cpp:96:7:96:7 | m | | -| map.cpp:91:16:91:24 | call to make_pair | map.cpp:91:6:91:14 | call to make_pair | TAINT | -| map.cpp:91:26:91:30 | 123 | map.cpp:91:16:91:24 | call to make_pair | TAINT | | map.cpp:91:33:91:38 | call to source | map.cpp:91:16:91:24 | call to make_pair | TAINT | | map.cpp:91:44:91:48 | 789 | map.cpp:91:6:91:14 | call to make_pair | TAINT | | map.cpp:92:7:92:7 | m | map.cpp:92:7:92:7 | call to pair | TAINT | @@ -616,7 +598,6 @@ | map.cpp:104:17:104:30 | call to make_pair | map.cpp:104:17:104:44 | call to pair | TAINT | | map.cpp:104:17:104:44 | call to pair | map.cpp:104:7:104:8 | ref arg m1 | TAINT | | map.cpp:104:17:104:44 | call to pair | map.cpp:104:10:104:15 | call to insert | TAINT | -| map.cpp:104:32:104:36 | abc | map.cpp:104:17:104:30 | call to make_pair | TAINT | | map.cpp:104:39:104:43 | def | map.cpp:104:17:104:30 | call to make_pair | TAINT | | map.cpp:104:47:104:51 | first | map.cpp:104:7:104:51 | call to iterator | | | map.cpp:105:7:105:8 | ref arg m2 | map.cpp:111:7:111:8 | m2 | | @@ -637,7 +618,6 @@ | map.cpp:105:17:105:30 | call to make_pair | map.cpp:105:17:105:47 | call to pair | TAINT | | map.cpp:105:17:105:47 | call to pair | map.cpp:105:7:105:8 | ref arg m2 | TAINT | | map.cpp:105:17:105:47 | call to pair | map.cpp:105:10:105:15 | call to insert | TAINT | -| map.cpp:105:32:105:36 | abc | map.cpp:105:17:105:30 | call to make_pair | TAINT | | map.cpp:105:39:105:44 | call to source | map.cpp:105:17:105:30 | call to make_pair | TAINT | | map.cpp:105:50:105:54 | first | map.cpp:105:7:105:54 | call to iterator | | | map.cpp:106:7:106:8 | ref arg m3 | map.cpp:112:7:112:8 | m3 | | @@ -649,7 +629,6 @@ | map.cpp:106:17:106:30 | call to make_pair | map.cpp:106:17:106:47 | call to pair | TAINT | | map.cpp:106:17:106:47 | call to pair | map.cpp:106:7:106:8 | ref arg m3 | TAINT | | map.cpp:106:17:106:47 | call to pair | map.cpp:106:10:106:15 | call to insert | TAINT | -| map.cpp:106:32:106:37 | call to source | map.cpp:106:17:106:30 | call to make_pair | TAINT | | map.cpp:106:42:106:46 | def | map.cpp:106:17:106:30 | call to make_pair | TAINT | | map.cpp:106:50:106:54 | first | map.cpp:106:7:106:54 | call to iterator | | | map.cpp:107:7:107:8 | ref arg m4 | map.cpp:113:7:113:8 | m4 | | @@ -666,7 +645,6 @@ | map.cpp:107:29:107:70 | call to pair | map.cpp:107:7:107:8 | ref arg m4 | TAINT | | map.cpp:107:29:107:70 | call to pair | map.cpp:107:10:107:15 | call to insert | TAINT | | map.cpp:107:29:107:70 | call to pair | map.cpp:107:29:107:70 | call to pair | TAINT | -| map.cpp:107:55:107:59 | abc | map.cpp:107:29:107:70 | call to pair | TAINT | | map.cpp:107:62:107:67 | call to source | map.cpp:107:29:107:70 | call to pair | TAINT | | map.cpp:108:7:108:8 | ref arg m5 | map.cpp:114:7:114:8 | m5 | | | map.cpp:108:7:108:8 | ref arg m5 | map.cpp:120:7:120:8 | m5 | | @@ -914,7 +892,6 @@ | map.cpp:175:13:175:26 | call to make_pair | map.cpp:175:13:175:36 | call to pair | TAINT | | map.cpp:175:13:175:36 | call to pair | map.cpp:175:2:175:4 | ref arg m14 | TAINT | | map.cpp:175:13:175:36 | call to pair | map.cpp:175:6:175:11 | call to insert | TAINT | -| map.cpp:175:28:175:30 | a | map.cpp:175:13:175:26 | call to make_pair | TAINT | | map.cpp:175:33:175:35 | a | map.cpp:175:13:175:26 | call to make_pair | TAINT | | map.cpp:176:2:176:4 | ref arg m14 | map.cpp:177:2:177:4 | m14 | | | map.cpp:176:2:176:4 | ref arg m14 | map.cpp:178:2:178:4 | m14 | | @@ -922,20 +899,17 @@ | map.cpp:176:13:176:26 | call to make_pair | map.cpp:176:13:176:41 | call to pair | TAINT | | map.cpp:176:13:176:41 | call to pair | map.cpp:176:2:176:4 | ref arg m14 | TAINT | | map.cpp:176:13:176:41 | call to pair | map.cpp:176:6:176:11 | call to insert | TAINT | -| map.cpp:176:28:176:30 | b | map.cpp:176:13:176:26 | call to make_pair | TAINT | | map.cpp:176:33:176:38 | call to source | map.cpp:176:13:176:26 | call to make_pair | TAINT | | map.cpp:177:2:177:4 | ref arg m14 | map.cpp:178:2:178:4 | m14 | | | map.cpp:177:2:177:4 | ref arg m14 | map.cpp:249:1:249:1 | m14 | | | map.cpp:177:13:177:26 | call to make_pair | map.cpp:177:13:177:41 | call to pair | TAINT | | map.cpp:177:13:177:41 | call to pair | map.cpp:177:2:177:4 | ref arg m14 | TAINT | | map.cpp:177:13:177:41 | call to pair | map.cpp:177:6:177:11 | call to insert | TAINT | -| map.cpp:177:28:177:30 | c | map.cpp:177:13:177:26 | call to make_pair | TAINT | | map.cpp:177:33:177:38 | call to source | map.cpp:177:13:177:26 | call to make_pair | TAINT | | map.cpp:178:2:178:4 | ref arg m14 | map.cpp:249:1:249:1 | m14 | | | map.cpp:178:13:178:26 | call to make_pair | map.cpp:178:13:178:36 | call to pair | TAINT | | map.cpp:178:13:178:36 | call to pair | map.cpp:178:2:178:4 | ref arg m14 | TAINT | | map.cpp:178:13:178:36 | call to pair | map.cpp:178:6:178:11 | call to insert | TAINT | -| map.cpp:178:28:178:30 | d | map.cpp:178:13:178:26 | call to make_pair | TAINT | | map.cpp:178:33:178:35 | d | map.cpp:178:13:178:26 | call to make_pair | TAINT | | map.cpp:179:7:179:8 | ref arg m2 | map.cpp:180:7:180:8 | m2 | | | map.cpp:179:7:179:8 | ref arg m2 | map.cpp:181:7:181:8 | m2 | | @@ -991,7 +965,6 @@ | map.cpp:188:13:188:57 | call to pair | map.cpp:188:2:188:4 | ref arg m15 | TAINT | | map.cpp:188:13:188:57 | call to pair | map.cpp:188:6:188:11 | call to insert | TAINT | | map.cpp:188:13:188:57 | call to pair | map.cpp:188:13:188:57 | call to pair | TAINT | -| map.cpp:188:39:188:44 | call to source | map.cpp:188:13:188:57 | call to pair | TAINT | | map.cpp:188:49:188:54 | call to source | map.cpp:188:13:188:57 | call to pair | TAINT | | map.cpp:189:2:189:4 | ref arg m18 | map.cpp:193:7:193:9 | m18 | | | map.cpp:189:2:189:4 | ref arg m18 | map.cpp:195:11:195:13 | m18 | | @@ -1001,7 +974,6 @@ | map.cpp:189:13:189:57 | call to pair | map.cpp:189:2:189:4 | ref arg m18 | TAINT | | map.cpp:189:13:189:57 | call to pair | map.cpp:189:6:189:11 | call to insert | TAINT | | map.cpp:189:13:189:57 | call to pair | map.cpp:189:13:189:57 | call to pair | TAINT | -| map.cpp:189:39:189:44 | call to source | map.cpp:189:13:189:57 | call to pair | TAINT | | map.cpp:189:49:189:54 | call to source | map.cpp:189:13:189:57 | call to pair | TAINT | | map.cpp:190:7:190:9 | m15 | map.cpp:190:7:190:9 | call to map | | | map.cpp:191:7:191:9 | m16 | map.cpp:191:7:191:9 | call to map | | @@ -1049,7 +1021,6 @@ | map.cpp:203:13:203:57 | call to pair | map.cpp:203:2:203:4 | ref arg m19 | TAINT | | map.cpp:203:13:203:57 | call to pair | map.cpp:203:6:203:11 | call to insert | TAINT | | map.cpp:203:13:203:57 | call to pair | map.cpp:203:13:203:57 | call to pair | TAINT | -| map.cpp:203:39:203:44 | call to source | map.cpp:203:13:203:57 | call to pair | TAINT | | map.cpp:203:49:203:54 | call to source | map.cpp:203:13:203:57 | call to pair | TAINT | | map.cpp:204:2:204:4 | ref arg m20 | map.cpp:208:7:208:9 | m20 | | | map.cpp:204:2:204:4 | ref arg m20 | map.cpp:214:7:214:9 | m20 | | @@ -1057,7 +1028,6 @@ | map.cpp:204:13:204:51 | call to pair | map.cpp:204:2:204:4 | ref arg m20 | TAINT | | map.cpp:204:13:204:51 | call to pair | map.cpp:204:6:204:11 | call to insert | TAINT | | map.cpp:204:13:204:51 | call to pair | map.cpp:204:13:204:51 | call to pair | TAINT | -| map.cpp:204:39:204:43 | abc | map.cpp:204:13:204:51 | call to pair | TAINT | | map.cpp:204:46:204:50 | def | map.cpp:204:13:204:51 | call to pair | TAINT | | map.cpp:205:2:205:4 | ref arg m21 | map.cpp:209:7:209:9 | m21 | | | map.cpp:205:2:205:4 | ref arg m21 | map.cpp:215:7:215:9 | m21 | | @@ -1065,7 +1035,6 @@ | map.cpp:205:13:205:51 | call to pair | map.cpp:205:2:205:4 | ref arg m21 | TAINT | | map.cpp:205:13:205:51 | call to pair | map.cpp:205:6:205:11 | call to insert | TAINT | | map.cpp:205:13:205:51 | call to pair | map.cpp:205:13:205:51 | call to pair | TAINT | -| map.cpp:205:39:205:43 | abc | map.cpp:205:13:205:51 | call to pair | TAINT | | map.cpp:205:46:205:50 | def | map.cpp:205:13:205:51 | call to pair | TAINT | | map.cpp:206:2:206:4 | ref arg m22 | map.cpp:210:7:210:9 | m22 | | | map.cpp:206:2:206:4 | ref arg m22 | map.cpp:216:7:216:9 | m22 | | @@ -1073,7 +1042,6 @@ | map.cpp:206:13:206:57 | call to pair | map.cpp:206:2:206:4 | ref arg m22 | TAINT | | map.cpp:206:13:206:57 | call to pair | map.cpp:206:6:206:11 | call to insert | TAINT | | map.cpp:206:13:206:57 | call to pair | map.cpp:206:13:206:57 | call to pair | TAINT | -| map.cpp:206:39:206:44 | call to source | map.cpp:206:13:206:57 | call to pair | TAINT | | map.cpp:206:49:206:54 | call to source | map.cpp:206:13:206:57 | call to pair | TAINT | | map.cpp:207:7:207:9 | m19 | map.cpp:207:7:207:9 | call to map | | | map.cpp:208:7:208:9 | m20 | map.cpp:208:7:208:9 | call to map | | @@ -1107,7 +1075,6 @@ | map.cpp:220:13:220:57 | call to pair | map.cpp:220:2:220:4 | ref arg m23 | TAINT | | map.cpp:220:13:220:57 | call to pair | map.cpp:220:6:220:11 | call to insert | TAINT | | map.cpp:220:13:220:57 | call to pair | map.cpp:220:13:220:57 | call to pair | TAINT | -| map.cpp:220:39:220:44 | call to source | map.cpp:220:13:220:57 | call to pair | TAINT | | map.cpp:220:49:220:54 | call to source | map.cpp:220:13:220:57 | call to pair | TAINT | | map.cpp:221:2:221:4 | ref arg m23 | map.cpp:222:7:222:9 | m23 | | | map.cpp:221:2:221:4 | ref arg m23 | map.cpp:223:7:223:9 | m23 | | @@ -1119,7 +1086,6 @@ | map.cpp:221:13:221:57 | call to pair | map.cpp:221:2:221:4 | ref arg m23 | TAINT | | map.cpp:221:13:221:57 | call to pair | map.cpp:221:6:221:11 | call to insert | TAINT | | map.cpp:221:13:221:57 | call to pair | map.cpp:221:13:221:57 | call to pair | TAINT | -| map.cpp:221:39:221:44 | call to source | map.cpp:221:13:221:57 | call to pair | TAINT | | map.cpp:221:49:221:54 | call to source | map.cpp:221:13:221:57 | call to pair | TAINT | | map.cpp:222:7:222:9 | m23 | map.cpp:222:7:222:9 | call to map | | | map.cpp:223:7:223:9 | m23 | map.cpp:223:11:223:15 | call to erase | TAINT | @@ -1278,7 +1244,6 @@ | map.cpp:256:17:256:30 | call to make_pair | map.cpp:256:17:256:44 | call to pair | TAINT | | map.cpp:256:17:256:44 | call to pair | map.cpp:256:7:256:8 | ref arg m1 | TAINT | | map.cpp:256:17:256:44 | call to pair | map.cpp:256:10:256:15 | call to insert | TAINT | -| map.cpp:256:32:256:36 | abc | map.cpp:256:17:256:30 | call to make_pair | TAINT | | map.cpp:256:39:256:43 | def | map.cpp:256:17:256:30 | call to make_pair | TAINT | | map.cpp:256:47:256:51 | first | map.cpp:256:7:256:51 | call to iterator | | | map.cpp:257:7:257:8 | ref arg m2 | map.cpp:263:7:263:8 | m2 | | @@ -1296,7 +1261,6 @@ | map.cpp:257:17:257:30 | call to make_pair | map.cpp:257:17:257:47 | call to pair | TAINT | | map.cpp:257:17:257:47 | call to pair | map.cpp:257:7:257:8 | ref arg m2 | TAINT | | map.cpp:257:17:257:47 | call to pair | map.cpp:257:10:257:15 | call to insert | TAINT | -| map.cpp:257:32:257:36 | abc | map.cpp:257:17:257:30 | call to make_pair | TAINT | | map.cpp:257:39:257:44 | call to source | map.cpp:257:17:257:30 | call to make_pair | TAINT | | map.cpp:257:50:257:54 | first | map.cpp:257:7:257:54 | call to iterator | | | map.cpp:258:7:258:8 | ref arg m3 | map.cpp:264:7:264:8 | m3 | | @@ -1308,7 +1272,6 @@ | map.cpp:258:17:258:30 | call to make_pair | map.cpp:258:17:258:47 | call to pair | TAINT | | map.cpp:258:17:258:47 | call to pair | map.cpp:258:7:258:8 | ref arg m3 | TAINT | | map.cpp:258:17:258:47 | call to pair | map.cpp:258:10:258:15 | call to insert | TAINT | -| map.cpp:258:32:258:37 | call to source | map.cpp:258:17:258:30 | call to make_pair | TAINT | | map.cpp:258:42:258:46 | def | map.cpp:258:17:258:30 | call to make_pair | TAINT | | map.cpp:258:50:258:54 | first | map.cpp:258:7:258:54 | call to iterator | | | map.cpp:259:7:259:8 | ref arg m4 | map.cpp:265:7:265:8 | m4 | | @@ -1325,7 +1288,6 @@ | map.cpp:259:29:259:70 | call to pair | map.cpp:259:7:259:8 | ref arg m4 | TAINT | | map.cpp:259:29:259:70 | call to pair | map.cpp:259:10:259:15 | call to insert | TAINT | | map.cpp:259:29:259:70 | call to pair | map.cpp:259:29:259:70 | call to pair | TAINT | -| map.cpp:259:55:259:59 | abc | map.cpp:259:29:259:70 | call to pair | TAINT | | map.cpp:259:62:259:67 | call to source | map.cpp:259:29:259:70 | call to pair | TAINT | | map.cpp:260:7:260:8 | ref arg m5 | map.cpp:266:7:266:8 | m5 | | | map.cpp:260:7:260:8 | ref arg m5 | map.cpp:272:7:272:8 | m5 | | @@ -1561,7 +1523,6 @@ | map.cpp:327:13:327:26 | call to make_pair | map.cpp:327:13:327:36 | call to pair | TAINT | | map.cpp:327:13:327:36 | call to pair | map.cpp:327:2:327:4 | ref arg m14 | TAINT | | map.cpp:327:13:327:36 | call to pair | map.cpp:327:6:327:11 | call to insert | TAINT | -| map.cpp:327:28:327:30 | a | map.cpp:327:13:327:26 | call to make_pair | TAINT | | map.cpp:327:33:327:35 | a | map.cpp:327:13:327:26 | call to make_pair | TAINT | | map.cpp:328:2:328:4 | ref arg m14 | map.cpp:329:2:329:4 | m14 | | | map.cpp:328:2:328:4 | ref arg m14 | map.cpp:330:2:330:4 | m14 | | @@ -1569,20 +1530,17 @@ | map.cpp:328:13:328:26 | call to make_pair | map.cpp:328:13:328:41 | call to pair | TAINT | | map.cpp:328:13:328:41 | call to pair | map.cpp:328:2:328:4 | ref arg m14 | TAINT | | map.cpp:328:13:328:41 | call to pair | map.cpp:328:6:328:11 | call to insert | TAINT | -| map.cpp:328:28:328:30 | b | map.cpp:328:13:328:26 | call to make_pair | TAINT | | map.cpp:328:33:328:38 | call to source | map.cpp:328:13:328:26 | call to make_pair | TAINT | | map.cpp:329:2:329:4 | ref arg m14 | map.cpp:330:2:330:4 | m14 | | | map.cpp:329:2:329:4 | ref arg m14 | map.cpp:398:1:398:1 | m14 | | | map.cpp:329:13:329:26 | call to make_pair | map.cpp:329:13:329:41 | call to pair | TAINT | | map.cpp:329:13:329:41 | call to pair | map.cpp:329:2:329:4 | ref arg m14 | TAINT | | map.cpp:329:13:329:41 | call to pair | map.cpp:329:6:329:11 | call to insert | TAINT | -| map.cpp:329:28:329:30 | c | map.cpp:329:13:329:26 | call to make_pair | TAINT | | map.cpp:329:33:329:38 | call to source | map.cpp:329:13:329:26 | call to make_pair | TAINT | | map.cpp:330:2:330:4 | ref arg m14 | map.cpp:398:1:398:1 | m14 | | | map.cpp:330:13:330:26 | call to make_pair | map.cpp:330:13:330:36 | call to pair | TAINT | | map.cpp:330:13:330:36 | call to pair | map.cpp:330:2:330:4 | ref arg m14 | TAINT | | map.cpp:330:13:330:36 | call to pair | map.cpp:330:6:330:11 | call to insert | TAINT | -| map.cpp:330:28:330:30 | d | map.cpp:330:13:330:26 | call to make_pair | TAINT | | map.cpp:330:33:330:35 | d | map.cpp:330:13:330:26 | call to make_pair | TAINT | | map.cpp:331:7:331:8 | ref arg m2 | map.cpp:332:7:332:8 | m2 | | | map.cpp:331:7:331:8 | ref arg m2 | map.cpp:333:7:333:8 | m2 | | @@ -1623,7 +1581,6 @@ | map.cpp:337:13:337:57 | call to pair | map.cpp:337:2:337:4 | ref arg m15 | TAINT | | map.cpp:337:13:337:57 | call to pair | map.cpp:337:6:337:11 | call to insert | TAINT | | map.cpp:337:13:337:57 | call to pair | map.cpp:337:13:337:57 | call to pair | TAINT | -| map.cpp:337:39:337:44 | call to source | map.cpp:337:13:337:57 | call to pair | TAINT | | map.cpp:337:49:337:54 | call to source | map.cpp:337:13:337:57 | call to pair | TAINT | | map.cpp:338:2:338:4 | ref arg m18 | map.cpp:342:7:342:9 | m18 | | | map.cpp:338:2:338:4 | ref arg m18 | map.cpp:344:11:344:13 | m18 | | @@ -1633,7 +1590,6 @@ | map.cpp:338:13:338:57 | call to pair | map.cpp:338:2:338:4 | ref arg m18 | TAINT | | map.cpp:338:13:338:57 | call to pair | map.cpp:338:6:338:11 | call to insert | TAINT | | map.cpp:338:13:338:57 | call to pair | map.cpp:338:13:338:57 | call to pair | TAINT | -| map.cpp:338:39:338:44 | call to source | map.cpp:338:13:338:57 | call to pair | TAINT | | map.cpp:338:49:338:54 | call to source | map.cpp:338:13:338:57 | call to pair | TAINT | | map.cpp:339:7:339:9 | m15 | map.cpp:339:7:339:9 | call to unordered_map | | | map.cpp:340:7:340:9 | m16 | map.cpp:340:7:340:9 | call to unordered_map | | @@ -1681,7 +1637,6 @@ | map.cpp:352:13:352:57 | call to pair | map.cpp:352:2:352:4 | ref arg m19 | TAINT | | map.cpp:352:13:352:57 | call to pair | map.cpp:352:6:352:11 | call to insert | TAINT | | map.cpp:352:13:352:57 | call to pair | map.cpp:352:13:352:57 | call to pair | TAINT | -| map.cpp:352:39:352:44 | call to source | map.cpp:352:13:352:57 | call to pair | TAINT | | map.cpp:352:49:352:54 | call to source | map.cpp:352:13:352:57 | call to pair | TAINT | | map.cpp:353:2:353:4 | ref arg m20 | map.cpp:357:7:357:9 | m20 | | | map.cpp:353:2:353:4 | ref arg m20 | map.cpp:363:7:363:9 | m20 | | @@ -1689,7 +1644,6 @@ | map.cpp:353:13:353:51 | call to pair | map.cpp:353:2:353:4 | ref arg m20 | TAINT | | map.cpp:353:13:353:51 | call to pair | map.cpp:353:6:353:11 | call to insert | TAINT | | map.cpp:353:13:353:51 | call to pair | map.cpp:353:13:353:51 | call to pair | TAINT | -| map.cpp:353:39:353:43 | abc | map.cpp:353:13:353:51 | call to pair | TAINT | | map.cpp:353:46:353:50 | def | map.cpp:353:13:353:51 | call to pair | TAINT | | map.cpp:354:2:354:4 | ref arg m21 | map.cpp:358:7:358:9 | m21 | | | map.cpp:354:2:354:4 | ref arg m21 | map.cpp:364:7:364:9 | m21 | | @@ -1697,7 +1651,6 @@ | map.cpp:354:13:354:51 | call to pair | map.cpp:354:2:354:4 | ref arg m21 | TAINT | | map.cpp:354:13:354:51 | call to pair | map.cpp:354:6:354:11 | call to insert | TAINT | | map.cpp:354:13:354:51 | call to pair | map.cpp:354:13:354:51 | call to pair | TAINT | -| map.cpp:354:39:354:43 | abc | map.cpp:354:13:354:51 | call to pair | TAINT | | map.cpp:354:46:354:50 | def | map.cpp:354:13:354:51 | call to pair | TAINT | | map.cpp:355:2:355:4 | ref arg m22 | map.cpp:359:7:359:9 | m22 | | | map.cpp:355:2:355:4 | ref arg m22 | map.cpp:365:7:365:9 | m22 | | @@ -1705,7 +1658,6 @@ | map.cpp:355:13:355:57 | call to pair | map.cpp:355:2:355:4 | ref arg m22 | TAINT | | map.cpp:355:13:355:57 | call to pair | map.cpp:355:6:355:11 | call to insert | TAINT | | map.cpp:355:13:355:57 | call to pair | map.cpp:355:13:355:57 | call to pair | TAINT | -| map.cpp:355:39:355:44 | call to source | map.cpp:355:13:355:57 | call to pair | TAINT | | map.cpp:355:49:355:54 | call to source | map.cpp:355:13:355:57 | call to pair | TAINT | | map.cpp:356:7:356:9 | m19 | map.cpp:356:7:356:9 | call to unordered_map | | | map.cpp:357:7:357:9 | m20 | map.cpp:357:7:357:9 | call to unordered_map | | @@ -1739,7 +1691,6 @@ | map.cpp:369:13:369:57 | call to pair | map.cpp:369:2:369:4 | ref arg m23 | TAINT | | map.cpp:369:13:369:57 | call to pair | map.cpp:369:6:369:11 | call to insert | TAINT | | map.cpp:369:13:369:57 | call to pair | map.cpp:369:13:369:57 | call to pair | TAINT | -| map.cpp:369:39:369:44 | call to source | map.cpp:369:13:369:57 | call to pair | TAINT | | map.cpp:369:49:369:54 | call to source | map.cpp:369:13:369:57 | call to pair | TAINT | | map.cpp:370:2:370:4 | ref arg m23 | map.cpp:371:7:371:9 | m23 | | | map.cpp:370:2:370:4 | ref arg m23 | map.cpp:372:7:372:9 | m23 | | @@ -1751,7 +1702,6 @@ | map.cpp:370:13:370:57 | call to pair | map.cpp:370:2:370:4 | ref arg m23 | TAINT | | map.cpp:370:13:370:57 | call to pair | map.cpp:370:6:370:11 | call to insert | TAINT | | map.cpp:370:13:370:57 | call to pair | map.cpp:370:13:370:57 | call to pair | TAINT | -| map.cpp:370:39:370:44 | call to source | map.cpp:370:13:370:57 | call to pair | TAINT | | map.cpp:370:49:370:54 | call to source | map.cpp:370:13:370:57 | call to pair | TAINT | | map.cpp:371:7:371:9 | m23 | map.cpp:371:7:371:9 | call to unordered_map | | | map.cpp:372:7:372:9 | m23 | map.cpp:372:11:372:15 | call to erase | TAINT | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp index eb022736918..ac0aa9da6cd 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp @@ -39,8 +39,8 @@ void test_pair() std::pair e(source(), "456"); sink(e.first); // tainted - sink(e.second); // [FALSE POSITIVE] - sink(e); // tainted + sink(e.second); + sink(e); // tainted [NOT DETECTED] std::pair f("123", source()); sink(f.first); // [FALSE POSITIVE] @@ -80,19 +80,19 @@ void test_pair() sink(make_pair("123", "456")); sink(make_pair("123", "456").first); sink(make_pair("123", "456").second); - sink(make_pair(source(), "456")); // tainted - sink(make_pair(source(), "456").first); // tainted - sink(make_pair(source(), "456").second); // [FALSE POSITIVE] + sink(make_pair(source(), "456")); // tainted [NOT DETECTED] + sink(make_pair(source(), "456").first); // tainted [NOT DETECTED] + sink(make_pair(source(), "456").second); sink(make_pair("123", source())); // tainted sink(make_pair("123", source()).first); // [FALSE POSITIVE] sink(make_pair("123", source()).second); // tainted std::pair, char *> m; m = make_pair(make_pair("123", source()), "789"); - sink(m); // tainted - sink(m.first); // tainted - sink(m.first.first); // [FALSE POSITIVE] - sink(m.first.second); // tainted + sink(m); // tainted [NOT DETECTED] + sink(m.first); // tainted [NOT DETECTED] + sink(m.first.first); + sink(m.first.second); // tainted [NOT DETECTED] sink(m.second); } @@ -109,19 +109,19 @@ void test_map() sink(m6.insert_or_assign(m6.begin(), "abc", source())); // tainted sink(m1); sink(m2); // tainted - sink(m3); // tainted + sink(m3); // tainted [NOT DETECTED] sink(m4); // tainted sink(m5); // tainted sink(m6); // tainted sink(m1.find("abc")); sink(m2.find("abc")); // tainted - sink(m3.find("abc")); // [FALSE POSITIVE] + sink(m3.find("abc")); sink(m4.find("abc")); // tainted sink(m5.find("abc")); // tainted sink(m6.find("abc")); // tainted sink(m1.find("def")); sink(m2.find("def")); // [FALSE POSITIVE] - sink(m3.find("def")); // [FALSE POSITIVE] + sink(m3.find("def")); sink(m4.find("def")); // [FALSE POSITIVE] sink(m5.find("def")); // [FALSE POSITIVE] sink(m6.find("def")); // [FALSE POSITIVE] @@ -154,7 +154,7 @@ void test_map() } for (i3 = m3.begin(); i3 != m3.end(); i3++) { - sink(*i3); // tainted + sink(*i3); // tainted [NOT DETECTED] sink(i2->first); // tainted sink(i2->second); // [FALSE POSITIVE] } @@ -261,19 +261,19 @@ void test_unordered_map() sink(m6.insert_or_assign(m6.begin(), "abc", source())); // tainted sink(m1); sink(m2); // tainted - sink(m3); // tainted + sink(m3); // tainted [NOT DETECTED] sink(m4); // tainted sink(m5); // tainted sink(m6); // tainted sink(m1.find("abc")); sink(m2.find("abc")); // tainted - sink(m3.find("abc")); // [FALSE POSITIVE] + sink(m3.find("abc")); sink(m4.find("abc")); // tainted sink(m5.find("abc")); // tainted sink(m6.find("abc")); // tainted sink(m1.find("def")); sink(m2.find("def")); // [FALSE POSITIVE] - sink(m3.find("def")); // [FALSE POSITIVE] + sink(m3.find("def")); sink(m4.find("def")); // [FALSE POSITIVE] sink(m5.find("def")); // [FALSE POSITIVE] sink(m6.find("def")); // [FALSE POSITIVE] @@ -306,7 +306,7 @@ void test_unordered_map() } for (i3 = m3.begin(); i3 != m3.end(); i3++) { - sink(*i3); // tainted + sink(*i3); // tainted [NOT DETECTED] sink(i2->first); // tainted sink(i2->second); // [FALSE POSITIVE] } 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 2293eb4edf4..3fcbfb6fbfa 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -36,7 +36,6 @@ | map.cpp:26:9:26:13 | first | map.cpp:25:12:25:17 | call to source | | map.cpp:32:9:32:14 | second | map.cpp:30:13:30:18 | call to source | | map.cpp:41:9:41:13 | first | map.cpp:40:30:40:35 | call to source | -| map.cpp:43:7:43:7 | e | map.cpp:40:30:40:35 | call to source | | map.cpp:47:9:47:14 | second | map.cpp:45:37:45:42 | call to source | | map.cpp:48:7:48:7 | f | map.cpp:45:37:45:42 | call to source | | map.cpp:52:9:52:14 | second | map.cpp:45:37:45:42 | call to source | @@ -49,23 +48,18 @@ | map.cpp:74:9:74:14 | second | map.cpp:63:37:63:42 | call to source | | map.cpp:75:7:75:7 | k | map.cpp:63:37:63:42 | call to source | | map.cpp:78:7:78:7 | l | map.cpp:63:37:63:42 | call to source | -| map.cpp:83:7:83:32 | call to pair | map.cpp:83:17:83:22 | call to source | | map.cpp:86:7:86:32 | call to pair | map.cpp:86:24:86:29 | call to source | -| map.cpp:92:7:92:7 | call to pair | map.cpp:91:33:91:38 | call to source | | map.cpp:107:10:107:15 | call to insert | map.cpp:107:62:107:67 | call to source | | map.cpp:109:10:109:25 | call to insert_or_assign | map.cpp:109:46:109:51 | call to source | | map.cpp:111:7:111:8 | call to map | map.cpp:105:39:105:44 | call to source | -| map.cpp:112:7:112:8 | call to map | map.cpp:106:32:106:37 | call to source | | map.cpp:113:7:113:8 | call to map | map.cpp:107:62:107:67 | call to source | | map.cpp:114:7:114:8 | call to map | map.cpp:108:34:108:39 | call to source | | map.cpp:115:7:115:8 | call to map | map.cpp:109:46:109:51 | call to source | | map.cpp:117:10:117:13 | call to find | map.cpp:105:39:105:44 | call to source | -| map.cpp:118:10:118:13 | call to find | map.cpp:106:32:106:37 | call to source | | map.cpp:119:10:119:13 | call to find | map.cpp:107:62:107:67 | call to source | | map.cpp:120:10:120:13 | call to find | map.cpp:108:34:108:39 | call to source | | map.cpp:121:10:121:13 | call to find | map.cpp:109:46:109:51 | call to source | | map.cpp:123:10:123:13 | call to find | map.cpp:105:39:105:44 | call to source | -| map.cpp:124:10:124:13 | call to find | map.cpp:106:32:106:37 | call to source | | map.cpp:125:10:125:13 | call to find | map.cpp:107:62:107:67 | call to source | | map.cpp:126:10:126:13 | call to find | map.cpp:108:34:108:39 | call to source | | map.cpp:127:10:127:13 | call to find | map.cpp:109:46:109:51 | call to source | @@ -76,61 +70,39 @@ | map.cpp:138:10:138:13 | call to find | map.cpp:105:39:105:44 | call to source | | map.cpp:139:10:139:13 | call to find | map.cpp:105:39:105:44 | call to source | | map.cpp:151:8:151:10 | call to pair | map.cpp:105:39:105:44 | call to source | -| map.cpp:157:8:157:10 | call to pair | map.cpp:106:32:106:37 | call to source | | map.cpp:165:7:165:27 | ... = ... | map.cpp:165:20:165:25 | call to source | | map.cpp:167:7:167:30 | ... = ... | map.cpp:167:23:167:28 | call to source | | map.cpp:169:10:169:10 | call to operator[] | map.cpp:165:20:165:25 | call to source | | map.cpp:171:10:171:10 | call to operator[] | map.cpp:167:23:167:28 | call to source | -| map.cpp:190:7:190:9 | call to map | map.cpp:188:39:188:44 | call to source | | map.cpp:190:7:190:9 | call to map | map.cpp:188:49:188:54 | call to source | -| map.cpp:193:7:193:9 | call to map | map.cpp:189:39:189:44 | call to source | | map.cpp:193:7:193:9 | call to map | map.cpp:189:49:189:54 | call to source | -| map.cpp:196:7:196:9 | call to map | map.cpp:188:39:188:44 | call to source | | map.cpp:196:7:196:9 | call to map | map.cpp:188:49:188:54 | call to source | -| map.cpp:197:7:197:9 | call to map | map.cpp:188:39:188:44 | call to source | | map.cpp:197:7:197:9 | call to map | map.cpp:188:49:188:54 | call to source | -| map.cpp:198:7:198:9 | call to map | map.cpp:189:39:189:44 | call to source | | map.cpp:198:7:198:9 | call to map | map.cpp:189:49:189:54 | call to source | -| map.cpp:199:7:199:9 | call to map | map.cpp:189:39:189:44 | call to source | | map.cpp:199:7:199:9 | call to map | map.cpp:189:49:189:54 | call to source | -| map.cpp:207:7:207:9 | call to map | map.cpp:203:39:203:44 | call to source | | map.cpp:207:7:207:9 | call to map | map.cpp:203:49:203:54 | call to source | -| map.cpp:210:7:210:9 | call to map | map.cpp:206:39:206:44 | call to source | | map.cpp:210:7:210:9 | call to map | map.cpp:206:49:206:54 | call to source | -| map.cpp:213:7:213:9 | call to map | map.cpp:203:39:203:44 | call to source | | map.cpp:213:7:213:9 | call to map | map.cpp:203:49:203:54 | call to source | -| map.cpp:216:7:216:9 | call to map | map.cpp:206:39:206:44 | call to source | | map.cpp:216:7:216:9 | call to map | map.cpp:206:49:206:54 | call to source | -| map.cpp:222:7:222:9 | call to map | map.cpp:220:39:220:44 | call to source | | map.cpp:222:7:222:9 | call to map | map.cpp:220:49:220:54 | call to source | -| map.cpp:222:7:222:9 | call to map | map.cpp:221:39:221:44 | call to source | | map.cpp:222:7:222:9 | call to map | map.cpp:221:49:221:54 | call to source | -| map.cpp:223:11:223:15 | call to erase | map.cpp:220:39:220:44 | call to source | | map.cpp:223:11:223:15 | call to erase | map.cpp:220:49:220:54 | call to source | -| map.cpp:223:11:223:15 | call to erase | map.cpp:221:39:221:44 | call to source | | map.cpp:223:11:223:15 | call to erase | map.cpp:221:49:221:54 | call to source | -| map.cpp:224:7:224:9 | call to map | map.cpp:220:39:220:44 | call to source | | map.cpp:224:7:224:9 | call to map | map.cpp:220:49:220:54 | call to source | -| map.cpp:224:7:224:9 | call to map | map.cpp:221:39:221:44 | call to source | | map.cpp:224:7:224:9 | call to map | map.cpp:221:49:221:54 | call to source | -| map.cpp:226:7:226:9 | call to map | map.cpp:220:39:220:44 | call to source | | map.cpp:226:7:226:9 | call to map | map.cpp:220:49:220:54 | call to source | -| map.cpp:226:7:226:9 | call to map | map.cpp:221:39:221:44 | call to source | | map.cpp:226:7:226:9 | call to map | map.cpp:221:49:221:54 | call to source | | map.cpp:259:10:259:15 | call to insert | map.cpp:259:62:259:67 | call to source | | map.cpp:261:10:261:25 | call to insert_or_assign | map.cpp:261:46:261:51 | call to source | | map.cpp:263:7:263:8 | call to unordered_map | map.cpp:257:39:257:44 | call to source | -| map.cpp:264:7:264:8 | call to unordered_map | map.cpp:258:32:258:37 | call to source | | map.cpp:265:7:265:8 | call to unordered_map | map.cpp:259:62:259:67 | call to source | | map.cpp:266:7:266:8 | call to unordered_map | map.cpp:260:34:260:39 | call to source | | map.cpp:267:7:267:8 | call to unordered_map | map.cpp:261:46:261:51 | call to source | | map.cpp:269:10:269:13 | call to find | map.cpp:257:39:257:44 | call to source | -| map.cpp:270:10:270:13 | call to find | map.cpp:258:32:258:37 | call to source | | map.cpp:271:10:271:13 | call to find | map.cpp:259:62:259:67 | call to source | | map.cpp:272:10:272:13 | call to find | map.cpp:260:34:260:39 | call to source | | map.cpp:273:10:273:13 | call to find | map.cpp:261:46:261:51 | call to source | | map.cpp:275:10:275:13 | call to find | map.cpp:257:39:257:44 | call to source | -| map.cpp:276:10:276:13 | call to find | map.cpp:258:32:258:37 | call to source | | map.cpp:277:10:277:13 | call to find | map.cpp:259:62:259:67 | call to source | | map.cpp:278:10:278:13 | call to find | map.cpp:260:34:260:39 | call to source | | map.cpp:279:10:279:13 | call to find | map.cpp:261:46:261:51 | call to source | @@ -141,46 +113,27 @@ | map.cpp:290:10:290:13 | call to find | map.cpp:257:39:257:44 | call to source | | map.cpp:291:10:291:13 | call to find | map.cpp:257:39:257:44 | call to source | | map.cpp:303:8:303:10 | call to pair | map.cpp:257:39:257:44 | call to source | -| map.cpp:309:8:309:10 | call to pair | map.cpp:258:32:258:37 | call to source | | map.cpp:317:7:317:27 | ... = ... | map.cpp:317:20:317:25 | call to source | | map.cpp:319:7:319:30 | ... = ... | map.cpp:319:23:319:28 | call to source | | map.cpp:321:10:321:10 | call to operator[] | map.cpp:317:20:317:25 | call to source | | map.cpp:323:10:323:10 | call to operator[] | map.cpp:319:23:319:28 | call to source | -| map.cpp:339:7:339:9 | call to unordered_map | map.cpp:337:39:337:44 | call to source | | map.cpp:339:7:339:9 | call to unordered_map | map.cpp:337:49:337:54 | call to source | -| map.cpp:342:7:342:9 | call to unordered_map | map.cpp:338:39:338:44 | call to source | | map.cpp:342:7:342:9 | call to unordered_map | map.cpp:338:49:338:54 | call to source | -| map.cpp:345:7:345:9 | call to unordered_map | map.cpp:337:39:337:44 | call to source | | map.cpp:345:7:345:9 | call to unordered_map | map.cpp:337:49:337:54 | call to source | -| map.cpp:346:7:346:9 | call to unordered_map | map.cpp:337:39:337:44 | call to source | | map.cpp:346:7:346:9 | call to unordered_map | map.cpp:337:49:337:54 | call to source | -| map.cpp:347:7:347:9 | call to unordered_map | map.cpp:338:39:338:44 | call to source | | map.cpp:347:7:347:9 | call to unordered_map | map.cpp:338:49:338:54 | call to source | -| map.cpp:348:7:348:9 | call to unordered_map | map.cpp:338:39:338:44 | call to source | | map.cpp:348:7:348:9 | call to unordered_map | map.cpp:338:49:338:54 | call to source | -| map.cpp:356:7:356:9 | call to unordered_map | map.cpp:352:39:352:44 | call to source | | map.cpp:356:7:356:9 | call to unordered_map | map.cpp:352:49:352:54 | call to source | -| map.cpp:359:7:359:9 | call to unordered_map | map.cpp:355:39:355:44 | call to source | | map.cpp:359:7:359:9 | call to unordered_map | map.cpp:355:49:355:54 | call to source | -| map.cpp:362:7:362:9 | call to unordered_map | map.cpp:352:39:352:44 | call to source | | map.cpp:362:7:362:9 | call to unordered_map | map.cpp:352:49:352:54 | call to source | -| map.cpp:365:7:365:9 | call to unordered_map | map.cpp:355:39:355:44 | call to source | | map.cpp:365:7:365:9 | call to unordered_map | map.cpp:355:49:355:54 | call to source | -| map.cpp:371:7:371:9 | call to unordered_map | map.cpp:369:39:369:44 | call to source | | map.cpp:371:7:371:9 | call to unordered_map | map.cpp:369:49:369:54 | call to source | -| map.cpp:371:7:371:9 | call to unordered_map | map.cpp:370:39:370:44 | call to source | | map.cpp:371:7:371:9 | call to unordered_map | map.cpp:370:49:370:54 | call to source | -| map.cpp:372:11:372:15 | call to erase | map.cpp:369:39:369:44 | call to source | | map.cpp:372:11:372:15 | call to erase | map.cpp:369:49:369:54 | call to source | -| map.cpp:372:11:372:15 | call to erase | map.cpp:370:39:370:44 | call to source | | map.cpp:372:11:372:15 | call to erase | map.cpp:370:49:370:54 | call to source | -| map.cpp:373:7:373:9 | call to unordered_map | map.cpp:369:39:369:44 | call to source | | map.cpp:373:7:373:9 | call to unordered_map | map.cpp:369:49:369:54 | call to source | -| map.cpp:373:7:373:9 | call to unordered_map | map.cpp:370:39:370:44 | call to source | | map.cpp:373:7:373:9 | call to unordered_map | map.cpp:370:49:370:54 | call to source | -| map.cpp:375:7:375:9 | call to unordered_map | map.cpp:369:39:369:44 | call to source | | map.cpp:375:7:375:9 | call to unordered_map | map.cpp:369:49:369:54 | call to source | -| map.cpp:375:7:375:9 | call to unordered_map | map.cpp:370:39:370:44 | call to source | | map.cpp:375:7:375:9 | call to unordered_map | map.cpp:370:49:370:54 | call to source | | movableclass.cpp:44:8:44:9 | s1 | movableclass.cpp:39:21:39:26 | call to source | | movableclass.cpp:45:8:45:9 | s2 | movableclass.cpp:40:23:40:28 | 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 bc8a843de51..e0a02761830 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 @@ -17,7 +17,6 @@ | copyableclass.cpp:67:11:67:21 | copyableclass.cpp:67:13:67:18 | IR only | | copyableclass_declonly.cpp:42:8:42:9 | copyableclass_declonly.cpp:34:30:34:35 | AST only | | copyableclass_declonly.cpp:67:11:67:11 | copyableclass_declonly.cpp:67:13:67:18 | AST only | -| map.cpp:42:9:42:14 | map.cpp:40:30:40:35 | IR only | | map.cpp:46:9:46:13 | map.cpp:45:37:45:42 | IR only | | map.cpp:51:9:51:13 | map.cpp:45:37:45:42 | IR only | | map.cpp:57:9:57:13 | map.cpp:45:37:45:42 | IR only | @@ -27,20 +26,11 @@ | map.cpp:73:9:73:13 | map.cpp:63:37:63:42 | IR only | | map.cpp:76:9:76:13 | map.cpp:63:37:63:42 | IR only | | map.cpp:77:9:77:14 | map.cpp:63:37:63:42 | IR only | -| map.cpp:84:34:84:38 | map.cpp:84:17:84:22 | IR only | -| map.cpp:85:34:85:39 | map.cpp:85:17:85:22 | IR only | | map.cpp:87:34:87:38 | map.cpp:87:24:87:29 | IR only | | map.cpp:88:34:88:39 | map.cpp:88:24:88:29 | IR only | -| map.cpp:92:7:92:7 | map.cpp:91:33:91:38 | AST only | -| map.cpp:93:9:93:13 | map.cpp:91:33:91:38 | IR only | -| map.cpp:94:15:94:19 | map.cpp:91:33:91:38 | IR only | -| map.cpp:95:15:95:20 | map.cpp:91:33:91:38 | IR only | -| map.cpp:96:9:96:14 | map.cpp:91:33:91:38 | IR only | | map.cpp:105:7:105:54 | map.cpp:105:39:105:44 | IR only | -| map.cpp:106:7:106:54 | map.cpp:106:32:106:37 | IR only | | map.cpp:108:7:108:48 | map.cpp:108:34:108:39 | IR only | | map.cpp:111:7:111:8 | map.cpp:105:39:105:44 | AST only | -| map.cpp:112:7:112:8 | map.cpp:106:32:106:37 | AST only | | map.cpp:113:7:113:8 | map.cpp:107:62:107:67 | AST only | | map.cpp:114:7:114:8 | map.cpp:108:34:108:39 | AST only | | map.cpp:115:7:115:8 | map.cpp:109:46:109:51 | AST only | @@ -59,43 +49,25 @@ | map.cpp:159:12:159:17 | map.cpp:105:39:105:44 | IR only | | map.cpp:169:10:169:10 | map.cpp:165:20:165:25 | AST only | | map.cpp:171:10:171:10 | map.cpp:167:23:167:28 | AST only | -| map.cpp:190:7:190:9 | map.cpp:188:39:188:44 | AST only | | map.cpp:190:7:190:9 | map.cpp:188:49:188:54 | AST only | -| map.cpp:193:7:193:9 | map.cpp:189:39:189:44 | AST only | | map.cpp:193:7:193:9 | map.cpp:189:49:189:54 | AST only | -| map.cpp:196:7:196:9 | map.cpp:188:39:188:44 | AST only | | map.cpp:196:7:196:9 | map.cpp:188:49:188:54 | AST only | -| map.cpp:197:7:197:9 | map.cpp:188:39:188:44 | AST only | | map.cpp:197:7:197:9 | map.cpp:188:49:188:54 | AST only | -| map.cpp:198:7:198:9 | map.cpp:189:39:189:44 | AST only | | map.cpp:198:7:198:9 | map.cpp:189:49:189:54 | AST only | -| map.cpp:199:7:199:9 | map.cpp:189:39:189:44 | AST only | | map.cpp:199:7:199:9 | map.cpp:189:49:189:54 | AST only | -| map.cpp:207:7:207:9 | map.cpp:203:39:203:44 | AST only | | map.cpp:207:7:207:9 | map.cpp:203:49:203:54 | AST only | -| map.cpp:210:7:210:9 | map.cpp:206:39:206:44 | AST only | | map.cpp:210:7:210:9 | map.cpp:206:49:206:54 | AST only | -| map.cpp:213:7:213:9 | map.cpp:203:39:203:44 | AST only | | map.cpp:213:7:213:9 | map.cpp:203:49:203:54 | AST only | -| map.cpp:216:7:216:9 | map.cpp:206:39:206:44 | AST only | | map.cpp:216:7:216:9 | map.cpp:206:49:206:54 | AST only | -| map.cpp:222:7:222:9 | map.cpp:220:39:220:44 | AST only | | map.cpp:222:7:222:9 | map.cpp:220:49:220:54 | AST only | -| map.cpp:222:7:222:9 | map.cpp:221:39:221:44 | AST only | | map.cpp:222:7:222:9 | map.cpp:221:49:221:54 | AST only | -| map.cpp:224:7:224:9 | map.cpp:220:39:220:44 | AST only | | map.cpp:224:7:224:9 | map.cpp:220:49:220:54 | AST only | -| map.cpp:224:7:224:9 | map.cpp:221:39:221:44 | AST only | | map.cpp:224:7:224:9 | map.cpp:221:49:221:54 | AST only | -| map.cpp:226:7:226:9 | map.cpp:220:39:220:44 | AST only | | map.cpp:226:7:226:9 | map.cpp:220:49:220:54 | AST only | -| map.cpp:226:7:226:9 | map.cpp:221:39:221:44 | AST only | | map.cpp:226:7:226:9 | map.cpp:221:49:221:54 | AST only | | map.cpp:257:7:257:54 | map.cpp:257:39:257:44 | IR only | -| map.cpp:258:7:258:54 | map.cpp:258:32:258:37 | IR only | | map.cpp:260:7:260:48 | map.cpp:260:34:260:39 | IR only | | map.cpp:263:7:263:8 | map.cpp:257:39:257:44 | AST only | -| map.cpp:264:7:264:8 | map.cpp:258:32:258:37 | AST only | | map.cpp:265:7:265:8 | map.cpp:259:62:259:67 | AST only | | map.cpp:266:7:266:8 | map.cpp:260:34:260:39 | AST only | | map.cpp:267:7:267:8 | map.cpp:261:46:261:51 | AST only | @@ -114,37 +86,21 @@ | map.cpp:311:12:311:17 | map.cpp:257:39:257:44 | IR only | | map.cpp:321:10:321:10 | map.cpp:317:20:317:25 | AST only | | map.cpp:323:10:323:10 | map.cpp:319:23:319:28 | AST only | -| map.cpp:339:7:339:9 | map.cpp:337:39:337:44 | AST only | | map.cpp:339:7:339:9 | map.cpp:337:49:337:54 | AST only | -| map.cpp:342:7:342:9 | map.cpp:338:39:338:44 | AST only | | map.cpp:342:7:342:9 | map.cpp:338:49:338:54 | AST only | -| map.cpp:345:7:345:9 | map.cpp:337:39:337:44 | AST only | | map.cpp:345:7:345:9 | map.cpp:337:49:337:54 | AST only | -| map.cpp:346:7:346:9 | map.cpp:337:39:337:44 | AST only | | map.cpp:346:7:346:9 | map.cpp:337:49:337:54 | AST only | -| map.cpp:347:7:347:9 | map.cpp:338:39:338:44 | AST only | | map.cpp:347:7:347:9 | map.cpp:338:49:338:54 | AST only | -| map.cpp:348:7:348:9 | map.cpp:338:39:338:44 | AST only | | map.cpp:348:7:348:9 | map.cpp:338:49:338:54 | AST only | -| map.cpp:356:7:356:9 | map.cpp:352:39:352:44 | AST only | | map.cpp:356:7:356:9 | map.cpp:352:49:352:54 | AST only | -| map.cpp:359:7:359:9 | map.cpp:355:39:355:44 | AST only | | map.cpp:359:7:359:9 | map.cpp:355:49:355:54 | AST only | -| map.cpp:362:7:362:9 | map.cpp:352:39:352:44 | AST only | | map.cpp:362:7:362:9 | map.cpp:352:49:352:54 | AST only | -| map.cpp:365:7:365:9 | map.cpp:355:39:355:44 | AST only | | map.cpp:365:7:365:9 | map.cpp:355:49:355:54 | AST only | -| map.cpp:371:7:371:9 | map.cpp:369:39:369:44 | AST only | | map.cpp:371:7:371:9 | map.cpp:369:49:369:54 | AST only | -| map.cpp:371:7:371:9 | map.cpp:370:39:370:44 | AST only | | map.cpp:371:7:371:9 | map.cpp:370:49:370:54 | AST only | -| map.cpp:373:7:373:9 | map.cpp:369:39:369:44 | AST only | | map.cpp:373:7:373:9 | map.cpp:369:49:369:54 | AST only | -| map.cpp:373:7:373:9 | map.cpp:370:39:370:44 | AST only | | map.cpp:373:7:373:9 | map.cpp:370:49:370:54 | AST only | -| map.cpp:375:7:375:9 | map.cpp:369:39:369:44 | AST only | | map.cpp:375:7:375:9 | map.cpp:369:49:369:54 | AST only | -| map.cpp:375:7:375:9 | map.cpp:370:39:370:44 | AST only | | map.cpp:375:7:375:9 | map.cpp:370:49:370:54 | AST only | | movableclass.cpp:65:11:65:11 | movableclass.cpp:65:13:65:18 | AST only | | movableclass.cpp:65:11:65:21 | movableclass.cpp:65:13:65:18 | IR 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 3536273a806..fff86c9cb7c 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 @@ -45,8 +45,6 @@ | map.cpp:26:9:26:13 | first | map.cpp:25:12:25:17 | call to source | | map.cpp:32:9:32:14 | second | map.cpp:30:13:30:18 | call to source | | map.cpp:41:9:41:13 | first | map.cpp:40:30:40:35 | call to source | -| map.cpp:42:9:42:14 | second | map.cpp:40:30:40:35 | call to source | -| map.cpp:43:7:43:7 | e | map.cpp:40:30:40:35 | call to source | | map.cpp:46:9:46:13 | first | map.cpp:45:37:45:42 | call to source | | map.cpp:47:9:47:14 | second | map.cpp:45:37:45:42 | call to source | | map.cpp:48:7:48:7 | f | map.cpp:45:37:45:42 | call to source | @@ -68,63 +66,44 @@ | map.cpp:76:9:76:13 | first | map.cpp:63:37:63:42 | call to source | | map.cpp:77:9:77:14 | second | map.cpp:63:37:63:42 | call to source | | map.cpp:78:7:78:7 | l | map.cpp:63:37:63:42 | call to source | -| map.cpp:83:7:83:32 | call to pair | map.cpp:83:17:83:22 | call to source | -| map.cpp:84:34:84:38 | first | map.cpp:84:17:84:22 | call to source | -| map.cpp:85:34:85:39 | second | map.cpp:85:17:85:22 | call to source | | map.cpp:86:7:86:32 | call to pair | map.cpp:86:24:86:29 | call to source | | map.cpp:87:34:87:38 | first | map.cpp:87:24:87:29 | call to source | | map.cpp:88:34:88:39 | second | map.cpp:88:24:88:29 | call to source | -| map.cpp:93:9:93:13 | first | map.cpp:91:33:91:38 | call to source | -| map.cpp:94:15:94:19 | first | map.cpp:91:33:91:38 | call to source | -| map.cpp:95:15:95:20 | second | map.cpp:91:33:91:38 | call to source | -| map.cpp:96:9:96:14 | second | map.cpp:91:33:91:38 | call to source | | map.cpp:105:7:105:54 | call to iterator | map.cpp:105:39:105:44 | call to source | -| map.cpp:106:7:106:54 | call to iterator | map.cpp:106:32:106:37 | call to source | | map.cpp:107:10:107:15 | call to insert | map.cpp:107:62:107:67 | call to source | | map.cpp:108:7:108:48 | call to iterator | map.cpp:108:34:108:39 | call to source | | map.cpp:109:10:109:25 | call to insert_or_assign | map.cpp:109:46:109:51 | call to source | | map.cpp:117:10:117:13 | call to find | map.cpp:105:39:105:44 | call to source | -| map.cpp:118:10:118:13 | call to find | map.cpp:106:32:106:37 | call to source | | map.cpp:119:10:119:13 | call to find | map.cpp:107:62:107:67 | call to source | | map.cpp:123:10:123:13 | call to find | map.cpp:105:39:105:44 | call to source | -| map.cpp:124:10:124:13 | call to find | map.cpp:106:32:106:37 | call to source | | map.cpp:125:10:125:13 | call to find | map.cpp:107:62:107:67 | call to source | | map.cpp:139:10:139:13 | call to find | map.cpp:105:39:105:44 | call to source | | map.cpp:151:8:151:10 | call to pair | map.cpp:105:39:105:44 | call to source | | map.cpp:152:12:152:16 | first | map.cpp:105:39:105:44 | call to source | | map.cpp:153:12:153:17 | second | map.cpp:105:39:105:44 | call to source | -| map.cpp:157:8:157:10 | call to pair | map.cpp:106:32:106:37 | call to source | | map.cpp:158:12:158:16 | first | map.cpp:105:39:105:44 | call to source | | map.cpp:159:12:159:17 | second | map.cpp:105:39:105:44 | call to source | | map.cpp:165:7:165:27 | ... = ... | map.cpp:165:20:165:25 | call to source | | map.cpp:167:7:167:30 | ... = ... | map.cpp:167:23:167:28 | call to source | -| map.cpp:223:11:223:15 | call to erase | map.cpp:220:39:220:44 | call to source | | map.cpp:223:11:223:15 | call to erase | map.cpp:220:49:220:54 | call to source | -| map.cpp:223:11:223:15 | call to erase | map.cpp:221:39:221:44 | call to source | | map.cpp:223:11:223:15 | call to erase | map.cpp:221:49:221:54 | call to source | | map.cpp:257:7:257:54 | call to iterator | map.cpp:257:39:257:44 | call to source | -| map.cpp:258:7:258:54 | call to iterator | map.cpp:258:32:258:37 | call to source | | map.cpp:259:10:259:15 | call to insert | map.cpp:259:62:259:67 | call to source | | map.cpp:260:7:260:48 | call to iterator | map.cpp:260:34:260:39 | call to source | | map.cpp:261:10:261:25 | call to insert_or_assign | map.cpp:261:46:261:51 | call to source | | map.cpp:269:10:269:13 | call to find | map.cpp:257:39:257:44 | call to source | -| map.cpp:270:10:270:13 | call to find | map.cpp:258:32:258:37 | call to source | | map.cpp:271:10:271:13 | call to find | map.cpp:259:62:259:67 | call to source | | map.cpp:275:10:275:13 | call to find | map.cpp:257:39:257:44 | call to source | -| map.cpp:276:10:276:13 | call to find | map.cpp:258:32:258:37 | call to source | | map.cpp:277:10:277:13 | call to find | map.cpp:259:62:259:67 | call to source | | map.cpp:291:10:291:13 | call to find | map.cpp:257:39:257:44 | call to source | | map.cpp:303:8:303:10 | call to pair | map.cpp:257:39:257:44 | call to source | | map.cpp:304:12:304:16 | first | map.cpp:257:39:257:44 | call to source | | map.cpp:305:12:305:17 | second | map.cpp:257:39:257:44 | call to source | -| map.cpp:309:8:309:10 | call to pair | map.cpp:258:32:258:37 | call to source | | map.cpp:310:12:310:16 | first | map.cpp:257:39:257:44 | call to source | | map.cpp:311:12:311:17 | second | map.cpp:257:39:257:44 | call to source | | map.cpp:317:7:317:27 | ... = ... | map.cpp:317:20:317:25 | call to source | | map.cpp:319:7:319:30 | ... = ... | map.cpp:319:23:319:28 | call to source | -| map.cpp:372:11:372:15 | call to erase | map.cpp:369:39:369:44 | call to source | | map.cpp:372:11:372:15 | call to erase | map.cpp:369:49:369:54 | call to source | -| map.cpp:372:11:372:15 | call to erase | map.cpp:370:39:370:44 | call to source | | map.cpp:372:11:372:15 | call to erase | map.cpp:370:49:370:54 | call to source | | movableclass.cpp:44:8:44:9 | s1 | movableclass.cpp:39:21:39:26 | call to source | | movableclass.cpp:45:8:45:9 | s2 | movableclass.cpp:40:23:40:28 | call to source | From bc68578c8bfd2c6710c930314e2cf6f1878ae9da Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 1 Oct 2020 21:11:47 +0200 Subject: [PATCH 159/411] C#: Remove deprecated external queries --- .../examples/filters/BumpMetricBy10.ql | 11 -------- .../examples/filters/EditDefectMessage.ql | 11 -------- .../examples/filters/ExcludeGeneratedCode.ql | 14 ---------- .../external/examples/filters/FromSource.ql | 12 --------- .../external/tests/DefectFromExternalData.ql | 19 ------------- .../tests/DefectFromExternalDefect.ql | 17 ------------ .../tests/DefectFromExternalMetric.ql | 17 ------------ csharp/ql/src/external/tests/MetricFilter.ql | 13 --------- .../tests/MetricFromExternalDefect.ql | 21 --------------- .../tests/MetricFromExternalMetric.ql | 27 ------------------- 10 files changed, 162 deletions(-) delete mode 100644 csharp/ql/src/external/examples/filters/BumpMetricBy10.ql delete mode 100644 csharp/ql/src/external/examples/filters/EditDefectMessage.ql delete mode 100644 csharp/ql/src/external/examples/filters/ExcludeGeneratedCode.ql delete mode 100644 csharp/ql/src/external/examples/filters/FromSource.ql delete mode 100644 csharp/ql/src/external/tests/DefectFromExternalData.ql delete mode 100644 csharp/ql/src/external/tests/DefectFromExternalDefect.ql delete mode 100644 csharp/ql/src/external/tests/DefectFromExternalMetric.ql delete mode 100644 csharp/ql/src/external/tests/MetricFilter.ql delete mode 100644 csharp/ql/src/external/tests/MetricFromExternalDefect.ql delete mode 100644 csharp/ql/src/external/tests/MetricFromExternalMetric.ql diff --git a/csharp/ql/src/external/examples/filters/BumpMetricBy10.ql b/csharp/ql/src/external/examples/filters/BumpMetricBy10.ql deleted file mode 100644 index 209d580bc19..00000000000 --- a/csharp/ql/src/external/examples/filters/BumpMetricBy10.ql +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @name Edit the value of a metric - * @description Add 10 to a metric's value - * @deprecated - */ - -import csharp -import external.MetricFilter - -from MetricResult res -select res, res.getValue() + 10 diff --git a/csharp/ql/src/external/examples/filters/EditDefectMessage.ql b/csharp/ql/src/external/examples/filters/EditDefectMessage.ql deleted file mode 100644 index 4fbf4146550..00000000000 --- a/csharp/ql/src/external/examples/filters/EditDefectMessage.ql +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @name Edit the message of a query - * @description Change the string in the select to edit the message - * @deprecated - */ - -import csharp -import external.DefectFilter - -from DefectResult res -select res, "Filtered query result: " + res.getMessage() diff --git a/csharp/ql/src/external/examples/filters/ExcludeGeneratedCode.ql b/csharp/ql/src/external/examples/filters/ExcludeGeneratedCode.ql deleted file mode 100644 index 2a1257427b2..00000000000 --- a/csharp/ql/src/external/examples/filters/ExcludeGeneratedCode.ql +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @name Filter: removed results from generated code - * @description Shows how to exclude certain files or folders from results. - * @deprecated - */ - -import csharp -import external.DefectFilter - -predicate generatedFile(File f) { f.getAbsolutePath().matches("%generated%") } - -from DefectResult res -where not generatedFile(res.getFile()) -select res, res.getMessage() diff --git a/csharp/ql/src/external/examples/filters/FromSource.ql b/csharp/ql/src/external/examples/filters/FromSource.ql deleted file mode 100644 index 2f714ec2225..00000000000 --- a/csharp/ql/src/external/examples/filters/FromSource.ql +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @name Filter: only keep results from source - * @description Shows how to filter for only certain files - * @deprecated - */ - -import csharp -import external.DefectFilter - -from DefectResult res -where res.getFile().fromSource() -select res, res.getMessage() diff --git a/csharp/ql/src/external/tests/DefectFromExternalData.ql b/csharp/ql/src/external/tests/DefectFromExternalData.ql deleted file mode 100644 index 70557f357a3..00000000000 --- a/csharp/ql/src/external/tests/DefectFromExternalData.ql +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @name Defect from external data - * @description Insert description here... - * @kind problem - * @problem.severity warning - * @deprecated - */ - -import csharp -import external.ExternalArtifact - -// custom://[FileUtil][2011-01-02][false][1.1][6][Message 2] -from ExternalData d, File u -where - d.getQueryPath() = "external-data.ql" and - u.getStem() = d.getField(0) -select u, - d.getField(5) + ", " + d.getFieldAsDate(1) + ", " + d.getField(2) + ", " + d.getFieldAsFloat(3) + - ", " + d.getFieldAsInt(4) + ": " + d.getNumFields() diff --git a/csharp/ql/src/external/tests/DefectFromExternalDefect.ql b/csharp/ql/src/external/tests/DefectFromExternalDefect.ql deleted file mode 100644 index 57138a6879f..00000000000 --- a/csharp/ql/src/external/tests/DefectFromExternalDefect.ql +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @name Defect from external defect - * @description Create a defect from external data - * @kind problem - * @problem.severity warning - * @deprecated - */ - -import csharp -import external.ExternalArtifact - -class DuplicateCode extends ExternalDefect { - DuplicateCode() { getQueryPath() = "duplicate-code/duplicateCode.ql" } -} - -from DuplicateCode d -select d, "External Defect " + d.getMessage() diff --git a/csharp/ql/src/external/tests/DefectFromExternalMetric.ql b/csharp/ql/src/external/tests/DefectFromExternalMetric.ql deleted file mode 100644 index 88d38d5f00b..00000000000 --- a/csharp/ql/src/external/tests/DefectFromExternalMetric.ql +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @name Defect from external metric - * @description Create a defect from external data - * @kind problem - * @problem.severity warning - * @deprecated - */ - -import csharp -import external.ExternalArtifact - -from ExternalMetric m, File f -where - m.getQueryPath() = "filesBuilt.ql" and - m.getValue() = 1.0 and - m.getFile() = f -select f, "File is built" diff --git a/csharp/ql/src/external/tests/MetricFilter.ql b/csharp/ql/src/external/tests/MetricFilter.ql deleted file mode 100644 index 9f79465be75..00000000000 --- a/csharp/ql/src/external/tests/MetricFilter.ql +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @name Metric filter - * @description Only include results in large files (200) lines of code. - * @kind treemap - * @deprecated - */ - -import csharp -import external.MetricFilter - -from MetricResult res -where res.getFile().getNumberOfLinesOfCode() > 200 -select res, res.getValue() diff --git a/csharp/ql/src/external/tests/MetricFromExternalDefect.ql b/csharp/ql/src/external/tests/MetricFromExternalDefect.ql deleted file mode 100644 index 4894de28761..00000000000 --- a/csharp/ql/src/external/tests/MetricFromExternalDefect.ql +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @name Metric from external defect - * @description Find number of duplicate code entries in a file - * @treemap.warnOn lowValues - * @metricType file - * @kind treemap - * @deprecated - */ - -import csharp -import external.ExternalArtifact - -class DuplicateCode extends ExternalDefect { - DuplicateCode() { getQueryPath() = "duplicate-code/duplicateCode.ql" } -} - -predicate numDuplicateEntries(File f, int i) { i = count(DuplicateCode d | d.getFile() = f) } - -from File f, int i -where numDuplicateEntries(f, i) -select f, i diff --git a/csharp/ql/src/external/tests/MetricFromExternalMetric.ql b/csharp/ql/src/external/tests/MetricFromExternalMetric.ql deleted file mode 100644 index 4d2ab4088ae..00000000000 --- a/csharp/ql/src/external/tests/MetricFromExternalMetric.ql +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @name Metric from external metric - * @description Each file in a folder gets as metric value the number of files built in that folder - * @treemap.warnOn lowValues - * @metricType file - * @kind treemap - * @deprecated - */ - -import csharp -import external.ExternalArtifact - -predicate numBuiltFiles(Folder fold, int i) { - i = - count(File f | - exists(ExternalMetric m | - m.getQueryPath() = "filesBuilt.ql" and - m.getValue() = 1.0 and - m.getFile() = f - ) and - f.getParentContainer() = fold - ) -} - -from File f, int i -where numBuiltFiles(f.getParentContainer(), i) -select f, i From 78625b764dd2f0c4f90d15e09d02b59524566c22 Mon Sep 17 00:00:00 2001 From: Gulshan Singh Date: Thu, 1 Oct 2020 16:07:06 -0700 Subject: [PATCH 160/411] C++: Add test for bitwise and ranges --- .../rangeanalysis/bitwiseand/bitwiseand.cpp | 59 +++++++++++++++++++ .../bitwiseand/bitwiseand.expected | 21 +++++++ .../rangeanalysis/bitwiseand/bitwiseand.ql | 8 +++ 3 files changed, 88 insertions(+) create mode 100644 cpp/ql/test/experimental/library-tests/rangeanalysis/bitwiseand/bitwiseand.cpp create mode 100644 cpp/ql/test/experimental/library-tests/rangeanalysis/bitwiseand/bitwiseand.expected create mode 100644 cpp/ql/test/experimental/library-tests/rangeanalysis/bitwiseand/bitwiseand.ql diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/bitwiseand/bitwiseand.cpp b/cpp/ql/test/experimental/library-tests/rangeanalysis/bitwiseand/bitwiseand.cpp new file mode 100644 index 00000000000..d45b0062d5d --- /dev/null +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/bitwiseand/bitwiseand.cpp @@ -0,0 +1,59 @@ +typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef unsigned uint32_t; +typedef signed long long int64_t; + +void test_assign_operator(uint8_t x) { + x &= 7; // [0 .. 7] +} + +void test_non_negative_const(uint8_t x) { + uint8_t unsigned_const = 7; + + // Non-negative range operand and non-negative constant. The operands are promoted + // to signed ints. + x & 0; // [0 .. 0] + x & 7; // [0 .. 7] + x & unsigned_const; // [0 .. 7] + + // This tests what happens when both arguments are promoted to `unsigned int` instead + // of `int`, and when the constant is larger than the max bound + x & 0xFFFFFFFF; // [0 .. 255] +} + +void test_non_const(uint8_t a, uint8_t b, uint32_t c, uint32_t d) { + if (b <= 100) { + // `a` and `b` are promoted to signed ints, meaning neither the range analysis library + // nor this extension handle it + a & b; // [-2147483648 .. 2147483647] + } + if (d <= 100) { + // Handled by the range analysis library + c & d; // [0 .. 100] + } +} + +void test_negative_operand(uint8_t x, int8_t y) { + uint8_t unsigned_const = 7; + int8_t signed_const = -7; + + // The right operand can be negative + x & -7; // [-2147483648 .. 2147483647] + x & signed_const; // [-2147483648 .. 2147483647] + x & y; // [-2147483648 .. 2147483647] + + // The left operand can be negative + y & 7; // [-2147483648 .. 2147483647] + y & unsigned_const; // [-2147483648 .. 2147483647] + y & 0xFFFFFFFF; // [0 .. 4294967295] + (int64_t)y & 0xFFFFFFFF; // [-9223372036854776000 .. 9223372036854776000] + y & x; // [-2147483648 .. 2147483647] + + // Both can be negative + y & -7; // [-2147483648 .. 2147483647] + y & signed_const; // [-2147483648 .. 2147483647] + signed_const & -7; // [-2147483648 .. 2147483647] + signed_const & y; // [-2147483648 .. 2147483647] + -7 & y; // [-2147483648 .. 2147483647] + -7 & signed_const; // [-2147483648 .. 2147483647] +} diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/bitwiseand/bitwiseand.expected b/cpp/ql/test/experimental/library-tests/rangeanalysis/bitwiseand/bitwiseand.expected new file mode 100644 index 00000000000..7f5bbcc4e25 --- /dev/null +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/bitwiseand/bitwiseand.expected @@ -0,0 +1,21 @@ +| bitwiseand.cpp:7:3:7:8 | ... &= ... | 0.0 | 255.0 | +| bitwiseand.cpp:15:3:15:7 | ... & ... | -2.147483648E9 | 2.147483647E9 | +| bitwiseand.cpp:16:3:16:7 | ... & ... | -2.147483648E9 | 2.147483647E9 | +| bitwiseand.cpp:17:3:17:20 | ... & ... | -2.147483648E9 | 2.147483647E9 | +| bitwiseand.cpp:21:3:21:16 | ... & ... | 0.0 | 255.0 | +| bitwiseand.cpp:28:5:28:9 | ... & ... | -2.147483648E9 | 2.147483647E9 | +| bitwiseand.cpp:32:5:32:9 | ... & ... | 0.0 | 100.0 | +| bitwiseand.cpp:41:3:41:8 | ... & ... | -2.147483648E9 | 2.147483647E9 | +| bitwiseand.cpp:42:3:42:18 | ... & ... | -2.147483648E9 | 2.147483647E9 | +| bitwiseand.cpp:43:3:43:7 | ... & ... | -2.147483648E9 | 2.147483647E9 | +| bitwiseand.cpp:46:3:46:7 | ... & ... | -2.147483648E9 | 2.147483647E9 | +| bitwiseand.cpp:47:3:47:20 | ... & ... | -2.147483648E9 | 2.147483647E9 | +| bitwiseand.cpp:48:3:48:16 | ... & ... | 0.0 | 4.294967295E9 | +| bitwiseand.cpp:49:3:49:25 | ... & ... | -9.223372036854776E18 | 9.223372036854776E18 | +| bitwiseand.cpp:50:3:50:7 | ... & ... | -2.147483648E9 | 2.147483647E9 | +| bitwiseand.cpp:53:3:53:8 | ... & ... | -2.147483648E9 | 2.147483647E9 | +| bitwiseand.cpp:54:3:54:18 | ... & ... | -2.147483648E9 | 2.147483647E9 | +| bitwiseand.cpp:55:3:55:19 | ... & ... | -2.147483648E9 | 2.147483647E9 | +| bitwiseand.cpp:56:3:56:18 | ... & ... | -2.147483648E9 | 2.147483647E9 | +| bitwiseand.cpp:57:3:57:8 | ... & ... | -2.147483648E9 | 2.147483647E9 | +| bitwiseand.cpp:58:3:58:19 | ... & ... | -2.147483648E9 | 2.147483647E9 | diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/bitwiseand/bitwiseand.ql b/cpp/ql/test/experimental/library-tests/rangeanalysis/bitwiseand/bitwiseand.ql new file mode 100644 index 00000000000..6521e8f0f61 --- /dev/null +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/bitwiseand/bitwiseand.ql @@ -0,0 +1,8 @@ +import experimental.semmle.code.cpp.rangeanalysis.ExtendedRangeAnalysis + +from Operation expr, float lower, float upper +where + (expr instanceof BitwiseAndExpr or expr instanceof AssignAndExpr) and + lower = lowerBound(expr) and + upper = upperBound(expr) +select expr, lower, upper From f026d3a1e693941ea0434b82eb773675704176c7 Mon Sep 17 00:00:00 2001 From: Gulshan Singh Date: Thu, 1 Oct 2020 23:22:33 -0700 Subject: [PATCH 161/411] C++: Improve bitwise and range analysis --- .../rangeanalysis/BinaryOrAssignOperation.qll | 31 +++++ .../rangeanalysis/ExtendedRangeAnalysis.qll | 1 + .../ConstantBitwiseAndExprRange.qll | 112 ++++++++++++++++++ .../bitwiseand/bitwiseand.expected | 8 +- 4 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/BinaryOrAssignOperation.qll create mode 100644 cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/extensions/ConstantBitwiseAndExprRange.qll diff --git a/cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/BinaryOrAssignOperation.qll b/cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/BinaryOrAssignOperation.qll new file mode 100644 index 00000000000..1670f4ebcd0 --- /dev/null +++ b/cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/BinaryOrAssignOperation.qll @@ -0,0 +1,31 @@ +private import cpp + +Expr getLOp(Operation o) { + result = o.(BinaryOperation).getLeftOperand() or + result = o.(Assignment).getLValue() +} + +Expr getROp(Operation o) { + result = o.(BinaryOperation).getRightOperand() or + result = o.(Assignment).getRValue() +} + +private newtype TBinaryOrAssignOperation = + BinaryOp(BinaryOperation op) or + AssignOp(AssignOperation op) + +class BinaryOrAssignOperation extends TBinaryOrAssignOperation { + BinaryOperation asBinaryOp() { this = BinaryOp(result) } + + AssignOperation asAssignOp() { this = AssignOp(result) } + + Expr getLeftOperand() { result = getLOp(asBinaryOp()) or result = getLOp(asAssignOp()) } + + Expr getRightOperand() { result = getROp(asBinaryOp()) or result = getROp(asAssignOp()) } + + Expr getAnOperand() { result = getLeftOperand() or result = getRightOperand() } + + Operation getOperation() { result = asBinaryOp() or result = asAssignOp() } + + string toString() { result = asBinaryOp().toString() or result = asAssignOp().toString() } +} diff --git a/cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/ExtendedRangeAnalysis.qll b/cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/ExtendedRangeAnalysis.qll index 4c9b0c738f4..bc63d740c32 100644 --- a/cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/ExtendedRangeAnalysis.qll +++ b/cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/ExtendedRangeAnalysis.qll @@ -2,3 +2,4 @@ import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis // // Import each extension we want to enable import extensions.SubtractSelf +import extensions.ConstantBitwiseAndExprRange diff --git a/cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/extensions/ConstantBitwiseAndExprRange.qll b/cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/extensions/ConstantBitwiseAndExprRange.qll new file mode 100644 index 00000000000..27f9733b557 --- /dev/null +++ b/cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/extensions/ConstantBitwiseAndExprRange.qll @@ -0,0 +1,112 @@ +private import cpp +private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr +private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils +private import experimental.semmle.code.cpp.rangeanalysis.BinaryOrAssignOperation + +/** + * The current implementation for `BitwiseAndExpr` only handles cases where both operands are + * either unsigned or non-negative constants. This class not only covers these cases, but also + * adds support for `&` expressions between a signed integer with a non-negative range and a + * non-negative constant. It also adds support for `&=` for the same set of cases as `&`. + */ +private class ConstantBitwiseAndExprRange extends SimpleRangeAnalysisExpr { + BinaryOrAssignConstantBitwiseAndExpr e; + + ConstantBitwiseAndExprRange() { this = e.getOperation() } + + BinaryOrAssignConstantBitwiseAndExpr getExpr() { result = e } + + Expr getLeftOperand() { result = e.getLeftOperand() } + + Expr getRightOperand() { result = e.getRightOperand() } + + override float getLowerBounds() { result = e.getLowerBounds() } + + override float getUpperBounds() { result = e.getUpperBounds() } + + override predicate dependsOnChild(Expr child) { child = e.getAnOperand() } +} + +private class ConstantBitwiseAndExprOp extends Expr { + BinaryOrAssignConstantBitwiseAndExpr b; + float lowerBound; + float upperBound; + + ConstantBitwiseAndExprOp() { + this = b.getAnOperand() and + lowerBound = getFullyConvertedLowerBounds(this) and + upperBound = getFullyConvertedUpperBounds(this) and + lowerBound <= upperBound + } + + float getLowerBound() { result = lowerBound } + + float getUpperBound() { result = upperBound } + + predicate hasNegativeRange() { getLowerBound() < 0 or getUpperBound() < 0 } +} + +/** + * Holds if `e` is a constant or if it is a variable with a constant value + */ +float evaluateConstantExpr(Expr e) { + result = e.getValue().toFloat() + or + exists(SsaDefinition defn, StackVariable sv | + defn.getAUse(sv) = e and + result = defn.getDefiningValue(sv).getValue().toFloat() + ) +} + +private class BinaryOrAssignConstantBitwiseAndExpr extends BinaryOrAssignOperation { + BinaryOrAssignConstantBitwiseAndExpr() { + ( + getOperation() instanceof BitwiseAndExpr + or + getOperation() instanceof AssignAndExpr + ) and + // Make sure all operands and the result type are integral + getOperation().getUnspecifiedType() instanceof IntegralType and + getLeftOperand().getUnspecifiedType() instanceof IntegralType and + getRightOperand().getUnspecifiedType() instanceof IntegralType and + // No operands can be negative constants + not (evaluateConstantExpr(getLeftOperand()) < 0 or evaluateConstantExpr(getRightOperand()) < 0) and + // At least one operand must be a non-negative constant + (evaluateConstantExpr(getLeftOperand()) >= 0 or evaluateConstantExpr(getRightOperand()) >= 0) + } + + float getLowerBounds() { + // If both operands have non-negative ranges, the lower bound is zero. If an operand can have + // negative values, the lower bound is unconstrained. + exists(ConstantBitwiseAndExprOp l, ConstantBitwiseAndExprOp r | + l = getLeftOperand() and + r = getRightOperand() and + ( + (l.hasNegativeRange() or r.hasNegativeRange()) and + result = exprMinVal(getOperation()) + or + // This technically results in two lowerBounds when an operand range is negative, but + // that's fine since `exprMinVal(x) <= 0`. We can't use an if statement here without + // non-monotonic recursion issues + result = 0 + ) + ) + } + + float getUpperBounds() { + // If an operand can have negative values, the upper bound is unconstrained. + // Otherwise, the upper bound is the maximum of the upper bounds of the operands + exists(ConstantBitwiseAndExprOp l, ConstantBitwiseAndExprOp r | + l = getLeftOperand() and + r = getRightOperand() and + ( + (l.hasNegativeRange() or r.hasNegativeRange()) and + result = exprMaxVal(getOperation()) + or + // This technically results in two upperBounds when an operand range is negative, but + // that's fine since `exprMaxVal(b) >= result` + result = r.getUpperBound().minimum(l.getUpperBound()) + ) + ) + } +} diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/bitwiseand/bitwiseand.expected b/cpp/ql/test/experimental/library-tests/rangeanalysis/bitwiseand/bitwiseand.expected index 7f5bbcc4e25..22ad956469e 100644 --- a/cpp/ql/test/experimental/library-tests/rangeanalysis/bitwiseand/bitwiseand.expected +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/bitwiseand/bitwiseand.expected @@ -1,7 +1,7 @@ -| bitwiseand.cpp:7:3:7:8 | ... &= ... | 0.0 | 255.0 | -| bitwiseand.cpp:15:3:15:7 | ... & ... | -2.147483648E9 | 2.147483647E9 | -| bitwiseand.cpp:16:3:16:7 | ... & ... | -2.147483648E9 | 2.147483647E9 | -| bitwiseand.cpp:17:3:17:20 | ... & ... | -2.147483648E9 | 2.147483647E9 | +| bitwiseand.cpp:7:3:7:8 | ... &= ... | 0.0 | 7.0 | +| bitwiseand.cpp:15:3:15:7 | ... & ... | 0.0 | 0.0 | +| bitwiseand.cpp:16:3:16:7 | ... & ... | 0.0 | 7.0 | +| bitwiseand.cpp:17:3:17:20 | ... & ... | 0.0 | 7.0 | | bitwiseand.cpp:21:3:21:16 | ... & ... | 0.0 | 255.0 | | bitwiseand.cpp:28:5:28:9 | ... & ... | -2.147483648E9 | 2.147483647E9 | | bitwiseand.cpp:32:5:32:9 | ... & ... | 0.0 | 100.0 | From 37fc1d6f0fbd4a5bb0d3375de9e00969c2f6039e Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 29 Sep 2020 11:19:02 +0200 Subject: [PATCH 162/411] Java, C#: cleanup sign analysis Add missing QL doc, improve readability --- .../rangeanalysis/SignAnalysisCommon.qll | 54 ++++++++++++------- .../rangeanalysis/SignAnalysisSpecific.qll | 29 +++++++--- .../rangeanalysis/SignAnalysisCommon.qll | 54 ++++++++++++------- .../rangeanalysis/SignAnalysisSpecific.qll | 32 +++++++---- 4 files changed, 110 insertions(+), 59 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index c734e6acb0e..33ef5d3683f 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -11,7 +11,7 @@ private import SsaReadPositionCommon private import Sign /** Gets the sign of `e` if this can be directly determined. */ -Sign certainExprSign(Expr e) { +private Sign certainExprSign(Expr e) { exists(int i | e.(ConstantIntegerExpr).getIntValue() = i | i < 0 and result = TNeg() or @@ -185,29 +185,32 @@ private predicate hasGuard(SsaVariable v, SsaReadPosition pos, Sign s) { s = TZero() and zeroBound(_, v, pos) } +/** + * Gets a possible sign of `v` at `pos` based on its definition, where the sign + * might be ruled out by a guard. + */ pragma[noinline] private Sign guardedSsaSign(SsaVariable v, SsaReadPosition pos) { - // SSA variable can have sign `result` result = ssaDefSign(v) and pos.hasReadOfVar(v) and - // there are guards at this position on `v` that might restrict it to be sign `result`. - // (So we need to check if they are satisfied) hasGuard(v, pos, result) } +/** + * Gets a possible sign of `v` at `pos` based on its definition, where no guard + * can rule it out. + */ pragma[noinline] private Sign unguardedSsaSign(SsaVariable v, SsaReadPosition pos) { - // SSA variable can have sign `result` result = ssaDefSign(v) and pos.hasReadOfVar(v) and - // there's no guard at this position on `v` that might restrict it to be sign `result`. not hasGuard(v, pos, result) } /** - * Gets the sign of `v` at read position `pos`, when there's at least one guard - * on `v` at position `pos`. Each bound corresponding to a given sign must be met - * in order for `v` to be of that sign. + * Gets a possible sign of `v` at read position `pos`, where a guard could have + * ruled out the sign but does not. + * This does not check that the definition of `v` also allows the sign. */ private Sign guardedSsaSignOk(SsaVariable v, SsaReadPosition pos) { result = TPos() and @@ -221,7 +224,7 @@ private Sign guardedSsaSignOk(SsaVariable v, SsaReadPosition pos) { } /** Gets a possible sign for `v` at `pos`. */ -Sign ssaSign(SsaVariable v, SsaReadPosition pos) { +private Sign ssaSign(SsaVariable v, SsaReadPosition pos) { result = unguardedSsaSign(v, pos) or result = guardedSsaSign(v, pos) and @@ -230,7 +233,7 @@ Sign ssaSign(SsaVariable v, SsaReadPosition pos) { /** Gets a possible sign for `v`. */ pragma[nomagic] -Sign ssaDefSign(SsaVariable v) { +private Sign ssaDefSign(SsaVariable v) { result = explicitSsaDefSign(v) or result = implicitSsaDefSign(v) @@ -250,18 +253,23 @@ Sign exprSign(Expr e) { or not exists(certainExprSign(e)) and ( - unknownSign(e) + anySign(s) and unknownSign(e) or - exists(SsaVariable v | getARead(v) = e | s = ssaVariableSign(v, e)) + exists(SsaVariable v | getARead(v) = e | + s = ssaSign(v, any(SsaReadPositionBlock bb | getAnExpression(bb) = e)) + or + not exists(SsaReadPositionBlock bb | getAnExpression(bb) = e) and + s = ssaDefSign(v) + ) or - e = - any(VarAccess access | - not exists(SsaVariable v | getARead(v) = access) and - ( - s = fieldSign(getField(access.(FieldAccess))) or - not access instanceof FieldAccess - ) + exists(VarAccess access | access = e | + not exists(SsaVariable v | getARead(v) = access) and + ( + s = fieldSign(getField(access.(FieldAccess))) + or + anySign(s) and not access instanceof FieldAccess ) + ) or s = specificSubExprSign(e) ) @@ -272,6 +280,12 @@ Sign exprSign(Expr e) { ) } +/** + * Dummy predicate that holds for any sign. This is added to improve readability + * of cases where the sign is unrestricted. + */ +predicate anySign(Sign s) { any() } + /** Holds if `e` can be positive and cannot be negative. */ predicate positive(Expr e) { exprSign(e) = TPos() and diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index 813834c3fd8..00f68fa85df 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -48,6 +48,10 @@ private module Impl { private class BooleanValue = AbstractValues::BooleanValue; + /** + * Gets the value of the expression if it can't be converted to integer, but + * can be converted to float. + */ float getNonIntegerValue(Expr e) { exists(string s | s = e.getValue() and @@ -56,8 +60,13 @@ private module Impl { ) } + /** Gets the character value of expression `e`. */ string getCharValue(Expr e) { result = e.getValue() and e.getType() instanceof CharType } + /** + * Holds if `e` is an access to the size of a container (`string`, `Array`, + * `IEnumerable`, or `ICollection`). + */ predicate containerSizeAccess(Expr e) { exists(Property p | p = e.(PropertyAccess).getTarget() | propertyOverrides(p, "System.Collections.Generic.IEnumerable<>", "Count") or @@ -69,6 +78,7 @@ private module Impl { e instanceof CountCall } + /** Holds if `e` is by definition strictly positive. */ predicate positiveExpression(Expr e) { e instanceof SizeofExpr } abstract class NumericOrCharType extends Type { } @@ -97,10 +107,12 @@ private module Impl { } } + /** Returns the sign of explicit SSA definition `v`. */ Sign explicitSsaDefSign(Ssa::ExplicitDefinition v) { exists(AssignableDefinition def | def = v.getADefinition() | result = exprSign(def.getSource()) or + anySign(result) and not exists(def.getSource()) and not def.getElement() instanceof MutatorOperation or @@ -110,14 +122,11 @@ private module Impl { ) } + /** Returns the sign of implicit SSA definition `v`. */ Sign implicitSsaDefSign(Ssa::ImplicitDefinition v) { - result = fieldSign(v.getSourceVariable().getAssignable()) or - not v.getSourceVariable().getAssignable() instanceof Field - } - - pragma[inline] - Sign ssaVariableSign(Ssa::Definition v, Expr e) { - result = ssaSign(v, any(SsaReadPositionBlock bb | getAnExpression(bb) = e)) + result = fieldSign(v.getSourceVariable().getAssignable()) + or + anySign(result) and not v.getSourceVariable().getAssignable() instanceof Field } /** Gets a possible sign for `f`. */ @@ -133,9 +142,12 @@ private module Impl { exists(AssignOperation a | a.getLValue() = f.getAnAccess() | result = exprSign(a)) or not exists(f.getInitializer()) and result = TZero() - else any() + else anySign(result) } + /** + * Holds if `e` has type `NumericOrCharType`, but the sign of `e` is unknown. + */ predicate unknownIntegerAccess(Expr e) { e.getType() instanceof NumericOrCharType and not e = getARead(_) and @@ -171,6 +183,7 @@ private module Impl { not e instanceof NullCoalescingExpr } + /** Gets a possible sign for `e` from the signs of its child nodes. */ Sign specificSubExprSign(Expr e) { // The expression types that are handled here should be excluded in `unknownIntegerAccess`. // Keep them in sync. diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index c734e6acb0e..33ef5d3683f 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -11,7 +11,7 @@ private import SsaReadPositionCommon private import Sign /** Gets the sign of `e` if this can be directly determined. */ -Sign certainExprSign(Expr e) { +private Sign certainExprSign(Expr e) { exists(int i | e.(ConstantIntegerExpr).getIntValue() = i | i < 0 and result = TNeg() or @@ -185,29 +185,32 @@ private predicate hasGuard(SsaVariable v, SsaReadPosition pos, Sign s) { s = TZero() and zeroBound(_, v, pos) } +/** + * Gets a possible sign of `v` at `pos` based on its definition, where the sign + * might be ruled out by a guard. + */ pragma[noinline] private Sign guardedSsaSign(SsaVariable v, SsaReadPosition pos) { - // SSA variable can have sign `result` result = ssaDefSign(v) and pos.hasReadOfVar(v) and - // there are guards at this position on `v` that might restrict it to be sign `result`. - // (So we need to check if they are satisfied) hasGuard(v, pos, result) } +/** + * Gets a possible sign of `v` at `pos` based on its definition, where no guard + * can rule it out. + */ pragma[noinline] private Sign unguardedSsaSign(SsaVariable v, SsaReadPosition pos) { - // SSA variable can have sign `result` result = ssaDefSign(v) and pos.hasReadOfVar(v) and - // there's no guard at this position on `v` that might restrict it to be sign `result`. not hasGuard(v, pos, result) } /** - * Gets the sign of `v` at read position `pos`, when there's at least one guard - * on `v` at position `pos`. Each bound corresponding to a given sign must be met - * in order for `v` to be of that sign. + * Gets a possible sign of `v` at read position `pos`, where a guard could have + * ruled out the sign but does not. + * This does not check that the definition of `v` also allows the sign. */ private Sign guardedSsaSignOk(SsaVariable v, SsaReadPosition pos) { result = TPos() and @@ -221,7 +224,7 @@ private Sign guardedSsaSignOk(SsaVariable v, SsaReadPosition pos) { } /** Gets a possible sign for `v` at `pos`. */ -Sign ssaSign(SsaVariable v, SsaReadPosition pos) { +private Sign ssaSign(SsaVariable v, SsaReadPosition pos) { result = unguardedSsaSign(v, pos) or result = guardedSsaSign(v, pos) and @@ -230,7 +233,7 @@ Sign ssaSign(SsaVariable v, SsaReadPosition pos) { /** Gets a possible sign for `v`. */ pragma[nomagic] -Sign ssaDefSign(SsaVariable v) { +private Sign ssaDefSign(SsaVariable v) { result = explicitSsaDefSign(v) or result = implicitSsaDefSign(v) @@ -250,18 +253,23 @@ Sign exprSign(Expr e) { or not exists(certainExprSign(e)) and ( - unknownSign(e) + anySign(s) and unknownSign(e) or - exists(SsaVariable v | getARead(v) = e | s = ssaVariableSign(v, e)) + exists(SsaVariable v | getARead(v) = e | + s = ssaSign(v, any(SsaReadPositionBlock bb | getAnExpression(bb) = e)) + or + not exists(SsaReadPositionBlock bb | getAnExpression(bb) = e) and + s = ssaDefSign(v) + ) or - e = - any(VarAccess access | - not exists(SsaVariable v | getARead(v) = access) and - ( - s = fieldSign(getField(access.(FieldAccess))) or - not access instanceof FieldAccess - ) + exists(VarAccess access | access = e | + not exists(SsaVariable v | getARead(v) = access) and + ( + s = fieldSign(getField(access.(FieldAccess))) + or + anySign(s) and not access instanceof FieldAccess ) + ) or s = specificSubExprSign(e) ) @@ -272,6 +280,12 @@ Sign exprSign(Expr e) { ) } +/** + * Dummy predicate that holds for any sign. This is added to improve readability + * of cases where the sign is unrestricted. + */ +predicate anySign(Sign s) { any() } + /** Holds if `e` can be positive and cannot be negative. */ predicate positive(Expr e) { exprSign(e) = TPos() and diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index 8e030c9a53f..cbca875c8c2 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -55,14 +55,22 @@ private module Impl { class UnsignedNumericType = CharacterType; + /** + * Gets the `float` value of expression `e` where `e` has no `int` value. + */ float getNonIntegerValue(Expr e) { result = e.(LongLiteral).getValue().toFloat() or result = e.(FloatingPointLiteral).getValue().toFloat() or result = e.(DoubleLiteral).getValue().toFloat() } + /** Gets the character value of expression `e`. */ string getCharValue(Expr e) { result = e.(CharacterLiteral).getValue() } + /** + * Holds if `e` is an access to the size of a container (`string`, `Map`, or + * `Collection`). + */ predicate containerSizeAccess(Expr e) { e.(MethodAccess).getMethod() instanceof StringLengthMethod or @@ -71,8 +79,15 @@ private module Impl { e.(MethodAccess).getMethod() instanceof MapSizeMethod } + /** Holds if `e` is by definition strictly positive. */ predicate positiveExpression(Expr e) { none() } + /** + * Holds if `e` has type `NumericOrCharType`, but the sign of `e` is unknown. + * + * The expression types handled in the predicate complements the expression + * types handled in `specificSubExprSign`. + */ predicate unknownIntegerAccess(Expr e) { e instanceof ArrayAccess and e.getType() instanceof NumericOrCharType or @@ -81,6 +96,7 @@ private module Impl { e instanceof ClassInstanceExpr and e.getType() instanceof NumericOrCharType } + /** Returns the sign of explicit SSA definition `v`. */ Sign explicitSsaDefSign(SsaVariable v) { exists(VariableUpdate def | def = v.(SsaExplicitUpdate).getDefiningExpr() | result = exprSign(def.(VariableAssign).getSource()) @@ -99,20 +115,13 @@ private module Impl { ) } + /** Returns the sign of implicit SSA definition `v`. */ Sign implicitSsaDefSign(SsaVariable v) { result = fieldSign(v.(SsaImplicitUpdate).getSourceVariable().getVariable()) or result = fieldSign(v.(SsaImplicitInit).getSourceVariable().getVariable()) or - exists(Parameter p | v.(SsaImplicitInit).isParameterDefinition(p)) - } - - pragma[inline] - Sign ssaVariableSign(SsaVariable v, Expr e) { - result = ssaSign(v, any(SsaReadPositionBlock bb | getAnExpression(bb) = e)) - or - not exists(SsaReadPositionBlock bb | getAnExpression(bb) = e) and - result = ssaDefSign(v) + anySign(result) and exists(Parameter p | v.(SsaImplicitInit).isParameterDefinition(p)) } /** Gets a possible sign for `f`. */ @@ -129,7 +138,7 @@ private module Impl { or exists(AssignOp a | a.getDest() = f.getAnAccess() | result = exprSign(a)) or - exists(ReflectiveFieldAccess rfa | rfa.inferAccessedField() = f) + anySign(result) and exists(ReflectiveFieldAccess rfa | rfa.inferAccessedField() = f) or if f.fromSource() then not exists(f.getInitializer()) and result = TZero() @@ -142,9 +151,10 @@ private module Impl { else if f.hasName("MIN_VALUE") then result = TNeg() - else any() + else anySign(result) } + /** Gets a possible sign for `e` from the signs of its child nodes. */ Sign specificSubExprSign(Expr e) { result = exprSign(e.(AssignExpr).getSource()) or From 7545fe74e3c2ea69384f199cb6c4fc80ddaa9719 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 29 Sep 2020 12:10:35 +0200 Subject: [PATCH 163/411] Java, C#: Refactor implicitSsaDefSign in sign analysis --- .../rangeanalysis/SignAnalysisCommon.qll | 7 +++++++ .../rangeanalysis/SignAnalysisSpecific.qll | 13 ++++++++----- .../rangeanalysis/SignAnalysisCommon.qll | 7 +++++++ .../rangeanalysis/SignAnalysisSpecific.qll | 16 +++++++++------- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index 33ef5d3683f..37183f13f8d 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -245,6 +245,13 @@ private Sign ssaDefSign(SsaVariable v) { ) } +/** Returns the sign of implicit SSA definition `v`. */ +private Sign implicitSsaDefSign(SsaVariable v) { + result = fieldSign(getImplicitSsaDeclaration(v)) + or + anySign(result) and nonFieldImplicitSsaDefinition(v) +} + /** Gets a possible sign for `e`. */ cached Sign exprSign(Expr e) { diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index 00f68fa85df..5d0f92d6c2a 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -122,11 +122,14 @@ private module Impl { ) } - /** Returns the sign of implicit SSA definition `v`. */ - Sign implicitSsaDefSign(Ssa::ImplicitDefinition v) { - result = fieldSign(v.getSourceVariable().getAssignable()) - or - anySign(result) and not v.getSourceVariable().getAssignable() instanceof Field + /** Gets the variable underlying the implicit SSA variable `v`. */ + Declaration getImplicitSsaDeclaration(Ssa::ImplicitDefinition v) { + result = v.getSourceVariable().getAssignable() + } + + /** Holds if the variable underlying the implicit SSA variable `v` is not a field. */ + predicate nonFieldImplicitSsaDefinition(Ssa::ImplicitDefinition v) { + not getImplicitSsaDeclaration(v) instanceof Field } /** Gets a possible sign for `f`. */ diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index 33ef5d3683f..37183f13f8d 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -245,6 +245,13 @@ private Sign ssaDefSign(SsaVariable v) { ) } +/** Returns the sign of implicit SSA definition `v`. */ +private Sign implicitSsaDefSign(SsaVariable v) { + result = fieldSign(getImplicitSsaDeclaration(v)) + or + anySign(result) and nonFieldImplicitSsaDefinition(v) +} + /** Gets a possible sign for `e`. */ cached Sign exprSign(Expr e) { diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index cbca875c8c2..74466990725 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -115,13 +115,15 @@ private module Impl { ) } - /** Returns the sign of implicit SSA definition `v`. */ - Sign implicitSsaDefSign(SsaVariable v) { - result = fieldSign(v.(SsaImplicitUpdate).getSourceVariable().getVariable()) - or - result = fieldSign(v.(SsaImplicitInit).getSourceVariable().getVariable()) - or - anySign(result) and exists(Parameter p | v.(SsaImplicitInit).isParameterDefinition(p)) + /** Gets the variable underlying the implicit SSA variable `v`. */ + Variable getImplicitSsaDeclaration(SsaVariable v) { + result = v.(SsaImplicitUpdate).getSourceVariable().getVariable() or + result = v.(SsaImplicitInit).getSourceVariable().getVariable() + } + + /** Holds if the variable underlying the implicit SSA variable `v` is not a field. */ + predicate nonFieldImplicitSsaDefinition(SsaImplicitInit v) { + exists(Parameter p | v.isParameterDefinition(p)) } /** Gets a possible sign for `f`. */ From 638d0399a8b0173dde4aa228202c6d8a00e06364 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 29 Sep 2020 12:49:42 +0200 Subject: [PATCH 164/411] Java, C#: Refactor explicitSsaDefSign in sign analysis --- .../rangeanalysis/SignAnalysisCommon.qll | 13 ++++++ .../rangeanalysis/SignAnalysisSpecific.qll | 37 ++++++++++------ .../rangeanalysis/SignAnalysisCommon.qll | 13 ++++++ .../rangeanalysis/SignAnalysisSpecific.qll | 44 ++++++++++++------- 4 files changed, 77 insertions(+), 30 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index 37183f13f8d..d8be98334a4 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -245,6 +245,19 @@ private Sign ssaDefSign(SsaVariable v) { ) } +/** Returns the sign of explicit SSA definition `v`. */ +Sign explicitSsaDefSign(SsaVariable v) { + exists(VariableUpdate def | def = getExplicitSsaAssignment(v) | + result = exprSign(getExprFromSsaAssignment(def)) + or + anySign(result) and explicitSsaDefWithAnySign(def) + or + result = exprSign(getIncrementOperand(def)).inc() + or + result = exprSign(getDecrementOperand(def)).dec() + ) +} + /** Returns the sign of implicit SSA definition `v`. */ private Sign implicitSsaDefSign(SsaVariable v) { result = fieldSign(getImplicitSsaDeclaration(v)) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index 5d0f92d6c2a..b9d66e93e9b 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -32,6 +32,8 @@ module Private { class Expr = CS::Expr; + class VariableUpdate = CS::AssignableDefinition; + predicate ssaRead = SU::ssaRead/2; } @@ -107,19 +109,28 @@ private module Impl { } } - /** Returns the sign of explicit SSA definition `v`. */ - Sign explicitSsaDefSign(Ssa::ExplicitDefinition v) { - exists(AssignableDefinition def | def = v.getADefinition() | - result = exprSign(def.getSource()) - or - anySign(result) and - not exists(def.getSource()) and - not def.getElement() instanceof MutatorOperation - or - result = exprSign(def.getElement().(IncrementOperation).getOperand()).inc() - or - result = exprSign(def.getElement().(DecrementOperation).getOperand()).dec() - ) + /** Returns the underlying variable update of the explicit SSA variable `v`. */ + AssignableDefinition getExplicitSsaAssignment(Ssa::ExplicitDefinition v) { + result = v.getADefinition() + } + + /** Returns the assignment of the variable update `def`. */ + Expr getExprFromSsaAssignment(AssignableDefinition def) { result = def.getSource() } + + /** Holds if `def` can have any sign. */ + predicate explicitSsaDefWithAnySign(AssignableDefinition def) { + not exists(def.getSource()) and + not def.getElement() instanceof MutatorOperation + } + + /** Returns the operand of the operation if `def` is a decrement. */ + Expr getDecrementOperand(AssignableDefinition def) { + result = def.getElement().(DecrementOperation).getOperand() + } + + /** Returns the operand of the operation if `def` is an increment. */ + Expr getIncrementOperand(AssignableDefinition def) { + result = def.getElement().(IncrementOperation).getOperand() } /** Gets the variable underlying the implicit SSA variable `v`. */ diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index 37183f13f8d..d8be98334a4 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -245,6 +245,19 @@ private Sign ssaDefSign(SsaVariable v) { ) } +/** Returns the sign of explicit SSA definition `v`. */ +Sign explicitSsaDefSign(SsaVariable v) { + exists(VariableUpdate def | def = getExplicitSsaAssignment(v) | + result = exprSign(getExprFromSsaAssignment(def)) + or + anySign(result) and explicitSsaDefWithAnySign(def) + or + result = exprSign(getIncrementOperand(def)).inc() + or + result = exprSign(getDecrementOperand(def)).dec() + ) +} + /** Returns the sign of implicit SSA definition `v`. */ private Sign implicitSsaDefSign(SsaVariable v) { result = fieldSign(getImplicitSsaDeclaration(v)) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index 74466990725..0f0188f45a1 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -36,6 +36,8 @@ module Private { class NumericOrCharType = J::NumericOrCharType; + class VariableUpdate = J::VariableUpdate; + predicate ssaRead = RU::ssaRead/2; predicate guardControlsSsaRead = RU::guardControlsSsaRead/3; @@ -96,23 +98,31 @@ private module Impl { e instanceof ClassInstanceExpr and e.getType() instanceof NumericOrCharType } - /** Returns the sign of explicit SSA definition `v`. */ - Sign explicitSsaDefSign(SsaVariable v) { - exists(VariableUpdate def | def = v.(SsaExplicitUpdate).getDefiningExpr() | - result = exprSign(def.(VariableAssign).getSource()) - or - exists(EnhancedForStmt for | def = for.getVariable()) - or - result = exprSign(def.(PostIncExpr).getExpr()).inc() - or - result = exprSign(def.(PreIncExpr).getExpr()).inc() - or - result = exprSign(def.(PostDecExpr).getExpr()).dec() - or - result = exprSign(def.(PreDecExpr).getExpr()).dec() - or - exists(AssignOp a | a = def and result = exprSign(a)) - ) + /** Returns the underlying variable update of the explicit SSA variable `v`. */ + VariableUpdate getExplicitSsaAssignment(SsaVariable v) { + result = v.(SsaExplicitUpdate).getDefiningExpr() + } + + /** Returns the assignment of the variable update `def`. */ + Expr getExprFromSsaAssignment(VariableUpdate def) { + result = def.(VariableAssign).getSource() + or + exists(AssignOp a | a = def and result = a) + } + + /** Holds if `def` can have any sign. */ + predicate explicitSsaDefWithAnySign(VariableUpdate def) { + exists(EnhancedForStmt for | def = for.getVariable()) + } + + /** Returns the operand of the operation if `def` is a decrement. */ + Expr getDecrementOperand(Element e) { + result = e.(PostDecExpr).getExpr() or result = e.(PreDecExpr).getExpr() + } + + /** Returns the operand of the operation if `def` is an increment. */ + Expr getIncrementOperand(Element e) { + result = e.(PostIncExpr).getExpr() or result = e.(PreIncExpr).getExpr() } /** Gets the variable underlying the implicit SSA variable `v`. */ From 21ff1a0445dc9c8d6a9513a96fa1c87fc29f6ba3 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 29 Sep 2020 14:53:59 +0200 Subject: [PATCH 165/411] Address some of the PR review findings --- .../rangeanalysis/SignAnalysisCommon.qll | 16 ++++++++++++++-- .../rangeanalysis/SignAnalysisSpecific.qll | 16 +++------------- .../rangeanalysis/SignAnalysisCommon.qll | 16 ++++++++++++++-- .../rangeanalysis/SignAnalysisSpecific.qll | 18 +++++------------- .../dataflow/sign-analysis/SignAnalysis.ql | 1 + 5 files changed, 37 insertions(+), 30 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index d8be98334a4..433fa3ef00c 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -41,6 +41,18 @@ private Sign certainExprSign(Expr e) { ) } +/** + * Gets the value of the expression if it can't be converted to integer, but + * can be converted to float. + */ +float getNonIntegerValue(ExprWithPossibleValue e) { + exists(string s | + s = e.getValue() and + result = s.toFloat() and + not exists(s.toInt()) + ) +} + /** Holds if the sign of `e` is too complicated to determine. */ predicate unknownSign(Expr e) { not exists(certainExprSign(e)) and @@ -55,7 +67,7 @@ predicate unknownSign(Expr e) { not fromtyp instanceof NumericOrCharType ) or - unknownIntegerAccess(e) + numericExprWithUnknownSign(e) ) } @@ -246,7 +258,7 @@ private Sign ssaDefSign(SsaVariable v) { } /** Returns the sign of explicit SSA definition `v`. */ -Sign explicitSsaDefSign(SsaVariable v) { +private Sign explicitSsaDefSign(SsaVariable v) { exists(VariableUpdate def | def = getExplicitSsaAssignment(v) | result = exprSign(getExprFromSsaAssignment(def)) or diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index b9d66e93e9b..46566ef6283 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -34,6 +34,8 @@ module Private { class VariableUpdate = CS::AssignableDefinition; + class ExprWithPossibleValue = CS::Expr; + predicate ssaRead = SU::ssaRead/2; } @@ -50,18 +52,6 @@ private module Impl { private class BooleanValue = AbstractValues::BooleanValue; - /** - * Gets the value of the expression if it can't be converted to integer, but - * can be converted to float. - */ - float getNonIntegerValue(Expr e) { - exists(string s | - s = e.getValue() and - result = s.toFloat() and - not exists(s.toInt()) - ) - } - /** Gets the character value of expression `e`. */ string getCharValue(Expr e) { result = e.getValue() and e.getType() instanceof CharType } @@ -162,7 +152,7 @@ private module Impl { /** * Holds if `e` has type `NumericOrCharType`, but the sign of `e` is unknown. */ - predicate unknownIntegerAccess(Expr e) { + predicate numericExprWithUnknownSign(Expr e) { e.getType() instanceof NumericOrCharType and not e = getARead(_) and not e instanceof FieldAccess and diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index d8be98334a4..433fa3ef00c 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -41,6 +41,18 @@ private Sign certainExprSign(Expr e) { ) } +/** + * Gets the value of the expression if it can't be converted to integer, but + * can be converted to float. + */ +float getNonIntegerValue(ExprWithPossibleValue e) { + exists(string s | + s = e.getValue() and + result = s.toFloat() and + not exists(s.toInt()) + ) +} + /** Holds if the sign of `e` is too complicated to determine. */ predicate unknownSign(Expr e) { not exists(certainExprSign(e)) and @@ -55,7 +67,7 @@ predicate unknownSign(Expr e) { not fromtyp instanceof NumericOrCharType ) or - unknownIntegerAccess(e) + numericExprWithUnknownSign(e) ) } @@ -246,7 +258,7 @@ private Sign ssaDefSign(SsaVariable v) { } /** Returns the sign of explicit SSA definition `v`. */ -Sign explicitSsaDefSign(SsaVariable v) { +private Sign explicitSsaDefSign(SsaVariable v) { exists(VariableUpdate def | def = getExplicitSsaAssignment(v) | result = exprSign(getExprFromSsaAssignment(def)) or diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index 0f0188f45a1..63ad5246aa0 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -38,6 +38,8 @@ module Private { class VariableUpdate = J::VariableUpdate; + class ExprWithPossibleValue = J::Literal; + predicate ssaRead = RU::ssaRead/2; predicate guardControlsSsaRead = RU::guardControlsSsaRead/3; @@ -57,15 +59,6 @@ private module Impl { class UnsignedNumericType = CharacterType; - /** - * Gets the `float` value of expression `e` where `e` has no `int` value. - */ - float getNonIntegerValue(Expr e) { - result = e.(LongLiteral).getValue().toFloat() or - result = e.(FloatingPointLiteral).getValue().toFloat() or - result = e.(DoubleLiteral).getValue().toFloat() - } - /** Gets the character value of expression `e`. */ string getCharValue(Expr e) { result = e.(CharacterLiteral).getValue() } @@ -86,11 +79,10 @@ private module Impl { /** * Holds if `e` has type `NumericOrCharType`, but the sign of `e` is unknown. - * - * The expression types handled in the predicate complements the expression - * types handled in `specificSubExprSign`. */ - predicate unknownIntegerAccess(Expr e) { + predicate numericExprWithUnknownSign(Expr e) { + // The expression types handled in the predicate complements the expression + // types handled in `specificSubExprSign`. e instanceof ArrayAccess and e.getType() instanceof NumericOrCharType or e instanceof MethodAccess and e.getType() instanceof NumericOrCharType diff --git a/java/ql/test/library-tests/dataflow/sign-analysis/SignAnalysis.ql b/java/ql/test/library-tests/dataflow/sign-analysis/SignAnalysis.ql index bc4fed33dc8..e47081a0094 100644 --- a/java/ql/test/library-tests/dataflow/sign-analysis/SignAnalysis.ql +++ b/java/ql/test/library-tests/dataflow/sign-analysis/SignAnalysis.ql @@ -18,4 +18,5 @@ string getASignString(Expr e) { } from Expr e +where not e instanceof Element or e.(Element).fromSource() select e, strictconcat(string s | s = getASignString(e) | s, " ") From f03146d12f68c7b8f16657c1851e5109dc41fc63 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 29 Sep 2020 15:26:20 +0200 Subject: [PATCH 166/411] Refactor fieldSign --- .../rangeanalysis/SignAnalysisCommon.qll | 14 ++++++ .../rangeanalysis/SignAnalysisSpecific.qll | 37 ++++++++++------ .../rangeanalysis/SignAnalysisCommon.qll | 14 ++++++ .../rangeanalysis/SignAnalysisSpecific.qll | 43 ++++++++++++------- 4 files changed, 78 insertions(+), 30 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index 433fa3ef00c..a33f2ae65f3 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -277,6 +277,20 @@ private Sign implicitSsaDefSign(SsaVariable v) { anySign(result) and nonFieldImplicitSsaDefinition(v) } +/** Gets a possible sign for `f`. */ +Sign fieldSign(Field f) { + if not fieldWithUnknownSign(f) + then + result = exprSign(getAssignedValueToField(f)) + or + fieldIncrementOperationOperand(f) and result = fieldSign(f).inc() + or + fieldDecrementOperationOperand(f) and result = fieldSign(f).dec() + or + result = specificFieldSign(f) + else anySign(result) +} + /** Gets a possible sign for `e`. */ cached Sign exprSign(Expr e) { diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index 46566ef6283..bae757447da 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -36,6 +36,8 @@ module Private { class ExprWithPossibleValue = CS::Expr; + class Field = CS::Field; + predicate ssaRead = SU::ssaRead/2; } @@ -133,22 +135,29 @@ private module Impl { not getImplicitSsaDeclaration(v) instanceof Field } - /** Gets a possible sign for `f`. */ - Sign fieldSign(Field f) { - if f.fromSource() and f.isEffectivelyPrivate() - then - result = exprSign(f.getAnAssignedValue()) - or - any(IncrementOperation inc).getOperand() = f.getAnAccess() and result = fieldSign(f).inc() - or - any(DecrementOperation dec).getOperand() = f.getAnAccess() and result = fieldSign(f).dec() - or - exists(AssignOperation a | a.getLValue() = f.getAnAccess() | result = exprSign(a)) - or - not exists(f.getInitializer()) and result = TZero() - else anySign(result) + /** Returned an expression that is assigned to `f`. */ + Expr getAssignedValueToField(Field f) { + result = f.getAnAssignedValue() or + result = any(AssignOperation a | a.getLValue() = f.getAnAccess()) } + /** Holds if `f` can have any sign. */ + predicate fieldWithUnknownSign(Field f) { not f.fromSource() or not f.isEffectivelyPrivate() } + + /** Holds if `f` is accessed in an increment operation. */ + predicate fieldIncrementOperationOperand(Field f) { + any(IncrementOperation inc).getOperand() = f.getAnAccess() + } + + /** Holds if `f` is accessed in a decrement operation. */ + predicate fieldDecrementOperationOperand(Field f) { + any(DecrementOperation dec).getOperand() = f.getAnAccess() + } + + /** Returns possible signs of `f` based on the declaration. */ + pragma[inline] + Sign specificFieldSign(Field f) { not exists(f.getInitializer()) and result = TZero() } + /** * Holds if `e` has type `NumericOrCharType`, but the sign of `e` is unknown. */ diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index 433fa3ef00c..a33f2ae65f3 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -277,6 +277,20 @@ private Sign implicitSsaDefSign(SsaVariable v) { anySign(result) and nonFieldImplicitSsaDefinition(v) } +/** Gets a possible sign for `f`. */ +Sign fieldSign(Field f) { + if not fieldWithUnknownSign(f) + then + result = exprSign(getAssignedValueToField(f)) + or + fieldIncrementOperationOperand(f) and result = fieldSign(f).inc() + or + fieldDecrementOperationOperand(f) and result = fieldSign(f).dec() + or + result = specificFieldSign(f) + else anySign(result) +} + /** Gets a possible sign for `e`. */ cached Sign exprSign(Expr e) { diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index 63ad5246aa0..616433a4502 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -40,6 +40,8 @@ module Private { class ExprWithPossibleValue = J::Literal; + class Field = J::Field; + predicate ssaRead = RU::ssaRead/2; predicate guardControlsSsaRead = RU::guardControlsSsaRead/3; @@ -128,22 +130,31 @@ private module Impl { exists(Parameter p | v.isParameterDefinition(p)) } - /** Gets a possible sign for `f`. */ - Sign fieldSign(Field f) { - result = exprSign(f.getAnAssignedValue()) - or - exists(PostIncExpr inc | inc.getExpr() = f.getAnAccess() and result = fieldSign(f).inc()) - or - exists(PreIncExpr inc | inc.getExpr() = f.getAnAccess() and result = fieldSign(f).inc()) - or - exists(PostDecExpr inc | inc.getExpr() = f.getAnAccess() and result = fieldSign(f).dec()) - or - exists(PreDecExpr inc | inc.getExpr() = f.getAnAccess() and result = fieldSign(f).dec()) - or - exists(AssignOp a | a.getDest() = f.getAnAccess() | result = exprSign(a)) - or - anySign(result) and exists(ReflectiveFieldAccess rfa | rfa.inferAccessedField() = f) - or + /** Returned an expression that is assigned to `f`. */ + Expr getAssignedValueToField(Field f) { + result = f.getAnAssignedValue() or + result = any(AssignOp a | a.getDest() = f.getAnAccess()) + } + + /** Holds if `f` can have any sign. */ + predicate fieldWithUnknownSign(Field f) { + exists(ReflectiveFieldAccess rfa | rfa.inferAccessedField() = f) + } + + /** Holds if `f` is accessed in an increment operation. */ + predicate fieldIncrementOperationOperand(Field f) { + any(PostIncExpr inc).getExpr() = f.getAnAccess() or + any(PreIncExpr inc).getExpr() = f.getAnAccess() + } + + /** Holds if `f` is accessed in a decrement operation. */ + predicate fieldDecrementOperationOperand(Field f) { + any(PostDecExpr dec).getExpr() = f.getAnAccess() or + any(PreDecExpr dec).getExpr() = f.getAnAccess() + } + + /** Returns possible signs of `f` based on the declaration. */ + Sign specificFieldSign(Field f) { if f.fromSource() then not exists(f.getInitializer()) and result = TZero() else From f52cf264ec4014b84174248784321033fc6c33fd Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 29 Sep 2020 16:52:49 +0200 Subject: [PATCH 167/411] Refactor specificSubExprSign --- .../dataflow/internal/rangeanalysis/Sign.qll | 61 +++++ .../rangeanalysis/SignAnalysisCommon.qll | 30 +++ .../rangeanalysis/SignAnalysisSpecific.qll | 154 ++++++------ .../dataflow/internal/rangeanalysis/Sign.qll | 61 +++++ .../rangeanalysis/SignAnalysisCommon.qll | 30 +++ .../rangeanalysis/SignAnalysisSpecific.qll | 219 +++++++++++------- 6 files changed, 404 insertions(+), 151 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/Sign.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/Sign.qll index 10ca946a044..b2058a27114 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/Sign.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/Sign.qll @@ -3,6 +3,25 @@ newtype TSign = TZero() or TPos() +newtype TUnarySignOperation = + TNegOp() or + TIncOp() or + TDecOp() or + TBitNotOp() + +newtype TBinarySignOperation = + TAddOp() or + TSubOp() or + TMulOp() or + TDivOp() or + TRemOp() or + TBitAndOp() or + TBitOrOp() or + TBitXorOp() or + TLShiftOp() or + TRShiftOp() or + TURShiftOp() + /** Class representing expression signs (+, -, 0). */ class Sign extends TSign { /** Gets the string representation of this sign. */ @@ -67,6 +86,12 @@ class Sign extends TSign { this = TNeg() and s = TPos() } + /** + * Gets a possible sign after subtracting an expression with sign `s` from an expression + * that has this sign. + */ + Sign sub(Sign s) { result = add(s.neg()) } + /** * Gets a possible sign after multiplying an expression with sign `s` to an expression * that has this sign. @@ -216,4 +241,40 @@ class Sign extends TSign { or result != TNeg() and this = TPos() and s != TZero() } + + /** Perform `op` on this sign. */ + Sign applyUnaryOp(TUnarySignOperation op) { + op = TIncOp() and result = inc() + or + op = TDecOp() and result = dec() + or + op = TNegOp() and result = neg() + or + op = TBitNotOp() and result = bitnot() + } + + /** Perform `op` on this sign and sign `s`. */ + Sign applyBinaryOp(Sign s, TBinarySignOperation op) { + op = TAddOp() and result = add(s) + or + op = TSubOp() and result = sub(s) + or + op = TMulOp() and result = mul(s) + or + op = TDivOp() and result = div(s) + or + op = TRemOp() and result = rem(s) + or + op = TBitAndOp() and result = bitand(s) + or + op = TBitOrOp() and result = bitor(s) + or + op = TBitXorOp() and result = bitxor(s) + or + op = TLShiftOp() and result = lshift(s) + or + op = TRShiftOp() and result = rshift(s) + or + op = TURShiftOp() and result = urshift(s) + } } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index a33f2ae65f3..bf09dbee83f 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -326,6 +326,36 @@ Sign exprSign(Expr e) { ) } +/** Gets a possible sign for `e` from the signs of its child nodes. */ +Sign specificSubExprSign(Expr e) { + result = exprSign(getASubExpr(e)) + or + e = + any(DivExpr div | + result = exprSign(div.getLeftOperand()) and + result != TZero() and + div.getRightOperand().(RealLiteral).getValue().toFloat() = 0 + ) + or + exists(UnaryExpr unary | unary = e | + result = exprSign(unary.getOperand()).applyUnaryOp(unary.getOp()) + ) + or + exists(Sign s1, Sign s2 | binaryOpSigns(e, s1, s2) | + result = s1.applyBinaryOp(s2, e.(BinaryExpr).getOp()) + ) +} + +pragma[noinline] +private predicate binaryOpSigns(Expr e, Sign lhs, Sign rhs) { + lhs = binaryOpLhsSign(e) and + rhs = binaryOpRhsSign(e) +} + +Sign binaryOpLhsSign(BinaryOperation e) { result = exprSign(e.getLeftOperand()) } + +Sign binaryOpRhsSign(BinaryOperation e) { result = exprSign(e.getRightOperand()) } + /** * Dummy predicate that holds for any sign. This is added to improve readability * of cases where the sign is unrestricted. diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index bae757447da..ef1bff62f40 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -38,6 +38,12 @@ module Private { class Field = CS::Field; + class RealLiteral = CS::RealLiteral; + + class DivExpr = CS::DivExpr; + + class BinaryOperation = CS::BinaryOperation; + predicate ssaRead = SU::ssaRead/2; } @@ -196,80 +202,88 @@ private module Impl { not e instanceof NullCoalescingExpr } - /** Gets a possible sign for `e` from the signs of its child nodes. */ - Sign specificSubExprSign(Expr e) { - // The expression types that are handled here should be excluded in `unknownIntegerAccess`. - // Keep them in sync. - result = exprSign(e.(AssignExpr).getRValue()) - or - result = exprSign(e.(AssignOperation).getExpandedAssignment()) - or - result = exprSign(e.(UnaryPlusExpr).getOperand()) - or - result = exprSign(e.(PostIncrExpr).getOperand()) - or - result = exprSign(e.(PostDecrExpr).getOperand()) - or - result = exprSign(e.(PreIncrExpr).getOperand()).inc() - or - result = exprSign(e.(PreDecrExpr).getOperand()).dec() - or - result = exprSign(e.(UnaryMinusExpr).getOperand()).neg() - or - result = exprSign(e.(ComplementExpr).getOperand()).bitnot() - or - e = - any(DivExpr div | - result = exprSign(div.getLeftOperand()) and - result != TZero() and - div.getRightOperand().(RealLiteral).getValue().toFloat() = 0 - ) - or - exists(Sign s1, Sign s2 | binaryOpSigns(e, s1, s2) | - e instanceof AddExpr and result = s1.add(s2) - or - e instanceof SubExpr and result = s1.add(s2.neg()) - or - e instanceof MulExpr and result = s1.mul(s2) - or - e instanceof DivExpr and result = s1.div(s2) - or - e instanceof RemExpr and result = s1.rem(s2) - or - e instanceof BitwiseAndExpr and result = s1.bitand(s2) - or - e instanceof BitwiseOrExpr and result = s1.bitor(s2) - or - e instanceof BitwiseXorExpr and result = s1.bitxor(s2) - or - e instanceof LShiftExpr and result = s1.lshift(s2) - or - e instanceof RShiftExpr and result = s1.rshift(s2) - ) - or - result = exprSign(e.(ConditionalExpr).getAChild()) - or - result = exprSign(e.(NullCoalescingExpr).getAChild()) - or - result = exprSign(e.(SwitchExpr).getACase().getBody()) - or - result = exprSign(e.(CastExpr).getExpr()) - or - result = exprSign(e.(SwitchCaseExpr).getBody()) - or - result = exprSign(e.(LocalVariableDeclAndInitExpr).getInitializer()) - or - result = exprSign(e.(RefExpr).getExpr()) + /** Returns a sub expression of `e` for expression types where the sign depends on the child. */ + Expr getASubExpr(Expr e) { + result = e.(AssignExpr).getRValue() or + result = e.(AssignOperation).getExpandedAssignment() or + result = e.(UnaryPlusExpr).getOperand() or + result = e.(PostIncrExpr).getOperand() or + result = e.(PostDecrExpr).getOperand() or + result = e.(ConditionalExpr).getAChild() or + result = e.(NullCoalescingExpr).getAChild() or + result = e.(SwitchExpr).getACase().getBody() or + result = e.(SwitchCaseExpr).getBody() or + result = e.(LocalVariableDeclAndInitExpr).getInitializer() or + result = e.(RefExpr).getExpr() or + result = e.(CastExpr).getExpr() } - private Sign binaryOpLhsSign(BinaryOperation e) { result = exprSign(e.getLeftOperand()) } + /** Class to represent unary expressions. */ + class UnaryExpr extends Expr { + UnaryExpr() { + this instanceof PreIncrExpr or + this instanceof PreDecrExpr or + this instanceof UnaryMinusExpr or + this instanceof ComplementExpr + } - private Sign binaryOpRhsSign(BinaryOperation e) { result = exprSign(e.getRightOperand()) } + /** Returns the operand of this expression. */ + Expr getOperand() { + result = this.(PreIncrExpr).getOperand() or + result = this.(PreDecrExpr).getOperand() or + result = this.(UnaryMinusExpr).getOperand() or + result = this.(ComplementExpr).getOperand() + } - pragma[noinline] - private predicate binaryOpSigns(Expr e, Sign lhs, Sign rhs) { - lhs = binaryOpLhsSign(e) and - rhs = binaryOpRhsSign(e) + /** Returns the operation representing this expression. */ + TUnarySignOperation getOp() { + this instanceof PreIncrExpr and result = TIncOp() + or + this instanceof PreDecrExpr and result = TDecOp() + or + this instanceof UnaryMinusExpr and result = TNegOp() + or + this instanceof ComplementExpr and result = TBitNotOp() + } + } + + /** Class to represent binary expressions. */ + class BinaryExpr extends Expr { + BinaryExpr() { + this instanceof AddExpr or + this instanceof SubExpr or + this instanceof MulExpr or + this instanceof DivExpr or + this instanceof RemExpr or + this instanceof BitwiseAndExpr or + this instanceof BitwiseOrExpr or + this instanceof BitwiseXorExpr or + this instanceof LShiftExpr or + this instanceof RShiftExpr + } + + /** Returns the operation representing this expression. */ + TBinarySignOperation getOp() { + this instanceof AddExpr and result = TAddOp() + or + this instanceof SubExpr and result = TSubOp() + or + this instanceof MulExpr and result = TMulOp() + or + this instanceof DivExpr and result = TDivOp() + or + this instanceof RemExpr and result = TRemOp() + or + this instanceof BitwiseAndExpr and result = TBitAndOp() + or + this instanceof BitwiseOrExpr and result = TBitOrOp() + or + this instanceof BitwiseXorExpr and result = TBitXorOp() + or + this instanceof LShiftExpr and result = TLShiftOp() + or + this instanceof RShiftExpr and result = TRShiftOp() + } } Expr getARead(Ssa::Definition v) { result = v.getARead() } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/Sign.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/Sign.qll index 10ca946a044..b2058a27114 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/Sign.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/Sign.qll @@ -3,6 +3,25 @@ newtype TSign = TZero() or TPos() +newtype TUnarySignOperation = + TNegOp() or + TIncOp() or + TDecOp() or + TBitNotOp() + +newtype TBinarySignOperation = + TAddOp() or + TSubOp() or + TMulOp() or + TDivOp() or + TRemOp() or + TBitAndOp() or + TBitOrOp() or + TBitXorOp() or + TLShiftOp() or + TRShiftOp() or + TURShiftOp() + /** Class representing expression signs (+, -, 0). */ class Sign extends TSign { /** Gets the string representation of this sign. */ @@ -67,6 +86,12 @@ class Sign extends TSign { this = TNeg() and s = TPos() } + /** + * Gets a possible sign after subtracting an expression with sign `s` from an expression + * that has this sign. + */ + Sign sub(Sign s) { result = add(s.neg()) } + /** * Gets a possible sign after multiplying an expression with sign `s` to an expression * that has this sign. @@ -216,4 +241,40 @@ class Sign extends TSign { or result != TNeg() and this = TPos() and s != TZero() } + + /** Perform `op` on this sign. */ + Sign applyUnaryOp(TUnarySignOperation op) { + op = TIncOp() and result = inc() + or + op = TDecOp() and result = dec() + or + op = TNegOp() and result = neg() + or + op = TBitNotOp() and result = bitnot() + } + + /** Perform `op` on this sign and sign `s`. */ + Sign applyBinaryOp(Sign s, TBinarySignOperation op) { + op = TAddOp() and result = add(s) + or + op = TSubOp() and result = sub(s) + or + op = TMulOp() and result = mul(s) + or + op = TDivOp() and result = div(s) + or + op = TRemOp() and result = rem(s) + or + op = TBitAndOp() and result = bitand(s) + or + op = TBitOrOp() and result = bitor(s) + or + op = TBitXorOp() and result = bitxor(s) + or + op = TLShiftOp() and result = lshift(s) + or + op = TRShiftOp() and result = rshift(s) + or + op = TURShiftOp() and result = urshift(s) + } } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index a33f2ae65f3..bf09dbee83f 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -326,6 +326,36 @@ Sign exprSign(Expr e) { ) } +/** Gets a possible sign for `e` from the signs of its child nodes. */ +Sign specificSubExprSign(Expr e) { + result = exprSign(getASubExpr(e)) + or + e = + any(DivExpr div | + result = exprSign(div.getLeftOperand()) and + result != TZero() and + div.getRightOperand().(RealLiteral).getValue().toFloat() = 0 + ) + or + exists(UnaryExpr unary | unary = e | + result = exprSign(unary.getOperand()).applyUnaryOp(unary.getOp()) + ) + or + exists(Sign s1, Sign s2 | binaryOpSigns(e, s1, s2) | + result = s1.applyBinaryOp(s2, e.(BinaryExpr).getOp()) + ) +} + +pragma[noinline] +private predicate binaryOpSigns(Expr e, Sign lhs, Sign rhs) { + lhs = binaryOpLhsSign(e) and + rhs = binaryOpRhsSign(e) +} + +Sign binaryOpLhsSign(BinaryOperation e) { result = exprSign(e.getLeftOperand()) } + +Sign binaryOpRhsSign(BinaryOperation e) { result = exprSign(e.getRightOperand()) } + /** * Dummy predicate that holds for any sign. This is added to improve readability * of cases where the sign is unrestricted. diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index 616433a4502..6f2c1026ea6 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -6,6 +6,7 @@ module Private { private import semmle.code.java.dataflow.SSA as Ssa private import semmle.code.java.controlflow.Guards as G private import java as J + private import Sign import Impl class ConstantIntegerExpr = RU::ConstantIntegerExpr; @@ -42,6 +43,135 @@ module Private { class Field = J::Field; + class DivExpr = J::DivExpr; + + class BinaryOperation extends J::Expr { + BinaryOperation() { + this instanceof J::BinaryExpr or + this instanceof J::AssignOp + } + + Expr getLeftOperand() { + result = this.(J::BinaryExpr).getLeftOperand() or result = this.(J::AssignOp).getDest() + } + + Expr getRightOperand() { + result = this.(J::BinaryExpr).getRightOperand() or result = this.(J::AssignOp).getRhs() + } + } + + /** Class to represent float and double literals. */ + class RealLiteral extends J::Literal { + RealLiteral() { + this instanceof J::FloatingPointLiteral or + this instanceof J::DoubleLiteral + } + } + + /** Class to represent unary expressions. */ + class UnaryExpr extends J::Expr { + UnaryExpr() { + this instanceof J::PreIncExpr or + this instanceof J::PreDecExpr or + this instanceof J::MinusExpr or + this instanceof J::BitNotExpr + } + + /** Returns the operand of this expression. */ + Expr getOperand() { + result = this.(J::PreIncExpr).getExpr() or + result = this.(J::PreDecExpr).getExpr() or + result = this.(J::MinusExpr).getExpr() or + result = this.(J::BitNotExpr).getExpr() + } + + /** Returns the operation representing this expression. */ + TUnarySignOperation getOp() { + this instanceof J::PreIncExpr and result = TIncOp() + or + this instanceof J::PreDecExpr and result = TDecOp() + or + this instanceof J::MinusExpr and result = TNegOp() + or + this instanceof J::BitNotExpr and result = TBitNotOp() + } + } + + /** Class to represent binary expressions. */ + class BinaryExpr extends J::Expr { + BinaryExpr() { + this instanceof J::AddExpr or + this instanceof J::AssignAddExpr or + this instanceof J::SubExpr or + this instanceof J::AssignSubExpr or + this instanceof J::MulExpr or + this instanceof J::AssignMulExpr or + this instanceof J::DivExpr or + this instanceof J::AssignDivExpr or + this instanceof J::RemExpr or + this instanceof J::AssignRemExpr or + this instanceof J::AndBitwiseExpr or + this instanceof J::AssignAndExpr or + this instanceof J::OrBitwiseExpr or + this instanceof J::AssignOrExpr or + this instanceof J::XorBitwiseExpr or + this instanceof J::AssignXorExpr or + this instanceof J::LShiftExpr or + this instanceof J::AssignLShiftExpr or + this instanceof J::RShiftExpr or + this instanceof J::AssignRShiftExpr or + this instanceof J::URShiftExpr or + this instanceof J::AssignURShiftExpr + } + + /** Returns the operation representing this expression. */ + TBinarySignOperation getOp() { + this instanceof J::AddExpr and result = TAddOp() + or + this instanceof J::AssignAddExpr and result = TAddOp() + or + this instanceof J::SubExpr and result = TSubOp() + or + this instanceof J::AssignSubExpr and result = TSubOp() + or + this instanceof J::MulExpr and result = TMulOp() + or + this instanceof J::AssignMulExpr and result = TMulOp() + or + this instanceof J::DivExpr and result = TDivOp() + or + this instanceof J::AssignDivExpr and result = TDivOp() + or + this instanceof J::RemExpr and result = TRemOp() + or + this instanceof J::AssignRemExpr and result = TRemOp() + or + this instanceof J::AndBitwiseExpr and result = TBitAndOp() + or + this instanceof J::AssignAndExpr and result = TBitAndOp() + or + this instanceof J::OrBitwiseExpr and result = TBitOrOp() + or + this instanceof J::AssignOrExpr and result = TBitOrOp() + or + this instanceof J::XorBitwiseExpr and result = TBitXorOp() + or + this instanceof J::AssignXorExpr and result = TBitXorOp() + or + this instanceof J::LShiftExpr and result = TLShiftOp() + or + this instanceof J::AssignLShiftExpr and result = TLShiftOp() + or + this instanceof J::RShiftExpr and result = TRShiftOp() + or + this instanceof J::AssignRShiftExpr and result = TRShiftOp() + or + this instanceof J::URShiftExpr and result = TURShiftOp() + or + this instanceof J::AssignURShiftExpr and result = TURShiftOp() + } + } + predicate ssaRead = RU::ssaRead/2; predicate guardControlsSsaRead = RU::guardControlsSsaRead/3; @@ -169,87 +299,14 @@ private module Impl { else anySign(result) } - /** Gets a possible sign for `e` from the signs of its child nodes. */ - Sign specificSubExprSign(Expr e) { - result = exprSign(e.(AssignExpr).getSource()) - or - result = exprSign(e.(PlusExpr).getExpr()) - or - result = exprSign(e.(PostIncExpr).getExpr()) - or - result = exprSign(e.(PostDecExpr).getExpr()) - or - result = exprSign(e.(PreIncExpr).getExpr()).inc() - or - result = exprSign(e.(PreDecExpr).getExpr()).dec() - or - result = exprSign(e.(MinusExpr).getExpr()).neg() - or - result = exprSign(e.(BitNotExpr).getExpr()).bitnot() - or - exists(DivExpr div | - div = e and - result = exprSign(div.getLeftOperand()) and - result != TZero() - | - div.getRightOperand().(FloatingPointLiteral).getValue().toFloat() = 0 or - div.getRightOperand().(DoubleLiteral).getValue().toFloat() = 0 - ) - or - exists(Sign s1, Sign s2 | binaryOpSigns(e, s1, s2) | - (e instanceof AssignAddExpr or e instanceof AddExpr) and - result = s1.add(s2) - or - (e instanceof AssignSubExpr or e instanceof SubExpr) and - result = s1.add(s2.neg()) - or - (e instanceof AssignMulExpr or e instanceof MulExpr) and - result = s1.mul(s2) - or - (e instanceof AssignDivExpr or e instanceof DivExpr) and - result = s1.div(s2) - or - (e instanceof AssignRemExpr or e instanceof RemExpr) and - result = s1.rem(s2) - or - (e instanceof AssignAndExpr or e instanceof AndBitwiseExpr) and - result = s1.bitand(s2) - or - (e instanceof AssignOrExpr or e instanceof OrBitwiseExpr) and - result = s1.bitor(s2) - or - (e instanceof AssignXorExpr or e instanceof XorBitwiseExpr) and - result = s1.bitxor(s2) - or - (e instanceof AssignLShiftExpr or e instanceof LShiftExpr) and - result = s1.lshift(s2) - or - (e instanceof AssignRShiftExpr or e instanceof RShiftExpr) and - result = s1.rshift(s2) - or - (e instanceof AssignURShiftExpr or e instanceof URShiftExpr) and - result = s1.urshift(s2) - ) - or - result = exprSign(e.(ChooseExpr).getAResultExpr()) - or - result = exprSign(e.(CastExpr).getExpr()) - } - - private Sign binaryOpLhsSign(Expr e) { - result = exprSign(e.(BinaryExpr).getLeftOperand()) or - result = exprSign(e.(AssignOp).getDest()) - } - - private Sign binaryOpRhsSign(Expr e) { - result = exprSign(e.(BinaryExpr).getRightOperand()) or - result = exprSign(e.(AssignOp).getRhs()) - } - - pragma[noinline] - private predicate binaryOpSigns(Expr e, Sign lhs, Sign rhs) { - lhs = binaryOpLhsSign(e) and - rhs = binaryOpRhsSign(e) + /** Returns a sub expression of `e` for expression types where the sign depends on the child. */ + Expr getASubExpr(Expr e) { + result = e.(AssignExpr).getSource() or + result = e.(PlusExpr).getExpr() or + result = e.(PostIncExpr).getExpr() or + result = e.(PostDecExpr).getExpr() or + result = e.(ChooseExpr).getAResultExpr() or + result = e.(CastExpr).getExpr() } Expr getARead(SsaVariable v) { result = v.getAUse() } From 01de550ef8c1de5cfd880fc2d61121d0089d8b66 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 30 Sep 2020 08:19:05 +0200 Subject: [PATCH 168/411] Make predicates private --- .../internal/rangeanalysis/SignAnalysisCommon.qll | 12 ++++++------ .../internal/rangeanalysis/SignAnalysisCommon.qll | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index bf09dbee83f..64f4a9d10c3 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -45,7 +45,7 @@ private Sign certainExprSign(Expr e) { * Gets the value of the expression if it can't be converted to integer, but * can be converted to float. */ -float getNonIntegerValue(ExprWithPossibleValue e) { +private float getNonIntegerValue(ExprWithPossibleValue e) { exists(string s | s = e.getValue() and result = s.toFloat() and @@ -54,7 +54,7 @@ float getNonIntegerValue(ExprWithPossibleValue e) { } /** Holds if the sign of `e` is too complicated to determine. */ -predicate unknownSign(Expr e) { +private predicate unknownSign(Expr e) { not exists(certainExprSign(e)) and ( exists(IntegerLiteral lit | lit = e and not exists(lit.getValue().toInt())) @@ -278,7 +278,7 @@ private Sign implicitSsaDefSign(SsaVariable v) { } /** Gets a possible sign for `f`. */ -Sign fieldSign(Field f) { +private Sign fieldSign(Field f) { if not fieldWithUnknownSign(f) then result = exprSign(getAssignedValueToField(f)) @@ -327,7 +327,7 @@ Sign exprSign(Expr e) { } /** Gets a possible sign for `e` from the signs of its child nodes. */ -Sign specificSubExprSign(Expr e) { +private Sign specificSubExprSign(Expr e) { result = exprSign(getASubExpr(e)) or e = @@ -352,9 +352,9 @@ private predicate binaryOpSigns(Expr e, Sign lhs, Sign rhs) { rhs = binaryOpRhsSign(e) } -Sign binaryOpLhsSign(BinaryOperation e) { result = exprSign(e.getLeftOperand()) } +private Sign binaryOpLhsSign(BinaryOperation e) { result = exprSign(e.getLeftOperand()) } -Sign binaryOpRhsSign(BinaryOperation e) { result = exprSign(e.getRightOperand()) } +private Sign binaryOpRhsSign(BinaryOperation e) { result = exprSign(e.getRightOperand()) } /** * Dummy predicate that holds for any sign. This is added to improve readability diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index bf09dbee83f..64f4a9d10c3 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -45,7 +45,7 @@ private Sign certainExprSign(Expr e) { * Gets the value of the expression if it can't be converted to integer, but * can be converted to float. */ -float getNonIntegerValue(ExprWithPossibleValue e) { +private float getNonIntegerValue(ExprWithPossibleValue e) { exists(string s | s = e.getValue() and result = s.toFloat() and @@ -54,7 +54,7 @@ float getNonIntegerValue(ExprWithPossibleValue e) { } /** Holds if the sign of `e` is too complicated to determine. */ -predicate unknownSign(Expr e) { +private predicate unknownSign(Expr e) { not exists(certainExprSign(e)) and ( exists(IntegerLiteral lit | lit = e and not exists(lit.getValue().toInt())) @@ -278,7 +278,7 @@ private Sign implicitSsaDefSign(SsaVariable v) { } /** Gets a possible sign for `f`. */ -Sign fieldSign(Field f) { +private Sign fieldSign(Field f) { if not fieldWithUnknownSign(f) then result = exprSign(getAssignedValueToField(f)) @@ -327,7 +327,7 @@ Sign exprSign(Expr e) { } /** Gets a possible sign for `e` from the signs of its child nodes. */ -Sign specificSubExprSign(Expr e) { +private Sign specificSubExprSign(Expr e) { result = exprSign(getASubExpr(e)) or e = @@ -352,9 +352,9 @@ private predicate binaryOpSigns(Expr e, Sign lhs, Sign rhs) { rhs = binaryOpRhsSign(e) } -Sign binaryOpLhsSign(BinaryOperation e) { result = exprSign(e.getLeftOperand()) } +private Sign binaryOpLhsSign(BinaryOperation e) { result = exprSign(e.getLeftOperand()) } -Sign binaryOpRhsSign(BinaryOperation e) { result = exprSign(e.getRightOperand()) } +private Sign binaryOpRhsSign(BinaryOperation e) { result = exprSign(e.getRightOperand()) } /** * Dummy predicate that holds for any sign. This is added to improve readability From 1cf3196b611fc321ed5d30df09f0b38614290263 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 1 Oct 2020 15:52:07 +0200 Subject: [PATCH 169/411] Fix additional PR review findings --- .../rangeanalysis/SignAnalysisCommon.qll | 17 +-- .../rangeanalysis/SignAnalysisSpecific.qll | 139 +++++++++--------- .../rangeanalysis/SignAnalysisCommon.qll | 17 +-- .../rangeanalysis/SignAnalysisSpecific.qll | 37 ++--- .../dataflow/sign-analysis/SignAnalysis.ql | 2 +- 5 files changed, 101 insertions(+), 111 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index 64f4a9d10c3..19412a0ba39 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -328,21 +328,20 @@ Sign exprSign(Expr e) { /** Gets a possible sign for `e` from the signs of its child nodes. */ private Sign specificSubExprSign(Expr e) { - result = exprSign(getASubExpr(e)) + result = exprSign(getASubExprWithSameSign(e)) or - e = - any(DivExpr div | - result = exprSign(div.getLeftOperand()) and - result != TZero() and - div.getRightOperand().(RealLiteral).getValue().toFloat() = 0 - ) + exists(DivExpr div | div = e | + result = exprSign(div.getLeftOperand()) and + result != TZero() and + div.getRightOperand().(RealLiteral).getValue().toFloat() = 0 + ) or - exists(UnaryExpr unary | unary = e | + exists(UnaryOperation unary | unary = e | result = exprSign(unary.getOperand()).applyUnaryOp(unary.getOp()) ) or exists(Sign s1, Sign s2 | binaryOpSigns(e, s1, s2) | - result = s1.applyBinaryOp(s2, e.(BinaryExpr).getOp()) + result = s1.applyBinaryOp(s2, e.(BinaryOperation).getOp()) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index ef1bff62f40..40e07eacbb9 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -6,6 +6,7 @@ module Private { private import csharp as CS private import ConstantUtils as CU private import semmle.code.csharp.controlflow.Guards as G + private import Sign import Impl class Guard = G::Guard; @@ -42,7 +43,73 @@ module Private { class DivExpr = CS::DivExpr; - class BinaryOperation = CS::BinaryOperation; + /** Class to represent unary operation. */ + class UnaryOperation extends Expr { + UnaryOperation() { + this instanceof CS::PreIncrExpr or + this instanceof CS::PreDecrExpr or + this instanceof CS::UnaryMinusExpr or + this instanceof CS::ComplementExpr + } + + /** Returns the operand of this expression. */ + Expr getOperand() { + result = this.(CS::PreIncrExpr).getOperand() or + result = this.(CS::PreDecrExpr).getOperand() or + result = this.(CS::UnaryMinusExpr).getOperand() or + result = this.(CS::ComplementExpr).getOperand() + } + + /** Returns the operation representing this expression. */ + TUnarySignOperation getOp() { + this instanceof CS::PreIncrExpr and result = TIncOp() + or + this instanceof CS::PreDecrExpr and result = TDecOp() + or + this instanceof CS::UnaryMinusExpr and result = TNegOp() + or + this instanceof CS::ComplementExpr and result = TBitNotOp() + } + } + + /** Class to represent binary operation. */ + class BinaryOperation extends CS::BinaryOperation { + BinaryOperation() { + this instanceof CS::AddExpr or + this instanceof CS::SubExpr or + this instanceof CS::MulExpr or + this instanceof CS::DivExpr or + this instanceof CS::RemExpr or + this instanceof CS::BitwiseAndExpr or + this instanceof CS::BitwiseOrExpr or + this instanceof CS::BitwiseXorExpr or + this instanceof CS::LShiftExpr or + this instanceof CS::RShiftExpr + } + + /** Returns the operation representing this expression. */ + TBinarySignOperation getOp() { + this instanceof CS::AddExpr and result = TAddOp() + or + this instanceof CS::SubExpr and result = TSubOp() + or + this instanceof CS::MulExpr and result = TMulOp() + or + this instanceof CS::DivExpr and result = TDivOp() + or + this instanceof CS::RemExpr and result = TRemOp() + or + this instanceof CS::BitwiseAndExpr and result = TBitAndOp() + or + this instanceof CS::BitwiseOrExpr and result = TBitOrOp() + or + this instanceof CS::BitwiseXorExpr and result = TBitXorOp() + or + this instanceof CS::LShiftExpr and result = TLShiftOp() + or + this instanceof CS::RShiftExpr and result = TRShiftOp() + } + } predicate ssaRead = SU::ssaRead/2; } @@ -203,7 +270,7 @@ private module Impl { } /** Returns a sub expression of `e` for expression types where the sign depends on the child. */ - Expr getASubExpr(Expr e) { + Expr getASubExprWithSameSign(Expr e) { result = e.(AssignExpr).getRValue() or result = e.(AssignOperation).getExpandedAssignment() or result = e.(UnaryPlusExpr).getOperand() or @@ -218,74 +285,6 @@ private module Impl { result = e.(CastExpr).getExpr() } - /** Class to represent unary expressions. */ - class UnaryExpr extends Expr { - UnaryExpr() { - this instanceof PreIncrExpr or - this instanceof PreDecrExpr or - this instanceof UnaryMinusExpr or - this instanceof ComplementExpr - } - - /** Returns the operand of this expression. */ - Expr getOperand() { - result = this.(PreIncrExpr).getOperand() or - result = this.(PreDecrExpr).getOperand() or - result = this.(UnaryMinusExpr).getOperand() or - result = this.(ComplementExpr).getOperand() - } - - /** Returns the operation representing this expression. */ - TUnarySignOperation getOp() { - this instanceof PreIncrExpr and result = TIncOp() - or - this instanceof PreDecrExpr and result = TDecOp() - or - this instanceof UnaryMinusExpr and result = TNegOp() - or - this instanceof ComplementExpr and result = TBitNotOp() - } - } - - /** Class to represent binary expressions. */ - class BinaryExpr extends Expr { - BinaryExpr() { - this instanceof AddExpr or - this instanceof SubExpr or - this instanceof MulExpr or - this instanceof DivExpr or - this instanceof RemExpr or - this instanceof BitwiseAndExpr or - this instanceof BitwiseOrExpr or - this instanceof BitwiseXorExpr or - this instanceof LShiftExpr or - this instanceof RShiftExpr - } - - /** Returns the operation representing this expression. */ - TBinarySignOperation getOp() { - this instanceof AddExpr and result = TAddOp() - or - this instanceof SubExpr and result = TSubOp() - or - this instanceof MulExpr and result = TMulOp() - or - this instanceof DivExpr and result = TDivOp() - or - this instanceof RemExpr and result = TRemOp() - or - this instanceof BitwiseAndExpr and result = TBitAndOp() - or - this instanceof BitwiseOrExpr and result = TBitOrOp() - or - this instanceof BitwiseXorExpr and result = TBitXorOp() - or - this instanceof LShiftExpr and result = TLShiftOp() - or - this instanceof RShiftExpr and result = TRShiftOp() - } - } - Expr getARead(Ssa::Definition v) { result = v.getARead() } Field getField(FieldAccess fa) { result = fa.getTarget() } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index 64f4a9d10c3..19412a0ba39 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -328,21 +328,20 @@ Sign exprSign(Expr e) { /** Gets a possible sign for `e` from the signs of its child nodes. */ private Sign specificSubExprSign(Expr e) { - result = exprSign(getASubExpr(e)) + result = exprSign(getASubExprWithSameSign(e)) or - e = - any(DivExpr div | - result = exprSign(div.getLeftOperand()) and - result != TZero() and - div.getRightOperand().(RealLiteral).getValue().toFloat() = 0 - ) + exists(DivExpr div | div = e | + result = exprSign(div.getLeftOperand()) and + result != TZero() and + div.getRightOperand().(RealLiteral).getValue().toFloat() = 0 + ) or - exists(UnaryExpr unary | unary = e | + exists(UnaryOperation unary | unary = e | result = exprSign(unary.getOperand()).applyUnaryOp(unary.getOp()) ) or exists(Sign s1, Sign s2 | binaryOpSigns(e, s1, s2) | - result = s1.applyBinaryOp(s2, e.(BinaryExpr).getOp()) + result = s1.applyBinaryOp(s2, e.(BinaryOperation).getOp()) ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index 6f2c1026ea6..84fbe10a91d 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -45,21 +45,6 @@ module Private { class DivExpr = J::DivExpr; - class BinaryOperation extends J::Expr { - BinaryOperation() { - this instanceof J::BinaryExpr or - this instanceof J::AssignOp - } - - Expr getLeftOperand() { - result = this.(J::BinaryExpr).getLeftOperand() or result = this.(J::AssignOp).getDest() - } - - Expr getRightOperand() { - result = this.(J::BinaryExpr).getRightOperand() or result = this.(J::AssignOp).getRhs() - } - } - /** Class to represent float and double literals. */ class RealLiteral extends J::Literal { RealLiteral() { @@ -68,9 +53,9 @@ module Private { } } - /** Class to represent unary expressions. */ - class UnaryExpr extends J::Expr { - UnaryExpr() { + /** Class to represent unary operation. */ + class UnaryOperation extends J::Expr { + UnaryOperation() { this instanceof J::PreIncExpr or this instanceof J::PreDecExpr or this instanceof J::MinusExpr or @@ -97,9 +82,9 @@ module Private { } } - /** Class to represent binary expressions. */ - class BinaryExpr extends J::Expr { - BinaryExpr() { + /** Class to represent binary operation. */ + class BinaryOperation extends J::Expr { + BinaryOperation() { this instanceof J::AddExpr or this instanceof J::AssignAddExpr or this instanceof J::SubExpr or @@ -170,6 +155,14 @@ module Private { or this instanceof J::AssignURShiftExpr and result = TURShiftOp() } + + Expr getLeftOperand() { + result = this.(J::BinaryExpr).getLeftOperand() or result = this.(J::AssignOp).getDest() + } + + Expr getRightOperand() { + result = this.(J::BinaryExpr).getRightOperand() or result = this.(J::AssignOp).getRhs() + } } predicate ssaRead = RU::ssaRead/2; @@ -300,7 +293,7 @@ private module Impl { } /** Returns a sub expression of `e` for expression types where the sign depends on the child. */ - Expr getASubExpr(Expr e) { + Expr getASubExprWithSameSign(Expr e) { result = e.(AssignExpr).getSource() or result = e.(PlusExpr).getExpr() or result = e.(PostIncExpr).getExpr() or diff --git a/java/ql/test/library-tests/dataflow/sign-analysis/SignAnalysis.ql b/java/ql/test/library-tests/dataflow/sign-analysis/SignAnalysis.ql index e47081a0094..9d3c03a7d08 100644 --- a/java/ql/test/library-tests/dataflow/sign-analysis/SignAnalysis.ql +++ b/java/ql/test/library-tests/dataflow/sign-analysis/SignAnalysis.ql @@ -18,5 +18,5 @@ string getASignString(Expr e) { } from Expr e -where not e instanceof Element or e.(Element).fromSource() +where e.getEnclosingCallable().fromSource() select e, strictconcat(string s | s = getASignString(e) | s, " ") From 98e93a7b9da765d4f0f31eb4c9a955b5fa8ee8f0 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Thu, 1 Oct 2020 12:05:12 +0100 Subject: [PATCH 170/411] JavaScript: Improve API-graph support for function-style classes. --- javascript/ql/src/semmle/javascript/ApiGraphs.qll | 6 +++++- javascript/ql/test/ApiGraphs/classes/classes.js | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index beae51fedcb..8550e57d916 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -547,7 +547,11 @@ module API { ref = DataFlow::moduleImport(m) ) or - exists(DataFlow::ClassNode cls | nd = MkClassInstance(cls) | ref = cls.getAReceiverNode()) + exists(DataFlow::ClassNode cls | nd = MkClassInstance(cls) | + ref = cls.getAReceiverNode() + or + ref = cls.(DataFlow::ClassNode::FunctionStyleClass).getAPrototypeReference() + ) or nd = MkUse(ref) or diff --git a/javascript/ql/test/ApiGraphs/classes/classes.js b/javascript/ql/test/ApiGraphs/classes/classes.js index 4d6fab7ee37..823abbe0a14 100644 --- a/javascript/ql/test/ApiGraphs/classes/classes.js +++ b/javascript/ql/test/ApiGraphs/classes/classes.js @@ -20,4 +20,8 @@ MyOtherStream.prototype.write = function (data) { /* use (instance (member MyOth return this; }; +MyOtherStream.prototype.instanceProp = 1; /* def (member instanceProp (instance (member MyOtherStream (member exports (module classes))))) */ + +MyOtherStream.classProp = 1; /* def (member classProp (member MyOtherStream (member exports (module classes)))) */ + module.exports.MyOtherStream = MyOtherStream; From abdbe92720b0b32742c0cb5e1bfb0cf8d9ae7129 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 29 Sep 2020 15:43:52 +0200 Subject: [PATCH 171/411] refactor the NoSQL model to use API graphs --- .../ql/src/semmle/javascript/ApiGraphs.qll | 3 + .../semmle/javascript/frameworks/NoSQL.qll | 485 ++++++++---------- .../CWE-089/untyped/SqlInjection.expected | 7 + .../Security/CWE-089/untyped/mongoose.js | 12 + 4 files changed, 226 insertions(+), 281 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 0a71f69c174..eb84658ea15 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -301,6 +301,9 @@ module API { /** Gets a data-flow node that defines this entry point. */ abstract DataFlow::Node getARhs(); + + /** Gets a API-node for this entry point. */ + API::Node getNode() { result = root().getASuccessor(this) } } /** diff --git a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll index 2854cdaa8f4..adcbb25afeb 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll @@ -13,106 +13,39 @@ module NoSQL { } /** - * Gets a reference to an object where the "$where" property has been assigned to`rhs`. + * Gets a value that has been assigned to the "$where" property of an object that flows to `queryArg`. */ -DataFlow::SourceNode getADollarWherePropertyValueSource(DataFlow::TypeTracker t, DataFlow::Node rhs) { - t.start() and - rhs = result.getAPropertyWrite("$where").getRhs() - or - exists(DataFlow::TypeTracker t2 | - result = getADollarWherePropertyValueSource(t2, rhs).track(t2, t) - ) -} - -/** - * Gets the value of a `$where` property of an object that flows to `n`. - */ -private DataFlow::Node getADollarWherePropertyValue(DataFlow::Node n) { - getADollarWherePropertyValueSource(DataFlow::TypeTracker::end(), result).flowsTo(n) +private DataFlow::Node getADollarWhereProperty(API::Node queryArg) { + result = queryArg.getMember("$where").getARhs() } /** * Provides classes modeling the MongoDB library. */ private module MongoDB { - /** - * Gets an import of MongoDB. - */ - DataFlow::ModuleImportNode mongodb() { result.getPath() = "mongodb" } - /** * Gets an access to `mongodb.MongoClient`. */ - private DataFlow::SourceNode getAMongoClient(DataFlow::TypeTracker t) { - t.start() and - ( - result = mongodb().getAPropertyRead("MongoClient") - or - exists(DataFlow::ParameterNode p | - p = result and - p = getAMongoDbCallback().getParameter(1) and - not p.getName().toLowerCase() = "db" // mongodb v2 provides a `Db` here - ) - ) + private API::Node getAMongoClient() { + result = API::moduleImport("mongodb").getMember("MongoClient") or - exists(DataFlow::TypeTracker t2 | result = getAMongoClient(t2).track(t2, t)) + // slightly imprecise, is not supposed to have a result if the parameter name is "db" (that would be a mongodb v2 `Db`). + result = getAMongoDbCallback().getParameter(1) + } + + /** Gets an api node that refers to a `connect` callback. */ + private API::Node getAMongoDbCallback() { + result = getAMongoClient().getMember("connect").getLastParameter() } /** - * Gets an access to `mongodb.MongoClient`. + * Gets an API node that may refer to a MongoDB database connection. */ - DataFlow::SourceNode getAMongoClient() { result = getAMongoClient(DataFlow::TypeTracker::end()) } - - /** Gets a data flow node that leads to a `connect` callback. */ - private DataFlow::SourceNode getAMongoDbCallback(DataFlow::TypeBackTracker t) { - t.start() and - result = getAMongoClient().getAMemberCall("connect").getLastArgument().getALocalSource() + private API::Node getAMongoDb() { + result = getAMongoClient().getMember("db").getReturn() or - exists(DataFlow::TypeBackTracker t2 | result = getAMongoDbCallback(t2).backtrack(t2, t)) - } - - /** Gets a data flow node that leads to a `connect` callback. */ - private DataFlow::FunctionNode getAMongoDbCallback() { - result = getAMongoDbCallback(DataFlow::TypeBackTracker::end()) - } - - /** - * Gets an expression that may refer to a MongoDB database connection. - */ - private DataFlow::SourceNode getAMongoDb(DataFlow::TypeTracker t) { - t.start() and - ( - exists(DataFlow::ParameterNode p | - p = result and - p = getAMongoDbCallback().getParameter(1) and - not p.getName().toLowerCase() = "client" // mongodb v3 provides a `Mongoclient` here - ) - or - result = getAMongoClient().getAMethodCall("db") - ) - or - exists(DataFlow::TypeTracker t2 | result = getAMongoDb(t2).track(t2, t)) - } - - /** - * Gets an expression that may refer to a MongoDB database connection. - */ - DataFlow::SourceNode getAMongoDb() { result = getAMongoDb(DataFlow::TypeTracker::end()) } - - /** - * A data flow node that may hold a MongoDB collection. - */ - abstract class Collection extends DataFlow::SourceNode { } - - /** - * A collection resulting from calling `Db.collection(...)`. - */ - private class CollectionFromDb extends Collection { - CollectionFromDb() { - this = getAMongoDb().getAMethodCall("collection") - or - this = getAMongoDb().getAMethodCall("collection").getCallback(1).getParameter(0) - } + // slightly imprecise, is not supposed to have a result if the parameter name is "client" (that would be a mongodb v3 `Mongoclient`). + result = getAMongoDbCallback().getParameter(1) } /** @@ -121,32 +54,55 @@ private module MongoDB { * Note that this also covers `mongoose` models since they are subtypes * of `mongodb.Collection`. */ - private class CollectionFromType extends Collection { - CollectionFromType() { hasUnderlyingType("mongodb", "Collection") } + private class TypedMongoCollection extends API::EntryPoint { + TypedMongoCollection() { this = "TypedMongoCollection" } + + override DataFlow::SourceNode getAUse() { result.hasUnderlyingType("mongodb", "Collection") } + + override DataFlow::Node getARhs() { none() } } /** Gets a data flow node referring to a MongoDB collection. */ - private DataFlow::SourceNode getACollection(DataFlow::TypeTracker t) { - t.start() and - result instanceof Collection + private API::Node getACollection() { + // A collection resulting from calling `Db.collection(...)`. + exists(API::Node collection | collection = getAMongoDb().getMember("collection").getReturn() | + result = collection + or + result = collection.getParameter(1).getParameter(0) + ) or - exists(DataFlow::TypeTracker t2 | result = getACollection(t2).track(t2, t)) + result = any(TypedMongoCollection c).getNode() } - /** Gets a data flow node referring to a MongoDB collection. */ - DataFlow::SourceNode getACollection() { result = getACollection(DataFlow::TypeTracker::end()) } - /** A call to a MongoDB query method. */ - private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { + private class QueryCall extends DatabaseAccess, DataFlow::CallNode { int queryArgIdx; + API::Node callee; QueryCall() { - exists(string m | this = getACollection().getAMethodCall(m) | - CollectionMethodSignatures::interpretsArgumentAsQuery(m, queryArgIdx) - ) + exists(string method | + CollectionMethodSignatures::interpretsArgumentAsQuery(method, queryArgIdx) and + callee = getACollection().getMember(method) + ) and + this = callee.getACall() } override DataFlow::Node getAQueryArgument() { result = getArgument(queryArgIdx) } + + DataFlow::Node getACodeOperator() { + result = getADollarWhereProperty(callee.getParameter(queryArgIdx)) + } + } + + /** + * An expression that is interpreted as a MongoDB query. + */ + class Query extends NoSQL::Query { + QueryCall qc; + + Query() { this = qc.getAQueryArgument().asExpr() } + + override DataFlow::Node getACodeOperator() { result = qc.getACodeOperator() } } /** @@ -206,17 +162,6 @@ private module MongoDB { ) } } - - /** - * An expression that is interpreted as a MongoDB query. - */ - class Query extends NoSQL::Query { - Query() { this = any(QueryCall qc).getAQueryArgument().asExpr() } - - override DataFlow::Node getACodeOperator() { - result = getADollarWherePropertyValue(this.flow()) - } - } } /** @@ -226,81 +171,84 @@ private module Mongoose { /** * Gets an import of Mongoose. */ - DataFlow::ModuleImportNode getAMongooseInstance() { result.getPath() = "mongoose" } + API::Node getAMongooseInstance() { result = API::moduleImport("mongoose") } /** - * Gets a call to `mongoose.createConnection`. + * Gets a reference to `mongoose.createConnection`. */ - DataFlow::CallNode createConnection() { - result = getAMongooseInstance().getAMemberCall("createConnection") - } + API::Node createConnection() { result = getAMongooseInstance().getMember("createConnection") } /** - * A Mongoose function invocation. + * A Mongoose function. */ - private class InvokeNode extends DataFlow::InvokeNode { + private class MongooseFunction extends API::Node { /** - * Holds if this invocation returns an object of type `Query`. + * Gets the API node for the result from this function (if the function returns a Query). */ - abstract predicate returnsQuery(); + abstract API::Node getQueryReturn(); /** - * Holds if this invocation returns a `Query` that evaluates to one or + * Holds if this function returns a `Query` that evaluates to one or * more Documents (`asArray` is false if it evaluates to a single * Document). */ abstract predicate returnsDocumentQuery(boolean asArray); /** - * Holds if this invocation interprets `arg` as a query. + * Gets an argument that this function interprets as a query. */ - abstract predicate interpretsArgumentAsQuery(DataFlow::Node arg); + abstract API::Node getQueryArgument(); } /** * Provides classes modeling the Mongoose Model class */ module Model { - private class ModelInvokeNode extends InvokeNode, DataFlow::MethodCallNode { - ModelInvokeNode() { this = ref().getAMethodCall() } + private class ModelFunction extends MongooseFunction { + string methodName; - override predicate returnsQuery() { MethodSignatures::returnsQuery(getMethodName()) } + ModelFunction() { this = getModelObject().getMember(methodName) } + + override API::Node getQueryReturn() { + MethodSignatures::returnsQuery(methodName) and result = this.getReturn() + } override predicate returnsDocumentQuery(boolean asArray) { - MethodSignatures::returnsDocumentQuery(getMethodName(), asArray) + MethodSignatures::returnsDocumentQuery(methodName, asArray) } - override predicate interpretsArgumentAsQuery(DataFlow::Node arg) { + override API::Node getQueryArgument() { exists(int n | - MethodSignatures::interpretsArgumentAsQuery(this.getMethodName(), n) and - arg = this.getArgument(n) + MethodSignatures::interpretsArgumentAsQuery(methodName, n) and + result = this.getParameter(n) ) } } /** - * Gets a data flow node referring to a Mongoose Model object. + * A Mongoose collection based on the type `mongoose.Model`. */ - private DataFlow::SourceNode ref(DataFlow::TypeTracker t) { - ( - result = getAMongooseInstance().getAMemberCall("model") - or - exists(DataFlow::SourceNode conn | conn = createConnection() | - result = conn.getAMemberCall("model") or - result = conn.getAPropertyRead("models").getAPropertyRead() - ) - or - result.hasUnderlyingType("mongoose", "Model") - ) and - t.start() - or - exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t)) + private class TypedMongooseModel extends API::EntryPoint { + TypedMongooseModel() { this = "TypedMongooseModel" } + + override DataFlow::SourceNode getAUse() { result.hasUnderlyingType("mongoose", "Model") } + + override DataFlow::Node getARhs() { none() } } /** - * Gets a data flow node referring to a Mongoose model object. + * Gets a API node referring to a Mongoose Model object. */ - DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) } + private API::Node getModelObject() { + result = getAMongooseInstance().getMember("model").getReturn() + or + exists(API::Node conn | conn = createConnection().getReturn() | + result = conn.getMember("model").getReturn() or + result = conn.getMember("models").getAMember() + ) + or + result = any(TypedMongooseModel c).getNode() + } /** * Provides signatures for the Model methods. @@ -362,58 +310,62 @@ private module Mongoose { * Provides classes modeling the Mongoose Query class */ module Query { - private class QueryInvokeNode extends InvokeNode, DataFlow::MethodCallNode { - QueryInvokeNode() { this = ref().getAMethodCall() } + private class QueryFunction extends MongooseFunction { + string methodName; - override predicate returnsQuery() { MethodSignatures::returnsQuery(getMethodName()) } + QueryFunction() { this = getAMongooseQuery().getMember(methodName) } - override predicate returnsDocumentQuery(boolean asArray) { - MethodSignatures::returnsDocumentQuery(getMethodName(), asArray) + override API::Node getQueryReturn() { + MethodSignatures::returnsQuery(methodName) and result = this.getReturn() } - override predicate interpretsArgumentAsQuery(DataFlow::Node arg) { + override predicate returnsDocumentQuery(boolean asArray) { + MethodSignatures::returnsDocumentQuery(methodName, asArray) + } + + override API::Node getQueryArgument() { exists(int n | - MethodSignatures::interpretsArgumentAsQuery(this.getMethodName(), n) and - arg = this.getArgument(n) + MethodSignatures::interpretsArgumentAsQuery(methodName, n) and + result = this.getParameter(n) ) } } - private class NewQueryInvokeNode extends InvokeNode { - NewQueryInvokeNode() { - this = getAMongooseInstance().getAPropertyRead("Query").getAnInstantiation() - } + private class NewQueryFunction extends MongooseFunction { + NewQueryFunction() { this = getAMongooseInstance().getMember("Query") } - override predicate returnsQuery() { any() } + override API::Node getQueryReturn() { result = this.getInstance() } override predicate returnsDocumentQuery(boolean asArray) { none() } - override predicate interpretsArgumentAsQuery(DataFlow::Node arg) { arg = this.getArgument(2) } + override API::Node getQueryArgument() { result = this.getParameter(2) } + } + + /** + * A Mongoose query. + */ + private class TypedMongooseQuery extends API::EntryPoint { + TypedMongooseQuery() { this = "TypedMongooseQuery" } + + override DataFlow::SourceNode getAUse() { result.hasUnderlyingType("mongoose", "Query") } + + override DataFlow::Node getARhs() { none() } } /** * Gets a data flow node referring to a Mongoose query object. */ - private DataFlow::SourceNode ref(DataFlow::TypeTracker t) { - ( - result.(InvokeNode).returnsQuery() or - result.hasUnderlyingType("mongoose", "Query") - ) and - t.start() + API::Node getAMongooseQuery() { + result = any(MongooseFunction f).getQueryReturn() or - exists(DataFlow::TypeTracker t2, DataFlow::SourceNode succ | succ = ref(t2) | - result = succ.track(t2, t) - or - result = succ.getAMethodCall(any(string name | MethodSignatures::returnsQuery(name))) and - t = t2.continue() - ) + result = any(TypedMongooseQuery c).getNode() + or + result = + getAMongooseQuery() + .getMember(any(string name | MethodSignatures::returnsQuery(name))) + .getReturn() } - /** - * Gets a data flow node referring to a Mongoose query object. - */ - DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) } - /** * Provides signatures for the Query methods. */ @@ -553,19 +505,23 @@ private module Mongoose { * Provides classes modeling the Mongoose Document class */ module Document { - private class DocumentInvokeNode extends InvokeNode, DataFlow::MethodCallNode { - DocumentInvokeNode() { this = ref().getAMethodCall() } + private class DocumentFunction extends MongooseFunction { + string methodName; - override predicate returnsQuery() { MethodSignatures::returnsQuery(getMethodName()) } + DocumentFunction() { this = getAMongooseDocument().getMember(methodName) } - override predicate returnsDocumentQuery(boolean asArray) { - MethodSignatures::returnsDocumentQuery(getMethodName(), asArray) + override API::Node getQueryReturn() { + MethodSignatures::returnsQuery(methodName) and result = this.getReturn() } - override predicate interpretsArgumentAsQuery(DataFlow::Node arg) { + override predicate returnsDocumentQuery(boolean asArray) { + MethodSignatures::returnsDocumentQuery(methodName, asArray) + } + + override API::Node getQueryArgument() { exists(int n | - MethodSignatures::interpretsArgumentAsQuery(this.getMethodName(), n) and - arg = this.getArgument(n) + MethodSignatures::interpretsArgumentAsQuery(methodName, n) and + result = this.getParameter(n) ) } } @@ -573,67 +529,59 @@ private module Mongoose { /** * A Mongoose Document that is retrieved from the backing database. */ - class RetrievedDocument extends DataFlow::SourceNode { + class RetrievedDocument extends API::Node { RetrievedDocument() { - exists(boolean asArray, DataFlow::ParameterNode param | - exists(InvokeNode call | - call.returnsDocumentQuery(asArray) and - param = call.getCallback(call.getNumArgument() - 1).getParameter(1) + exists(boolean asArray, API::Node param | + exists(MongooseFunction func | + func.returnsDocumentQuery(asArray) and + param = func.getLastParameter().getParameter(1) ) or - exists( - DataFlow::SourceNode base, DataFlow::MethodCallNode call, string executor, - int paramIndex - | + exists(API::Node f, string executor, int paramIndex | executor = "then" and paramIndex = 0 or executor = "exec" and paramIndex = 1 | - base = Query::ref() and - call = base.getAMethodCall(executor) and - param = call.getCallback(0).getParameter(paramIndex) and + f = Query::getAMongooseQuery().getMember(executor) and + param = f.getParameter(0).getParameter(paramIndex) and exists(DataFlow::MethodCallNode pred | - // limitation: look at the previous method call + // limitation: look at the previous method call Query::MethodSignatures::returnsDocumentQuery(pred.getMethodName(), asArray) and - pred.getAMethodCall() = call + pred.getAMethodCall() = f.getACall() ) ) | asArray = false and this = param or asArray = true and - exists(DataFlow::PropRead access | - // limitation: look for direct accesses - access = param.getAPropertyRead() and - not exists(access.getPropertyName()) and - this = access - ) + // limitation: look for direct accesses + this = param.getUnknownMember() ) } } /** - * Gets a data flow node referring to a Mongoose Document object. + * A Mongoose document. */ - private DataFlow::SourceNode ref(DataFlow::TypeTracker t) { - ( - result instanceof RetrievedDocument or - result.hasUnderlyingType("mongoose", "Document") - ) and - t.start() - or - exists(DataFlow::TypeTracker t2, DataFlow::SourceNode succ | succ = ref(t2) | - result = succ.track(t2, t) - or - result = succ.getAMethodCall(any(string name | MethodSignatures::returnsDocument(name))) and - t = t2.continue() - ) + private class TypedMongooseDocument extends API::EntryPoint { + TypedMongooseDocument() { this = "TypedMongooseDocument" } + + override DataFlow::SourceNode getAUse() { result.hasUnderlyingType("mongoose", "Document") } + + override DataFlow::Node getARhs() { none() } } /** * Gets a data flow node referring to a Mongoose Document object. */ - DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) } + private API::Node getAMongooseDocument() { + result instanceof RetrievedDocument or + result = any(TypedMongooseDocument c).getNode() or + result = + getAMongooseDocument() + .getMember(any(string name | MethodSignatures::returnsDocument(name))) + .getReturn() + } private module MethodSignatures { /** @@ -691,7 +639,9 @@ private module Mongoose { string kind; Credentials() { - exists(string prop | this = createConnection().getOptionArgument(3, prop).asExpr() | + exists(string prop | + this = createConnection().getParameter(3).getMember(prop).getARhs().asExpr() + | prop = "user" and kind = "user name" or prop = "pass" and kind = "password" @@ -705,38 +655,38 @@ private module Mongoose { * An expression that is interpreted as a (part of a) MongoDB query. */ class MongoDBQueryPart extends NoSQL::Query { - MongoDBQueryPart() { any(InvokeNode call).interpretsArgumentAsQuery(this.flow()) } + MongooseFunction f; + + MongoDBQueryPart() { this = f.getQueryArgument().getARhs().asExpr() } override DataFlow::Node getACodeOperator() { - result = getADollarWherePropertyValue(this.flow()) + result = getADollarWhereProperty(f.getQueryArgument()) } } /** * An evaluation of a MongoDB query. */ - class ShorthandQueryEvaluation extends DatabaseAccess { - InvokeNode invk; + class ShorthandQueryEvaluation extends DatabaseAccess, DataFlow::InvokeNode { + MongooseFunction f; ShorthandQueryEvaluation() { - this = invk and + this = f.getACall() and // shorthand for execution: provide a callback - invk.returnsQuery() and - exists(invk.getCallback(invk.getNumArgument() - 1)) + exists(f.getQueryReturn()) and + exists(this.getCallback(this.getNumArgument() - 1)) } override DataFlow::Node getAQueryArgument() { // NB: the complete information is not easily accessible for deeply chained calls - invk.interpretsArgumentAsQuery(result) + f.getQueryArgument().getARhs() = result } } class ExplicitQueryEvaluation extends DatabaseAccess { ExplicitQueryEvaluation() { // explicit execution using a Query method call - exists(string executor | executor = "exec" or executor = "then" or executor = "catch" | - Query::ref().getAMethodCall(executor) = this - ) + Query::getAMongooseQuery().getMember(["exec", "then", "catch"]).getACall() = this } override DataFlow::Node getAQueryArgument() { @@ -750,26 +700,6 @@ private module Mongoose { * Provides classes modeling the Minimongo library. */ private module Minimongo { - /** - * Gets an expression that may refer to a Minimongo database. - */ - private DataFlow::SourceNode getADb(DataFlow::TypeTracker t) { - t.start() and - // new (require('minimongo')[DBKINDNAME])() - result = DataFlow::moduleImport("minimongo").getAPropertyRead().getAnInvocation() - or - exists(DataFlow::TypeTracker t2 | result = getADb(t2).track(t2, t)) - } - - /** Gets a data flow node referring to a Minimongo collection. */ - private DataFlow::SourceNode getACollection(DataFlow::TypeTracker t) { - t.start() and - // db[COLLECTIONNAME] - result = getADb(DataFlow::TypeTracker::end()).getAPropertyRead() - or - exists(DataFlow::TypeTracker t2 | result = getACollection(t2).track(t2, t)) - } - /** * Provides signatures for the Collection methods. */ @@ -786,25 +716,32 @@ private module Minimongo { /** A call to a Minimongo query method. */ private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { int queryArgIdx; + API::Node callee; QueryCall() { - exists(string m | this = getACollection(DataFlow::TypeTracker::end()).getAMethodCall(m) | + exists(string m | + callee = API::moduleImport("minimongo").getAMember().getReturn().getAMember().getMember(m) and + this = callee.getACall() and CollectionMethodSignatures::interpretsArgumentAsQuery(m, queryArgIdx) ) } override DataFlow::Node getAQueryArgument() { result = getArgument(queryArgIdx) } + + DataFlow::Node getACodeOperator() { + result = getADollarWhereProperty(callee.getParameter(queryArgIdx)) + } } /** * An expression that is interpreted as a Minimongo query. */ class Query extends NoSQL::Query { - Query() { this = any(QueryCall qc).getAQueryArgument().asExpr() } + QueryCall qc; - override DataFlow::Node getACodeOperator() { - result = getADollarWherePropertyValue(this.flow()) - } + Query() { this = qc.getAQueryArgument().asExpr() } + + override DataFlow::Node getACodeOperator() { result = qc.getACodeOperator() } } } @@ -812,49 +749,35 @@ private module Minimongo { * Provides classes modeling the MarsDB library. */ private module MarsDB { - /** - * Gets an expression that may refer to a MarsDB database. - */ - private DataFlow::SourceNode getADb(DataFlow::TypeTracker t) { - t.start() and - // Collection = require('marsdb') - result = DataFlow::moduleImport("marsdb") - or - exists(DataFlow::TypeTracker t2 | result = getADb(t2).track(t2, t)) - } - - /** Gets a data flow node referring to a MarsDB collection. */ - private DataFlow::SourceNode getACollection(DataFlow::TypeTracker t) { - t.start() and - // new Collection(...) - result = - getADb(DataFlow::TypeTracker::end()).getAPropertyRead("Collection").getAnInstantiation() - or - exists(DataFlow::TypeTracker t2 | result = getACollection(t2).track(t2, t)) - } - /** A call to a MarsDB query method. */ private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode { int queryArgIdx; + API::Node callee; QueryCall() { - exists(string m | this = getACollection(DataFlow::TypeTracker::end()).getAMethodCall(m) | + exists(string m | + callee = API::moduleImport("marsdb").getMember("Collection").getInstance().getMember(m) and + this = callee.getACall() and // implements parts of the Minimongo interface Minimongo::CollectionMethodSignatures::interpretsArgumentAsQuery(m, queryArgIdx) ) } override DataFlow::Node getAQueryArgument() { result = getArgument(queryArgIdx) } + + DataFlow::Node getACodeOperator() { + result = getADollarWhereProperty(callee.getParameter(queryArgIdx)) + } } /** * An expression that is interpreted as a MarsDB query. */ class Query extends NoSQL::Query { - Query() { this = any(QueryCall qc).getAQueryArgument().asExpr() } + QueryCall qc; - override DataFlow::Node getACodeOperator() { - result = getADollarWherePropertyValue(this.flow()) - } + Query() { this = qc.getAQueryArgument().asExpr() } + + override DataFlow::Node getACodeOperator() { result = qc.getACodeOperator() } } } diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected b/javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected index 764a6cf96da..945bf9f65ce 100644 --- a/javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected @@ -136,6 +136,8 @@ nodes | mongoose.js:94:51:94:55 | query | | mongoose.js:96:46:96:50 | query | | mongoose.js:96:46:96:50 | query | +| mongoose.js:111:14:111:18 | query | +| mongoose.js:111:14:111:18 | query | | mongooseJsonParse.js:19:11:19:20 | query | | mongooseJsonParse.js:19:19:19:20 | {} | | mongooseJsonParse.js:20:19:20:44 | JSON.pa ... y.data) | @@ -337,6 +339,8 @@ edges | mongoose.js:20:11:20:20 | query | mongoose.js:94:51:94:55 | query | | mongoose.js:20:11:20:20 | query | mongoose.js:96:46:96:50 | query | | mongoose.js:20:11:20:20 | query | mongoose.js:96:46:96:50 | query | +| mongoose.js:20:11:20:20 | query | mongoose.js:111:14:111:18 | query | +| mongoose.js:20:11:20:20 | query | mongoose.js:111:14:111:18 | query | | mongoose.js:20:19:20:20 | {} | mongoose.js:20:11:20:20 | query | | mongoose.js:21:19:21:26 | req.body | mongoose.js:21:19:21:32 | req.body.title | | mongoose.js:21:19:21:26 | req.body | mongoose.js:21:19:21:32 | req.body.title | @@ -403,6 +407,8 @@ edges | mongoose.js:21:19:21:32 | req.body.title | mongoose.js:94:51:94:55 | query | | mongoose.js:21:19:21:32 | req.body.title | mongoose.js:96:46:96:50 | query | | mongoose.js:21:19:21:32 | req.body.title | mongoose.js:96:46:96:50 | query | +| mongoose.js:21:19:21:32 | req.body.title | mongoose.js:111:14:111:18 | query | +| mongoose.js:21:19:21:32 | req.body.title | mongoose.js:111:14:111:18 | query | | mongoose.js:24:25:24:29 | query | mongoose.js:24:24:24:30 | [query] | | mongoose.js:24:25:24:29 | query | mongoose.js:24:24:24:30 | [query] | | mongooseJsonParse.js:19:11:19:20 | query | mongooseJsonParse.js:23:19:23:23 | query | @@ -490,6 +496,7 @@ edges | mongoose.js:92:46:92:50 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:92:46:92:50 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value | | mongoose.js:94:51:94:55 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:94:51:94:55 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value | | mongoose.js:96:46:96:50 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:96:46:96:50 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value | +| mongoose.js:111:14:111:18 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:111:14:111:18 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value | | mongooseJsonParse.js:23:19:23:23 | query | mongooseJsonParse.js:20:30:20:43 | req.query.data | mongooseJsonParse.js:23:19:23:23 | query | This query depends on $@. | mongooseJsonParse.js:20:30:20:43 | req.query.data | a user-provided value | | mongooseModelClient.js:11:16:11:24 | { id: v } | mongooseModelClient.js:10:22:10:29 | req.body | mongooseModelClient.js:11:16:11:24 | { id: v } | This query depends on $@. | mongooseModelClient.js:10:22:10:29 | req.body | a user-provided value | | mongooseModelClient.js:12:16:12:34 | { id: req.body.id } | mongooseModelClient.js:12:22:12:29 | req.body | mongooseModelClient.js:12:16:12:34 | { id: req.body.id } | This query depends on $@. | mongooseModelClient.js:12:22:12:29 | req.body | a user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/mongoose.js b/javascript/ql/test/query-tests/Security/CWE-089/untyped/mongoose.js index 03e149b7c02..3818b5e05f9 100644 --- a/javascript/ql/test/query-tests/Security/CWE-089/untyped/mongoose.js +++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/mongoose.js @@ -97,4 +97,16 @@ app.post('/documents/find', (req, res) => { Document.find(X).then(Y, (err) => err.count(query)); // OK Document.count(X, (err, res) => res.count(query)); // OK (res is a number) + + function innocent(X, Y, query) { // To detect if API-graphs were used incorrectly. + return new Mongoose.Query("constant", "constant", "constant"); + } + new innocent(X, Y, query); + + function getQueryConstructor() { + return Mongoose.Query; + } + + var C = getQueryConstructor(); + new C(X, Y, query); // NOT OK }); From 6acb1990748303a17cc0177752e57ae6b5072aa4 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 2 Oct 2020 11:09:50 +0200 Subject: [PATCH 172/411] improve precision using `getAnImmediateUse` to check parameter names --- javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll index adcbb25afeb..f1ec213caf0 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll @@ -29,8 +29,8 @@ private module MongoDB { private API::Node getAMongoClient() { result = API::moduleImport("mongodb").getMember("MongoClient") or - // slightly imprecise, is not supposed to have a result if the parameter name is "db" (that would be a mongodb v2 `Db`). - result = getAMongoDbCallback().getParameter(1) + result = getAMongoDbCallback().getParameter(1) and + not result.getAnImmediateUse().(DataFlow::ParameterNode).getName() = "db" // mongodb v2 provides a `Db` here } /** Gets an api node that refers to a `connect` callback. */ @@ -44,8 +44,8 @@ private module MongoDB { private API::Node getAMongoDb() { result = getAMongoClient().getMember("db").getReturn() or - // slightly imprecise, is not supposed to have a result if the parameter name is "client" (that would be a mongodb v3 `Mongoclient`). - result = getAMongoDbCallback().getParameter(1) + result = getAMongoDbCallback().getParameter(1) and + not result.getAnImmediateUse().(DataFlow::ParameterNode).getName() = "client" // mongodb v3 provides a `Mongoclient` here } /** From 0b6096ebfe0fbdecde26c8be4be687dd8f51da76 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 Oct 2020 10:51:34 +0100 Subject: [PATCH 173/411] C++: Define make_pair and declare std::forward in the test. --- .../dataflow/taint-tests/localTaint.expected | 166 +++++++++++++++--- .../library-tests/dataflow/taint-tests/stl.h | 10 +- 2 files changed, 150 insertions(+), 26 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 d719c453705..1f1bb019646 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -1931,31 +1931,147 @@ | standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:53:12:53:18 | source1 | | | standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:54:14:54:20 | source1 | | | standalone_iterators.cpp:53:12:53:18 | ref arg source1 | standalone_iterators.cpp:54:14:54:20 | source1 | | -| stl.h:235:30:235:40 | call to allocator | stl.h:235:21:235:41 | noexcept(...) | TAINT | -| stl.h:235:30:235:40 | call to allocator | stl.h:235:21:235:41 | noexcept(...) | TAINT | -| stl.h:235:30:235:40 | call to allocator | stl.h:235:21:235:41 | noexcept(...) | TAINT | -| stl.h:235:30:235:40 | call to allocator | stl.h:235:21:235:41 | noexcept(...) | TAINT | -| stl.h:235:30:235:40 | call to allocator | stl.h:235:21:235:41 | noexcept(...) | TAINT | -| stl.h:235:53:235:63 | 0 | stl.h:235:46:235:64 | (no string representation) | TAINT | -| stl.h:328:9:328:9 | Unknown literal | stl.h:328:9:328:9 | constructor init of field first | TAINT | -| stl.h:328:9:328:9 | Unknown literal | stl.h:328:9:328:9 | constructor init of field second | TAINT | -| stl.h:328:9:328:9 | constructor init of field first [post-this] | stl.h:328:9:328:9 | constructor init of field second [pre-this] | | -| stl.h:328:9:328:9 | constructor init of field first [pre-this] | stl.h:328:9:328:9 | constructor init of field second [pre-this] | | -| stl.h:328:9:328:9 | this | stl.h:328:9:328:9 | constructor init of field first [pre-this] | | -| stl.h:335:3:335:3 | this | stl.h:335:36:335:43 | constructor init of field first [pre-this] | | -| stl.h:335:3:335:6 | this | stl.h:335:36:335:43 | constructor init of field first [pre-this] | | -| stl.h:335:18:335:18 | x | stl.h:335:42:335:42 | x | | -| stl.h:335:18:335:18 | x | stl.h:335:42:335:42 | x | | -| stl.h:335:31:335:31 | y | stl.h:335:53:335:53 | y | | -| stl.h:335:31:335:31 | y | stl.h:335:53:335:53 | y | | -| stl.h:335:36:335:43 | call to unknown function | stl.h:335:36:335:43 | constructor init of field first | TAINT | -| stl.h:335:36:335:43 | constructor init of field first [post-this] | stl.h:335:46:335:54 | constructor init of field second [pre-this] | | -| stl.h:335:36:335:43 | constructor init of field first [post-this] | stl.h:335:46:335:54 | constructor init of field second [pre-this] | | -| stl.h:335:36:335:43 | constructor init of field first [pre-this] | stl.h:335:46:335:54 | constructor init of field second [pre-this] | | -| stl.h:335:36:335:43 | constructor init of field first [pre-this] | stl.h:335:46:335:54 | constructor init of field second [pre-this] | | -| stl.h:335:42:335:42 | x | stl.h:335:36:335:43 | constructor init of field first | TAINT | -| stl.h:335:46:335:54 | call to unknown function | stl.h:335:46:335:54 | constructor init of field second | TAINT | -| stl.h:335:53:335:53 | y | stl.h:335:46:335:54 | constructor init of field second | TAINT | +| stl.h:241:30:241:40 | call to allocator | stl.h:241:21:241:41 | noexcept(...) | TAINT | +| stl.h:241:30:241:40 | call to allocator | stl.h:241:21:241:41 | noexcept(...) | TAINT | +| stl.h:241:30:241:40 | call to allocator | stl.h:241:21:241:41 | noexcept(...) | TAINT | +| stl.h:241:30:241:40 | call to allocator | stl.h:241:21:241:41 | noexcept(...) | TAINT | +| stl.h:241:30:241:40 | call to allocator | stl.h:241:21:241:41 | noexcept(...) | TAINT | +| stl.h:241:53:241:63 | 0 | stl.h:241:46:241:64 | (no string representation) | TAINT | +| stl.h:334:9:334:9 | Unknown literal | stl.h:334:9:334:9 | constructor init of field first | TAINT | +| stl.h:334:9:334:9 | Unknown literal | stl.h:334:9:334:9 | constructor init of field second | TAINT | +| stl.h:334:9:334:9 | constructor init of field first [post-this] | stl.h:334:9:334:9 | constructor init of field second [pre-this] | | +| stl.h:334:9:334:9 | constructor init of field first [pre-this] | stl.h:334:9:334:9 | constructor init of field second [pre-this] | | +| stl.h:334:9:334:9 | this | stl.h:334:9:334:9 | constructor init of field first [pre-this] | | +| stl.h:341:3:341:3 | this | stl.h:341:36:341:43 | constructor init of field first [pre-this] | | +| stl.h:341:3:341:3 | this | stl.h:341:36:341:43 | constructor init of field first [pre-this] | | +| stl.h:341:3:341:3 | this | stl.h:341:36:341:43 | constructor init of field first [pre-this] | | +| stl.h:341:3:341:3 | this | stl.h:341:36:341:43 | constructor init of field first [pre-this] | | +| stl.h:341:3:341:3 | this | stl.h:341:36:341:43 | constructor init of field first [pre-this] | | +| stl.h:341:3:341:3 | this | stl.h:341:36:341:43 | constructor init of field first [pre-this] | | +| stl.h:341:3:341:3 | this | stl.h:341:36:341:43 | constructor init of field first [pre-this] | | +| stl.h:341:3:341:6 | this | stl.h:341:36:341:43 | constructor init of field first [pre-this] | | +| stl.h:341:18:341:18 | x | stl.h:341:18:341:18 | x | | +| stl.h:341:18:341:18 | x | stl.h:341:18:341:18 | x | | +| stl.h:341:18:341:18 | x | stl.h:341:18:341:18 | x | | +| stl.h:341:18:341:18 | x | stl.h:341:18:341:18 | x | | +| stl.h:341:18:341:18 | x | stl.h:341:42:341:42 | x | | +| stl.h:341:18:341:18 | x | stl.h:341:42:341:42 | x | | +| stl.h:341:18:341:18 | x | stl.h:341:42:341:42 | x | | +| stl.h:341:18:341:18 | x | stl.h:341:42:341:42 | x | | +| stl.h:341:18:341:18 | x | stl.h:341:42:341:42 | x | | +| stl.h:341:18:341:18 | x | stl.h:341:42:341:42 | x | | +| stl.h:341:18:341:18 | x | stl.h:341:42:341:42 | x | | +| stl.h:341:18:341:18 | x | stl.h:341:42:341:42 | x | | +| stl.h:341:31:341:31 | y | stl.h:341:31:341:31 | y | | +| stl.h:341:31:341:31 | y | stl.h:341:31:341:31 | y | | +| stl.h:341:31:341:31 | y | stl.h:341:31:341:31 | y | | +| stl.h:341:31:341:31 | y | stl.h:341:31:341:31 | y | | +| stl.h:341:31:341:31 | y | stl.h:341:53:341:53 | y | | +| stl.h:341:31:341:31 | y | stl.h:341:53:341:53 | y | | +| stl.h:341:31:341:31 | y | stl.h:341:53:341:53 | y | | +| stl.h:341:31:341:31 | y | stl.h:341:53:341:53 | y | | +| stl.h:341:31:341:31 | y | stl.h:341:53:341:53 | y | | +| stl.h:341:31:341:31 | y | stl.h:341:53:341:53 | y | | +| stl.h:341:31:341:31 | y | stl.h:341:53:341:53 | y | | +| stl.h:341:31:341:31 | y | stl.h:341:53:341:53 | y | | +| stl.h:341:36:341:43 | call to unknown function | stl.h:341:36:341:43 | constructor init of field first | TAINT | +| stl.h:341:36:341:43 | constructor init of field first [post-this] | stl.h:341:46:341:54 | constructor init of field second [pre-this] | | +| stl.h:341:36:341:43 | constructor init of field first [post-this] | stl.h:341:46:341:54 | constructor init of field second [pre-this] | | +| stl.h:341:36:341:43 | constructor init of field first [post-this] | stl.h:341:46:341:54 | constructor init of field second [pre-this] | | +| stl.h:341:36:341:43 | constructor init of field first [post-this] | stl.h:341:46:341:54 | constructor init of field second [pre-this] | | +| stl.h:341:36:341:43 | constructor init of field first [post-this] | stl.h:341:46:341:54 | constructor init of field second [pre-this] | | +| stl.h:341:36:341:43 | constructor init of field first [post-this] | stl.h:341:46:341:54 | constructor init of field second [pre-this] | | +| stl.h:341:36:341:43 | constructor init of field first [post-this] | stl.h:341:46:341:54 | constructor init of field second [pre-this] | | +| stl.h:341:36:341:43 | constructor init of field first [post-this] | stl.h:341:46:341:54 | constructor init of field second [pre-this] | | +| stl.h:341:36:341:43 | constructor init of field first [pre-this] | stl.h:341:46:341:54 | constructor init of field second [pre-this] | | +| stl.h:341:36:341:43 | constructor init of field first [pre-this] | stl.h:341:46:341:54 | constructor init of field second [pre-this] | | +| stl.h:341:36:341:43 | constructor init of field first [pre-this] | stl.h:341:46:341:54 | constructor init of field second [pre-this] | | +| stl.h:341:36:341:43 | constructor init of field first [pre-this] | stl.h:341:46:341:54 | constructor init of field second [pre-this] | | +| stl.h:341:36:341:43 | constructor init of field first [pre-this] | stl.h:341:46:341:54 | constructor init of field second [pre-this] | | +| stl.h:341:36:341:43 | constructor init of field first [pre-this] | stl.h:341:46:341:54 | constructor init of field second [pre-this] | | +| stl.h:341:36:341:43 | constructor init of field first [pre-this] | stl.h:341:46:341:54 | constructor init of field second [pre-this] | | +| stl.h:341:36:341:43 | constructor init of field first [pre-this] | stl.h:341:46:341:54 | constructor init of field second [pre-this] | | +| stl.h:341:42:341:42 | x | stl.h:341:36:341:43 | constructor init of field first | TAINT | +| stl.h:341:42:341:42 | x | stl.h:341:36:341:43 | constructor init of field first | TAINT | +| stl.h:341:42:341:42 | x | stl.h:341:36:341:43 | constructor init of field first | TAINT | +| stl.h:341:42:341:42 | x | stl.h:341:36:341:43 | constructor init of field first | TAINT | +| stl.h:341:42:341:42 | x | stl.h:341:36:341:43 | constructor init of field first | TAINT | +| stl.h:341:42:341:42 | x | stl.h:341:36:341:43 | constructor init of field first | TAINT | +| stl.h:341:42:341:42 | x | stl.h:341:36:341:43 | constructor init of field first | TAINT | +| stl.h:341:46:341:54 | call to unknown function | stl.h:341:46:341:54 | constructor init of field second | TAINT | +| stl.h:341:53:341:53 | y | stl.h:341:46:341:54 | constructor init of field second | TAINT | +| stl.h:341:53:341:53 | y | stl.h:341:46:341:54 | constructor init of field second | TAINT | +| stl.h:341:53:341:53 | y | stl.h:341:46:341:54 | constructor init of field second | TAINT | +| stl.h:341:53:341:53 | y | stl.h:341:46:341:54 | constructor init of field second | TAINT | +| stl.h:341:53:341:53 | y | stl.h:341:46:341:54 | constructor init of field second | TAINT | +| stl.h:341:53:341:53 | y | stl.h:341:46:341:54 | constructor init of field second | TAINT | +| stl.h:341:53:341:53 | y | stl.h:341:46:341:54 | constructor init of field second | TAINT | +| stl.h:347:109:347:109 | x | stl.h:347:109:347:109 | x | | +| stl.h:347:109:347:109 | x | stl.h:347:109:347:109 | x | | +| stl.h:347:109:347:109 | x | stl.h:347:109:347:109 | x | | +| stl.h:347:109:347:109 | x | stl.h:347:109:347:109 | x | | +| stl.h:347:109:347:109 | x | stl.h:347:109:347:109 | x | | +| stl.h:347:109:347:109 | x | stl.h:347:109:347:109 | x | | +| stl.h:347:109:347:109 | x | stl.h:347:109:347:109 | x | | +| stl.h:347:109:347:109 | x | stl.h:348:40:348:40 | x | | +| stl.h:347:109:347:109 | x | stl.h:348:40:348:40 | x | | +| stl.h:347:109:347:109 | x | stl.h:348:40:348:40 | x | | +| stl.h:347:109:347:109 | x | stl.h:348:40:348:40 | x | | +| stl.h:347:109:347:109 | x | stl.h:348:40:348:40 | x | | +| stl.h:347:109:347:109 | x | stl.h:348:40:348:40 | x | | +| stl.h:347:109:347:109 | x | stl.h:348:40:348:40 | x | | +| stl.h:347:117:347:117 | y | stl.h:347:117:347:117 | y | | +| stl.h:347:117:347:117 | y | stl.h:347:117:347:117 | y | | +| stl.h:347:117:347:117 | y | stl.h:347:117:347:117 | y | | +| stl.h:347:117:347:117 | y | stl.h:347:117:347:117 | y | | +| stl.h:347:117:347:117 | y | stl.h:347:117:347:117 | y | | +| stl.h:347:117:347:117 | y | stl.h:347:117:347:117 | y | | +| stl.h:347:117:347:117 | y | stl.h:347:117:347:117 | y | | +| stl.h:347:117:347:117 | y | stl.h:348:61:348:61 | y | | +| stl.h:347:117:347:117 | y | stl.h:348:61:348:61 | y | | +| stl.h:347:117:347:117 | y | stl.h:348:61:348:61 | y | | +| stl.h:347:117:347:117 | y | stl.h:348:61:348:61 | y | | +| stl.h:347:117:347:117 | y | stl.h:348:61:348:61 | y | | +| stl.h:347:117:347:117 | y | stl.h:348:61:348:61 | y | | +| stl.h:347:117:347:117 | y | stl.h:348:61:348:61 | y | | +| stl.h:348:10:348:63 | call to pair | stl.h:348:10:348:63 | call to pair | TAINT | +| stl.h:348:10:348:63 | call to pair | stl.h:348:10:348:63 | call to pair | TAINT | +| stl.h:348:10:348:63 | call to pair | stl.h:348:10:348:63 | call to pair | TAINT | +| stl.h:348:10:348:63 | call to pair | stl.h:348:10:348:63 | call to pair | TAINT | +| stl.h:348:10:348:63 | call to pair | stl.h:348:10:348:63 | call to pair | TAINT | +| stl.h:348:10:348:63 | call to pair | stl.h:348:10:348:63 | call to pair | TAINT | +| stl.h:348:23:348:38 | ref arg call to forward | stl.h:347:109:347:109 | x | | +| stl.h:348:23:348:38 | ref arg call to forward | stl.h:347:109:347:109 | x | | +| stl.h:348:23:348:38 | ref arg call to forward | stl.h:347:109:347:109 | x | | +| stl.h:348:23:348:38 | ref arg call to forward | stl.h:347:109:347:109 | x | | +| stl.h:348:23:348:38 | ref arg call to forward | stl.h:348:40:348:40 | x [inner post update] | | +| stl.h:348:23:348:38 | ref arg call to forward | stl.h:348:40:348:40 | x [inner post update] | | +| stl.h:348:23:348:38 | ref arg call to forward | stl.h:348:40:348:40 | x [inner post update] | | +| stl.h:348:23:348:38 | ref arg call to forward | stl.h:348:40:348:40 | x [inner post update] | | +| stl.h:348:40:348:40 | x | stl.h:348:23:348:38 | call to forward | | +| stl.h:348:40:348:40 | x | stl.h:348:23:348:38 | call to forward | | +| stl.h:348:40:348:40 | x | stl.h:348:23:348:38 | call to forward | | +| stl.h:348:40:348:40 | x | stl.h:348:23:348:38 | call to forward | | +| stl.h:348:40:348:40 | x | stl.h:348:23:348:38 | call to forward | | +| stl.h:348:40:348:40 | x | stl.h:348:23:348:38 | call to forward | | +| stl.h:348:44:348:59 | call to forward | stl.h:348:10:348:63 | call to pair | TAINT | +| stl.h:348:44:348:59 | call to forward | stl.h:348:10:348:63 | call to pair | TAINT | +| stl.h:348:44:348:59 | ref arg call to forward | stl.h:347:117:347:117 | y | | +| stl.h:348:44:348:59 | ref arg call to forward | stl.h:347:117:347:117 | y | | +| stl.h:348:44:348:59 | ref arg call to forward | stl.h:347:117:347:117 | y | | +| stl.h:348:44:348:59 | ref arg call to forward | stl.h:347:117:347:117 | y | | +| stl.h:348:44:348:59 | ref arg call to forward | stl.h:348:61:348:61 | y [inner post update] | | +| stl.h:348:44:348:59 | ref arg call to forward | stl.h:348:61:348:61 | y [inner post update] | | +| stl.h:348:44:348:59 | ref arg call to forward | stl.h:348:61:348:61 | y [inner post update] | | +| stl.h:348:44:348:59 | ref arg call to forward | stl.h:348:61:348:61 | y [inner post update] | | +| stl.h:348:61:348:61 | y | stl.h:348:10:348:63 | call to pair | TAINT | +| stl.h:348:61:348:61 | y | stl.h:348:10:348:63 | call to pair | TAINT | +| stl.h:348:61:348:61 | y | stl.h:348:44:348:59 | call to forward | | +| stl.h:348:61:348:61 | y | stl.h:348:44:348:59 | call to forward | | +| stl.h:348:61:348:61 | y | stl.h:348:44:348:59 | call to forward | | +| stl.h:348:61:348:61 | y | stl.h:348:44:348:59 | call to forward | | +| stl.h:348:61:348:61 | y | stl.h:348:44:348:59 | call to forward | | +| stl.h:348:61:348:61 | y | stl.h:348:44:348:59 | call to forward | | | string.cpp:24:12:24:17 | call to source | string.cpp:28:7:28:7 | a | | | string.cpp:25:16:25:20 | 123 | string.cpp:25:16:25:21 | call to basic_string | TAINT | | string.cpp:25:16:25:21 | call to basic_string | string.cpp:29:7:29:7 | b | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h index 4def0a84e5a..4873d48d5d8 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h @@ -24,6 +24,12 @@ struct remove_reference { typedef T type; }; template using remove_reference_t = typename remove_reference::type; +namespace std +{ + template constexpr T&& forward(remove_reference_t& t) noexcept; + template constexpr T&& forward(remove_reference_t&& t) noexcept; +} + // --- iterator --- namespace std { @@ -338,7 +344,9 @@ namespace std { void swap(pair& p) /*noexcept(...)*/; }; - template constexpr pair, remove_reference_t> make_pair(T1&& x, T2&& y); + template constexpr pair, remove_reference_t> make_pair(T1&& x, T2&& y) { + return pair(std::forward(x), std::forward(y)); + } } // --- map --- From 4b0e9a4fb1b927924dc5070fc1bae9c2c2dc37c2 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 Oct 2020 10:55:13 +0100 Subject: [PATCH 174/411] C++: Remove the model of make_pair. --- .../cpp/models/implementations/StdPair.qll | 13 ---------- .../dataflow/taint-tests/localTaint.expected | 25 ------------------- 2 files changed, 38 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll index 7b17ec05800..b36f7ab3325 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdPair.qll @@ -31,19 +31,6 @@ class StdPairConstructor extends Constructor, TaintFunction { } } -/** - * An instantiation of `std::make_pair`. - */ -class StdMakePair extends TaintFunction { - StdMakePair() { this.hasQualifiedName("std", "make_pair") } - - override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - // taint flow from first parameter to the returned object - input.isParameterDeref(1) and - output.isReturnValue() - } -} - /** * The standard pair `swap` function. */ 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 1f1bb019646..56cf29bde53 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -518,17 +518,8 @@ | map.cpp:76:7:76:7 | l [post update] | map.cpp:78:7:78:7 | l | | | map.cpp:77:7:77:7 | l [post update] | map.cpp:78:7:78:7 | l | | | map.cpp:80:7:80:15 | call to make_pair | map.cpp:80:7:80:29 | call to pair | TAINT | -| map.cpp:80:24:80:28 | 456 | map.cpp:80:7:80:15 | call to make_pair | TAINT | -| map.cpp:81:24:81:28 | 456 | map.cpp:81:7:81:15 | call to make_pair | TAINT | -| map.cpp:82:24:82:28 | 456 | map.cpp:82:7:82:15 | call to make_pair | TAINT | | map.cpp:83:7:83:15 | call to make_pair | map.cpp:83:7:83:32 | call to pair | TAINT | -| map.cpp:83:27:83:31 | 456 | map.cpp:83:7:83:15 | call to make_pair | TAINT | -| map.cpp:84:27:84:31 | 456 | map.cpp:84:7:84:15 | call to make_pair | TAINT | -| map.cpp:85:27:85:31 | 456 | map.cpp:85:7:85:15 | call to make_pair | TAINT | | map.cpp:86:7:86:15 | call to make_pair | map.cpp:86:7:86:32 | call to pair | TAINT | -| map.cpp:86:24:86:29 | call to source | map.cpp:86:7:86:15 | call to make_pair | TAINT | -| map.cpp:87:24:87:29 | call to source | map.cpp:87:7:87:15 | call to make_pair | TAINT | -| map.cpp:88:24:88:29 | call to source | map.cpp:88:7:88:15 | call to make_pair | TAINT | | map.cpp:91:6:91:14 | call to make_pair | map.cpp:91:6:91:49 | call to pair | TAINT | | map.cpp:91:6:91:49 | call to pair | map.cpp:91:2:91:49 | ... = ... | | | map.cpp:91:6:91:49 | call to pair | map.cpp:92:7:92:7 | m | | @@ -536,8 +527,6 @@ | map.cpp:91:6:91:49 | call to pair | map.cpp:94:7:94:7 | m | | | map.cpp:91:6:91:49 | call to pair | map.cpp:95:7:95:7 | m | | | map.cpp:91:6:91:49 | call to pair | map.cpp:96:7:96:7 | m | | -| map.cpp:91:33:91:38 | call to source | map.cpp:91:16:91:24 | call to make_pair | TAINT | -| map.cpp:91:44:91:48 | 789 | map.cpp:91:6:91:14 | call to make_pair | TAINT | | map.cpp:92:7:92:7 | m | map.cpp:92:7:92:7 | call to pair | TAINT | | map.cpp:94:7:94:7 | m [post update] | map.cpp:95:7:95:7 | m | | | map.cpp:94:7:94:7 | m [post update] | map.cpp:96:7:96:7 | m | | @@ -598,7 +587,6 @@ | map.cpp:104:17:104:30 | call to make_pair | map.cpp:104:17:104:44 | call to pair | TAINT | | map.cpp:104:17:104:44 | call to pair | map.cpp:104:7:104:8 | ref arg m1 | TAINT | | map.cpp:104:17:104:44 | call to pair | map.cpp:104:10:104:15 | call to insert | TAINT | -| map.cpp:104:39:104:43 | def | map.cpp:104:17:104:30 | call to make_pair | TAINT | | map.cpp:104:47:104:51 | first | map.cpp:104:7:104:51 | call to iterator | | | map.cpp:105:7:105:8 | ref arg m2 | map.cpp:111:7:111:8 | m2 | | | map.cpp:105:7:105:8 | ref arg m2 | map.cpp:117:7:117:8 | m2 | | @@ -618,7 +606,6 @@ | map.cpp:105:17:105:30 | call to make_pair | map.cpp:105:17:105:47 | call to pair | TAINT | | map.cpp:105:17:105:47 | call to pair | map.cpp:105:7:105:8 | ref arg m2 | TAINT | | map.cpp:105:17:105:47 | call to pair | map.cpp:105:10:105:15 | call to insert | TAINT | -| map.cpp:105:39:105:44 | call to source | map.cpp:105:17:105:30 | call to make_pair | TAINT | | map.cpp:105:50:105:54 | first | map.cpp:105:7:105:54 | call to iterator | | | map.cpp:106:7:106:8 | ref arg m3 | map.cpp:112:7:112:8 | m3 | | | map.cpp:106:7:106:8 | ref arg m3 | map.cpp:118:7:118:8 | m3 | | @@ -629,7 +616,6 @@ | map.cpp:106:17:106:30 | call to make_pair | map.cpp:106:17:106:47 | call to pair | TAINT | | map.cpp:106:17:106:47 | call to pair | map.cpp:106:7:106:8 | ref arg m3 | TAINT | | map.cpp:106:17:106:47 | call to pair | map.cpp:106:10:106:15 | call to insert | TAINT | -| map.cpp:106:42:106:46 | def | map.cpp:106:17:106:30 | call to make_pair | TAINT | | map.cpp:106:50:106:54 | first | map.cpp:106:7:106:54 | call to iterator | | | map.cpp:107:7:107:8 | ref arg m4 | map.cpp:113:7:113:8 | m4 | | | map.cpp:107:7:107:8 | ref arg m4 | map.cpp:119:7:119:8 | m4 | | @@ -892,25 +878,21 @@ | map.cpp:175:13:175:26 | call to make_pair | map.cpp:175:13:175:36 | call to pair | TAINT | | map.cpp:175:13:175:36 | call to pair | map.cpp:175:2:175:4 | ref arg m14 | TAINT | | map.cpp:175:13:175:36 | call to pair | map.cpp:175:6:175:11 | call to insert | TAINT | -| map.cpp:175:33:175:35 | a | map.cpp:175:13:175:26 | call to make_pair | TAINT | | map.cpp:176:2:176:4 | ref arg m14 | map.cpp:177:2:177:4 | m14 | | | map.cpp:176:2:176:4 | ref arg m14 | map.cpp:178:2:178:4 | m14 | | | map.cpp:176:2:176:4 | ref arg m14 | map.cpp:249:1:249:1 | m14 | | | map.cpp:176:13:176:26 | call to make_pair | map.cpp:176:13:176:41 | call to pair | TAINT | | map.cpp:176:13:176:41 | call to pair | map.cpp:176:2:176:4 | ref arg m14 | TAINT | | map.cpp:176:13:176:41 | call to pair | map.cpp:176:6:176:11 | call to insert | TAINT | -| map.cpp:176:33:176:38 | call to source | map.cpp:176:13:176:26 | call to make_pair | TAINT | | map.cpp:177:2:177:4 | ref arg m14 | map.cpp:178:2:178:4 | m14 | | | map.cpp:177:2:177:4 | ref arg m14 | map.cpp:249:1:249:1 | m14 | | | map.cpp:177:13:177:26 | call to make_pair | map.cpp:177:13:177:41 | call to pair | TAINT | | map.cpp:177:13:177:41 | call to pair | map.cpp:177:2:177:4 | ref arg m14 | TAINT | | map.cpp:177:13:177:41 | call to pair | map.cpp:177:6:177:11 | call to insert | TAINT | -| map.cpp:177:33:177:38 | call to source | map.cpp:177:13:177:26 | call to make_pair | TAINT | | map.cpp:178:2:178:4 | ref arg m14 | map.cpp:249:1:249:1 | m14 | | | map.cpp:178:13:178:26 | call to make_pair | map.cpp:178:13:178:36 | call to pair | TAINT | | map.cpp:178:13:178:36 | call to pair | map.cpp:178:2:178:4 | ref arg m14 | TAINT | | map.cpp:178:13:178:36 | call to pair | map.cpp:178:6:178:11 | call to insert | TAINT | -| map.cpp:178:33:178:35 | d | map.cpp:178:13:178:26 | call to make_pair | TAINT | | map.cpp:179:7:179:8 | ref arg m2 | map.cpp:180:7:180:8 | m2 | | | map.cpp:179:7:179:8 | ref arg m2 | map.cpp:181:7:181:8 | m2 | | | map.cpp:179:7:179:8 | ref arg m2 | map.cpp:182:7:182:8 | m2 | | @@ -1244,7 +1226,6 @@ | map.cpp:256:17:256:30 | call to make_pair | map.cpp:256:17:256:44 | call to pair | TAINT | | map.cpp:256:17:256:44 | call to pair | map.cpp:256:7:256:8 | ref arg m1 | TAINT | | map.cpp:256:17:256:44 | call to pair | map.cpp:256:10:256:15 | call to insert | TAINT | -| map.cpp:256:39:256:43 | def | map.cpp:256:17:256:30 | call to make_pair | TAINT | | map.cpp:256:47:256:51 | first | map.cpp:256:7:256:51 | call to iterator | | | map.cpp:257:7:257:8 | ref arg m2 | map.cpp:263:7:263:8 | m2 | | | map.cpp:257:7:257:8 | ref arg m2 | map.cpp:269:7:269:8 | m2 | | @@ -1261,7 +1242,6 @@ | map.cpp:257:17:257:30 | call to make_pair | map.cpp:257:17:257:47 | call to pair | TAINT | | map.cpp:257:17:257:47 | call to pair | map.cpp:257:7:257:8 | ref arg m2 | TAINT | | map.cpp:257:17:257:47 | call to pair | map.cpp:257:10:257:15 | call to insert | TAINT | -| map.cpp:257:39:257:44 | call to source | map.cpp:257:17:257:30 | call to make_pair | TAINT | | map.cpp:257:50:257:54 | first | map.cpp:257:7:257:54 | call to iterator | | | map.cpp:258:7:258:8 | ref arg m3 | map.cpp:264:7:264:8 | m3 | | | map.cpp:258:7:258:8 | ref arg m3 | map.cpp:270:7:270:8 | m3 | | @@ -1272,7 +1252,6 @@ | map.cpp:258:17:258:30 | call to make_pair | map.cpp:258:17:258:47 | call to pair | TAINT | | map.cpp:258:17:258:47 | call to pair | map.cpp:258:7:258:8 | ref arg m3 | TAINT | | map.cpp:258:17:258:47 | call to pair | map.cpp:258:10:258:15 | call to insert | TAINT | -| map.cpp:258:42:258:46 | def | map.cpp:258:17:258:30 | call to make_pair | TAINT | | map.cpp:258:50:258:54 | first | map.cpp:258:7:258:54 | call to iterator | | | map.cpp:259:7:259:8 | ref arg m4 | map.cpp:265:7:265:8 | m4 | | | map.cpp:259:7:259:8 | ref arg m4 | map.cpp:271:7:271:8 | m4 | | @@ -1523,25 +1502,21 @@ | map.cpp:327:13:327:26 | call to make_pair | map.cpp:327:13:327:36 | call to pair | TAINT | | map.cpp:327:13:327:36 | call to pair | map.cpp:327:2:327:4 | ref arg m14 | TAINT | | map.cpp:327:13:327:36 | call to pair | map.cpp:327:6:327:11 | call to insert | TAINT | -| map.cpp:327:33:327:35 | a | map.cpp:327:13:327:26 | call to make_pair | TAINT | | map.cpp:328:2:328:4 | ref arg m14 | map.cpp:329:2:329:4 | m14 | | | map.cpp:328:2:328:4 | ref arg m14 | map.cpp:330:2:330:4 | m14 | | | map.cpp:328:2:328:4 | ref arg m14 | map.cpp:398:1:398:1 | m14 | | | map.cpp:328:13:328:26 | call to make_pair | map.cpp:328:13:328:41 | call to pair | TAINT | | map.cpp:328:13:328:41 | call to pair | map.cpp:328:2:328:4 | ref arg m14 | TAINT | | map.cpp:328:13:328:41 | call to pair | map.cpp:328:6:328:11 | call to insert | TAINT | -| map.cpp:328:33:328:38 | call to source | map.cpp:328:13:328:26 | call to make_pair | TAINT | | map.cpp:329:2:329:4 | ref arg m14 | map.cpp:330:2:330:4 | m14 | | | map.cpp:329:2:329:4 | ref arg m14 | map.cpp:398:1:398:1 | m14 | | | map.cpp:329:13:329:26 | call to make_pair | map.cpp:329:13:329:41 | call to pair | TAINT | | map.cpp:329:13:329:41 | call to pair | map.cpp:329:2:329:4 | ref arg m14 | TAINT | | map.cpp:329:13:329:41 | call to pair | map.cpp:329:6:329:11 | call to insert | TAINT | -| map.cpp:329:33:329:38 | call to source | map.cpp:329:13:329:26 | call to make_pair | TAINT | | map.cpp:330:2:330:4 | ref arg m14 | map.cpp:398:1:398:1 | m14 | | | map.cpp:330:13:330:26 | call to make_pair | map.cpp:330:13:330:36 | call to pair | TAINT | | map.cpp:330:13:330:36 | call to pair | map.cpp:330:2:330:4 | ref arg m14 | TAINT | | map.cpp:330:13:330:36 | call to pair | map.cpp:330:6:330:11 | call to insert | TAINT | -| map.cpp:330:33:330:35 | d | map.cpp:330:13:330:26 | call to make_pair | TAINT | | map.cpp:331:7:331:8 | ref arg m2 | map.cpp:332:7:332:8 | m2 | | | map.cpp:331:7:331:8 | ref arg m2 | map.cpp:333:7:333:8 | m2 | | | map.cpp:331:7:331:8 | ref arg m2 | map.cpp:398:1:398:1 | m2 | | From b5d05f99c99e3835579ef8206949332be51dc0d2 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Fri, 2 Oct 2020 12:04:43 +0200 Subject: [PATCH 175/411] Python: Fix test output --- .../ql/test/library-tests/PointsTo/import_star/Values.expected | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/test/library-tests/PointsTo/import_star/Values.expected b/python/ql/test/library-tests/PointsTo/import_star/Values.expected index 6d0f8d1ff05..965191f1a3e 100644 --- a/python/ql/test/library-tests/PointsTo/import_star/Values.expected +++ b/python/ql/test/library-tests/PointsTo/import_star/Values.expected @@ -1,4 +1,4 @@ | nested/__init__.py:1:6:1:12 | ControlFlowNode for ImportExpr | import | nested/nested.py:0:0:0:0 | Module nested.nested | | nested/nested.py:1:1:1:13 | ControlFlowNode for FunctionExpr | import | nested/nested.py:1:1:1:13 | Function nested | -| test.py:1:6:1:11 | ControlFlowNode for ImportExpr | import | file://:0:0:0:0 | Package nested | +| test.py:1:6:1:11 | ControlFlowNode for ImportExpr | import | nested:0:0:0:0 | Package nested | | test.py:2:1:2:6 | ControlFlowNode for nested | import | nested/nested.py:1:1:1:13 | Function nested | From de07d9e5d98ccd02f9b9c27ab3e38a4970789d0c Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 2 Oct 2020 13:34:33 +0200 Subject: [PATCH 176/411] Python: Highlight that os.popen is not only problem for extra alerts --- .../Security-new-dataflow/CWE-078/CommandInjection.ql | 6 +++++- .../Security-new-dataflow/CWE-078/command_injection.py | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/python/ql/src/experimental/Security-new-dataflow/CWE-078/CommandInjection.ql b/python/ql/src/experimental/Security-new-dataflow/CWE-078/CommandInjection.ql index 1f826acb932..49aa1cd1885 100755 --- a/python/ql/src/experimental/Security-new-dataflow/CWE-078/CommandInjection.ql +++ b/python/ql/src/experimental/Security-new-dataflow/CWE-078/CommandInjection.ql @@ -28,7 +28,7 @@ class CommandInjectionConfiguration extends TaintTracking::Configuration { override predicate isSink(DataFlow::Node sink) { sink = any(SystemCommandExecution e).getCommand() and - // Since the implementation of os.popen looks like + // Since the implementation of standard library functions such `os.popen` looks like // ```py // def popen(cmd, mode="r", buffering=-1): // ... @@ -49,6 +49,10 @@ class CommandInjectionConfiguration extends TaintTracking::Configuration { // Best solution I could come up with is to exclude all sinks inside the standard // library -- this does have a downside: If we have overlooked a function in the // standard library that internally runs a command, we no longer give an alert :| + // + // This does not only affect `os.popen`, but also the helper functions in `subprocess`. See + // https://github.com/python/cpython/blob/fa7ce080175f65d678a7d5756c94f82887fc9803/Lib/os.py#L974 + // https://github.com/python/cpython/blob/fa7ce080175f65d678a7d5756c94f82887fc9803/Lib/subprocess.py#L341 not sink.getLocation().getFile().inStdlib() } } diff --git a/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/command_injection.py b/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/command_injection.py index d92690c57fe..75125f59fca 100644 --- a/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/command_injection.py +++ b/python/ql/test/experimental/query-tests/Security-new-dataflow/CWE-078/command_injection.py @@ -46,8 +46,8 @@ def not_into_sink_impl(): flow through the actual `popen` function to the internal call to `subprocess.Popen` -- we would usually see that flow since we extract the `os.py` file from the standard library. - os.popen implementation: - https://github.com/python/cpython/blob/fa7ce080175f65d678a7d5756c94f82887fc9803/Lib/os.py#L974 + os.popen implementation: https://github.com/python/cpython/blob/fa7ce080175f65d678a7d5756c94f82887fc9803/Lib/os.py#L974 + subprocess.call implementation: https://github.com/python/cpython/blob/fa7ce080175f65d678a7d5756c94f82887fc9803/Lib/subprocess.py#L341 """ command = request.args.get('command', '') os.system(command) From 68eacef23c91bd6a576a6d835a054a12bb4bf670 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 2 Oct 2020 13:38:54 +0200 Subject: [PATCH 177/411] Python: Refactor OsExecCall and friends for better readability --- .../semmle/python/frameworks/Stdlib.qll | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 35ade8e326e..5fa36c67e09 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -128,9 +128,10 @@ private module Stdlib { */ private class OsExecCall extends SystemCommandExecution::Range { OsExecCall() { - this.asCfgNode().(CallNode).getFunction() = - os_attr(["execl", "execle", "execlp", "execlpe", "execv", "execve", "execvp", "execvpe"]) - .asCfgNode() + exists(string name | + name in ["execl", "execle", "execlp", "execlpe", "execv", "execve", "execvp", "execvpe"] and + this.asCfgNode().(CallNode).getFunction() = os_attr(name).asCfgNode() + ) } override DataFlow::Node getCommand() { @@ -144,9 +145,11 @@ private module Stdlib { */ private class OsSpawnCall extends SystemCommandExecution::Range { OsSpawnCall() { - this.asCfgNode().(CallNode).getFunction() = - os_attr(["spawnl", "spawnle", "spawnlp", "spawnlpe", "spawnv", "spawnve", "spawnvp", - "spawnvpe"]).asCfgNode() + exists(string name | + name in ["spawnl", "spawnle", "spawnlp", "spawnlpe", "spawnv", "spawnve", "spawnvp", + "spawnvpe"] and + this.asCfgNode().(CallNode).getFunction() = os_attr(name).asCfgNode() + ) } override DataFlow::Node getCommand() { @@ -247,8 +250,10 @@ private module Stdlib { SubprocessPopenCall() { call = this.asCfgNode() and - call.getFunction() = - subprocess_attr(["Popen", "call", "check_call", "check_output", "run"]).asCfgNode() + exists(string name | + name in ["Popen", "call", "check_call", "check_output", "run"] and + call.getFunction() = subprocess_attr(name).asCfgNode() + ) } /** Gets the ControlFlowNode for the `args` argument, if any. */ From 8f4982d3f5bfb24d2fdaf2f6a9c0d479db50ea4e Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 2 Oct 2020 14:10:28 +0200 Subject: [PATCH 178/411] C++: Remove flow into ReadSideEffect instructions in simpleInstructionLocalFlowStep --- .../ir/dataflow/internal/DataFlowPrivate.qll | 59 +++++++++++++++---- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 15 +++-- .../taint-tests/IRTaintTestCommon.qll | 11 ++-- 3 files changed, 58 insertions(+), 27 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index fb9b39c0fda..482b9d6cb7b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -7,15 +7,33 @@ private import DataFlowDispatch * A data flow node that occurs as the argument of a call and is passed as-is * to the callable. Instance arguments (`this` pointer) are also included. */ -class ArgumentNode extends InstructionNode { +class ArgumentNode extends Node { ArgumentNode() { - exists(CallInstruction call | - instr = call.getAnArgument() - or - instr.(ReadSideEffectInstruction).getPrimaryInstruction() = call - ) + // To avoid making this class abstract, we enumerate its values here. + this instanceof PrimaryArgumentNode or + this instanceof SideEffectArgumentNode } + /** + * Holds if this argument occurs at the given position in the given call. + * The instance argument is considered to have index `-1`. + */ + predicate argumentOf(DataFlowCall call, int pos) { + this.(PrimaryArgumentNode).argumentOf(call, pos) or + this.(SideEffectArgumentNode).argumentOf(call, pos) + } + + /** Gets the call in which this node is an argument. */ + DataFlowCall getCall() { this.argumentOf(result, _) } +} + +/** + * A data flow node that occurs as the argument to a call, or an + * implicit `this` pointer argument. + */ +private class PrimaryArgumentNode extends InstructionNode { + PrimaryArgumentNode() { exists(CallInstruction call | instr = call.getAnArgument()) } + /** * Holds if this argument occurs at the given position in the given call. * The instance argument is considered to have index `-1`. @@ -24,16 +42,33 @@ class ArgumentNode extends InstructionNode { instr = call.getPositionalArgument(pos) or instr = call.getThisArgument() and pos = -1 - or - exists(ReadSideEffectInstruction read | - read = instr and + } +} + +/** + * A data flow node representing the read side effect of a call on a + * specific parameter. + */ +private class SideEffectArgumentNode extends OperandNode { + override SideEffectOperand op; + ReadSideEffectInstruction read; + + SideEffectArgumentNode() { + exists(CallInstruction call | read.getPrimaryInstruction() = call and - pos = getArgumentPosOfSideEffect(read.getIndex()) + op = read.getSideEffectOperand() ) } - /** Gets the call in which this node is an argument. */ - DataFlowCall getCall() { this.argumentOf(result, _) } + /** + * Holds if this argument occurs at the given position in the given call. + * See `getArgumentPosOfSideEffect` for a describing of how read side effects + * are assigned an argument position. + */ + predicate argumentOf(DataFlowCall call, int pos) { + read.getPrimaryInstruction() = call and + pos = getArgumentPosOfSideEffect(read.getIndex()) + } } private newtype TReturnKind = diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 024e2386af2..054c42721af 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -509,12 +509,15 @@ class DefinitionByReferenceNode extends InstructionNode { * A node representing the memory pointed to by a function argument. * * This class exists only in order to override `toString`, which would - * otherwise be the default implementation inherited from `InstructionNode`. + * otherwise be the default implementation inherited from `OperandNode`. */ -private class ArgumentIndirectionNode extends InstructionNode { - override ReadSideEffectInstruction instr; +private class ArgumentIndirectionNode extends OperandNode { + override SideEffectOperand op; + ReadSideEffectInstruction read; - override string toString() { result = "Argument " + instr.getIndex() + " indirection" } + ArgumentIndirectionNode() { read.getSideEffectOperand() = op } + + override string toString() { result = "Argument " + read.getIndex() + " indirection" } } /** @@ -680,10 +683,6 @@ private predicate simpleInstructionLocalFlowStep(Operand opFrom, Instruction iTo or iTo.(PhiInstruction).getAnInputOperand() = opFrom or - // A read side effect is almost never exact since we don't know exactly how - // much memory the callee will read. - iTo.(ReadSideEffectInstruction).getSideEffectOperand() = opFrom - or // Treat all conversions as flow, even conversions between different numeric types. iTo.(ConvertInstruction).getUnaryOperand() = opFrom or diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/IRTaintTestCommon.qll b/cpp/ql/test/library-tests/dataflow/taint-tests/IRTaintTestCommon.qll index 4d2772be0c6..715d1883525 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/IRTaintTestCommon.qll +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/IRTaintTestCommon.qll @@ -25,13 +25,10 @@ class TestAllocationConfig extends TaintTracking::Configuration { sink.(DataFlow::ExprNode).getConvertedExpr() instanceof ReferenceDereferenceExpr ) or - sink - .asInstruction() - .(ReadSideEffectInstruction) - .getPrimaryInstruction() - .(CallInstruction) - .getStaticCallTarget() - .hasName("sink") + exists(ReadSideEffectInstruction read | + read.getSideEffectOperand() = sink.asOperand() and + read.getPrimaryInstruction().(CallInstruction).getStaticCallTarget().hasName("sink") + ) } override predicate isSanitizer(DataFlow::Node barrier) { From 48902c07a4830ce527d315d5a1d2dff82f3c7898 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 2 Oct 2020 14:10:58 +0200 Subject: [PATCH 179/411] C++: Accept test changes --- .../dataflow/fields/ir-path-flow.expected | 150 +++++------------- 1 file changed, 40 insertions(+), 110 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected index 28acefe5514..ed5153da336 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected @@ -1,15 +1,12 @@ edges -| A.cpp:55:5:55:5 | set output argument [c] | A.cpp:56:10:56:10 | Argument -1 indirection [c] | +| A.cpp:55:5:55:5 | set output argument [c] | A.cpp:56:13:56:15 | call to get | | A.cpp:55:12:55:19 | (C *)... | A.cpp:55:5:55:5 | set output argument [c] | | A.cpp:55:12:55:19 | new | A.cpp:55:12:55:19 | (C *)... | -| A.cpp:56:10:56:10 | Argument -1 indirection [c] | A.cpp:56:13:56:15 | call to get | -| A.cpp:57:10:57:25 | Argument -1 indirection [c] | A.cpp:57:28:57:30 | call to get | -| A.cpp:57:11:57:24 | B output argument [c] | A.cpp:57:10:57:25 | Argument -1 indirection [c] | +| A.cpp:57:11:57:24 | B output argument [c] | A.cpp:57:28:57:30 | call to get | | A.cpp:57:17:57:23 | new | A.cpp:57:11:57:24 | B output argument [c] | | A.cpp:98:12:98:18 | new | A.cpp:100:5:100:13 | Store | -| A.cpp:100:5:100:13 | Chi [a] | A.cpp:101:8:101:9 | Argument 0 indirection [a] | +| A.cpp:100:5:100:13 | Chi [a] | A.cpp:103:14:103:14 | *c [a] | | A.cpp:100:5:100:13 | Store | A.cpp:100:5:100:13 | Chi [a] | -| A.cpp:101:8:101:9 | Argument 0 indirection [a] | A.cpp:103:14:103:14 | *c [a] | | A.cpp:103:14:103:14 | *c [a] | A.cpp:107:16:107:16 | a | | A.cpp:126:5:126:5 | Chi [c] | A.cpp:131:8:131:8 | f7 output argument [c] | | A.cpp:126:5:126:5 | set output argument [c] | A.cpp:126:5:126:5 | Chi [c] | @@ -28,10 +25,8 @@ edges | A.cpp:151:18:151:18 | Chi [c] | A.cpp:154:13:154:13 | c | | A.cpp:151:18:151:18 | D output argument [c] | A.cpp:151:18:151:18 | Chi [c] | | A.cpp:151:18:151:18 | b | A.cpp:151:12:151:24 | D output argument [b] | -| C.cpp:18:12:18:18 | C output argument [s1] | C.cpp:19:5:19:5 | Argument -1 indirection [s1] | -| C.cpp:18:12:18:18 | C output argument [s3] | C.cpp:19:5:19:5 | Argument -1 indirection [s3] | -| C.cpp:19:5:19:5 | Argument -1 indirection [s1] | C.cpp:27:8:27:11 | *#this [s1] | -| C.cpp:19:5:19:5 | Argument -1 indirection [s3] | C.cpp:27:8:27:11 | *#this [s3] | +| C.cpp:18:12:18:18 | C output argument [s1] | C.cpp:27:8:27:11 | *#this [s1] | +| C.cpp:18:12:18:18 | C output argument [s3] | C.cpp:27:8:27:11 | *#this [s3] | | C.cpp:22:12:22:21 | Chi [s1] | C.cpp:24:5:24:25 | Chi [s1] | | C.cpp:22:12:22:21 | Store | C.cpp:22:12:22:21 | Chi [s1] | | C.cpp:22:12:22:21 | new | C.cpp:22:12:22:21 | Store | @@ -102,18 +97,14 @@ edges | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:10:8:10:15 | * ... | | arrays.cpp:15:14:15:23 | call to user_input | arrays.cpp:16:8:16:13 | access to array | | arrays.cpp:36:26:36:35 | call to user_input | arrays.cpp:37:24:37:27 | data | -| by_reference.cpp:50:3:50:3 | setDirectly output argument [a] | by_reference.cpp:51:8:51:8 | Argument -1 indirection [a] | +| by_reference.cpp:50:3:50:3 | setDirectly output argument [a] | by_reference.cpp:51:10:51:20 | call to getDirectly | | by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:50:3:50:3 | setDirectly output argument [a] | -| by_reference.cpp:51:8:51:8 | Argument -1 indirection [a] | by_reference.cpp:51:10:51:20 | call to getDirectly | -| by_reference.cpp:56:3:56:3 | setIndirectly output argument [a] | by_reference.cpp:57:8:57:8 | Argument -1 indirection [a] | +| by_reference.cpp:56:3:56:3 | setIndirectly output argument [a] | by_reference.cpp:57:10:57:22 | call to getIndirectly | | by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:56:3:56:3 | setIndirectly output argument [a] | -| by_reference.cpp:57:8:57:8 | Argument -1 indirection [a] | by_reference.cpp:57:10:57:22 | call to getIndirectly | -| by_reference.cpp:62:3:62:3 | setThroughNonMember output argument [a] | by_reference.cpp:63:8:63:8 | Argument -1 indirection [a] | +| by_reference.cpp:62:3:62:3 | setThroughNonMember output argument [a] | by_reference.cpp:63:10:63:28 | call to getThroughNonMember | | by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:62:3:62:3 | setThroughNonMember output argument [a] | -| by_reference.cpp:63:8:63:8 | Argument -1 indirection [a] | by_reference.cpp:63:10:63:28 | call to getThroughNonMember | -| by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] | by_reference.cpp:69:22:69:23 | Argument 0 indirection [a] | +| by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] | by_reference.cpp:69:8:69:20 | call to nonMemberGetA | | by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] | -| by_reference.cpp:69:22:69:23 | Argument 0 indirection [a] | by_reference.cpp:69:8:69:20 | call to nonMemberGetA | | by_reference.cpp:84:3:84:25 | Chi [a] | by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | | by_reference.cpp:84:3:84:25 | Chi [a] | by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | | by_reference.cpp:84:3:84:25 | Store | by_reference.cpp:84:3:84:25 | Chi [a] | @@ -150,104 +141,75 @@ edges | by_reference.cpp:128:15:128:23 | Chi | by_reference.cpp:128:15:128:23 | Chi [a] | | by_reference.cpp:128:15:128:23 | Chi [a] | by_reference.cpp:136:16:136:16 | a | | by_reference.cpp:128:15:128:23 | taint_a_ref output argument [array content] | by_reference.cpp:128:15:128:23 | Chi | -| complex.cpp:40:17:40:17 | *b [a_] | complex.cpp:51:16:51:16 | Argument -1 indirection [a_] | -| complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:51:16:51:16 | Argument -1 indirection [b_] | -| complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:52:16:52:16 | Argument -1 indirection [b_] | -| complex.cpp:51:16:51:16 | Argument -1 indirection [a_] | complex.cpp:51:18:51:18 | call to a | -| complex.cpp:51:16:51:16 | Argument -1 indirection [b_] | complex.cpp:51:16:51:16 | a output argument [b_] | -| complex.cpp:51:16:51:16 | a output argument [b_] | complex.cpp:52:16:52:16 | Argument -1 indirection [b_] | -| complex.cpp:52:16:52:16 | Argument -1 indirection [b_] | complex.cpp:52:18:52:18 | call to b | -| complex.cpp:62:12:62:12 | setA output argument [a_] | complex.cpp:68:7:68:8 | Argument 0 indirection [a_] | +| complex.cpp:40:17:40:17 | *b [a_] | complex.cpp:51:18:51:18 | call to a | +| complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:51:16:51:16 | a output argument [b_] | +| complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:52:18:52:18 | call to b | +| complex.cpp:51:16:51:16 | a output argument [b_] | complex.cpp:52:18:52:18 | call to b | +| complex.cpp:62:12:62:12 | setA output argument [a_] | complex.cpp:40:17:40:17 | *b [a_] | | complex.cpp:62:19:62:28 | call to user_input | complex.cpp:62:12:62:12 | setA output argument [a_] | -| complex.cpp:63:12:63:12 | setB output argument [b_] | complex.cpp:71:7:71:8 | Argument 0 indirection [b_] | +| complex.cpp:63:12:63:12 | setB output argument [b_] | complex.cpp:40:17:40:17 | *b [b_] | | complex.cpp:63:19:63:28 | call to user_input | complex.cpp:63:12:63:12 | setB output argument [b_] | -| complex.cpp:64:12:64:12 | setA output argument [a_] | complex.cpp:65:12:65:12 | Argument -1 indirection [a_] | -| complex.cpp:64:12:64:12 | setA output argument [a_] | complex.cpp:74:7:74:8 | Argument 0 indirection [a_] | +| complex.cpp:64:12:64:12 | setA output argument [a_] | complex.cpp:40:17:40:17 | *b [a_] | +| complex.cpp:64:12:64:12 | setA output argument [a_] | complex.cpp:65:12:65:12 | setB output argument [a_] | | complex.cpp:64:19:64:28 | call to user_input | complex.cpp:64:12:64:12 | setA output argument [a_] | -| complex.cpp:65:12:65:12 | Argument -1 indirection [a_] | complex.cpp:65:12:65:12 | setB output argument [a_] | -| complex.cpp:65:12:65:12 | setB output argument [a_] | complex.cpp:74:7:74:8 | Argument 0 indirection [a_] | -| complex.cpp:65:12:65:12 | setB output argument [b_] | complex.cpp:74:7:74:8 | Argument 0 indirection [b_] | +| complex.cpp:65:12:65:12 | setB output argument [a_] | complex.cpp:40:17:40:17 | *b [a_] | +| complex.cpp:65:12:65:12 | setB output argument [b_] | complex.cpp:40:17:40:17 | *b [b_] | | complex.cpp:65:19:65:28 | call to user_input | complex.cpp:65:12:65:12 | setB output argument [b_] | -| complex.cpp:68:7:68:8 | Argument 0 indirection [a_] | complex.cpp:40:17:40:17 | *b [a_] | -| complex.cpp:71:7:71:8 | Argument 0 indirection [b_] | complex.cpp:40:17:40:17 | *b [b_] | -| complex.cpp:74:7:74:8 | Argument 0 indirection [a_] | complex.cpp:40:17:40:17 | *b [a_] | -| complex.cpp:74:7:74:8 | Argument 0 indirection [b_] | complex.cpp:40:17:40:17 | *b [b_] | -| constructors.cpp:26:15:26:15 | *f [a_] | constructors.cpp:28:10:28:10 | Argument -1 indirection [a_] | -| constructors.cpp:26:15:26:15 | *f [b_] | constructors.cpp:28:10:28:10 | Argument -1 indirection [b_] | -| constructors.cpp:26:15:26:15 | *f [b_] | constructors.cpp:29:10:29:10 | Argument -1 indirection [b_] | -| constructors.cpp:28:10:28:10 | Argument -1 indirection [a_] | constructors.cpp:28:12:28:12 | call to a | -| constructors.cpp:28:10:28:10 | Argument -1 indirection [b_] | constructors.cpp:28:10:28:10 | a output argument [b_] | -| constructors.cpp:28:10:28:10 | a output argument [b_] | constructors.cpp:29:10:29:10 | Argument -1 indirection [b_] | -| constructors.cpp:29:10:29:10 | Argument -1 indirection [b_] | constructors.cpp:29:12:29:12 | call to b | +| constructors.cpp:26:15:26:15 | *f [a_] | constructors.cpp:28:12:28:12 | call to a | +| constructors.cpp:26:15:26:15 | *f [b_] | constructors.cpp:28:10:28:10 | a output argument [b_] | +| constructors.cpp:26:15:26:15 | *f [b_] | constructors.cpp:29:12:29:12 | call to b | +| constructors.cpp:28:10:28:10 | a output argument [b_] | constructors.cpp:29:12:29:12 | call to b | | constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:34:11:34:26 | Foo output argument [a_] | -| constructors.cpp:34:11:34:26 | Foo output argument [a_] | constructors.cpp:40:9:40:9 | Argument 0 indirection [a_] | -| constructors.cpp:35:11:35:26 | Foo output argument [b_] | constructors.cpp:43:9:43:9 | Argument 0 indirection [b_] | +| constructors.cpp:34:11:34:26 | Foo output argument [a_] | constructors.cpp:26:15:26:15 | *f [a_] | +| constructors.cpp:35:11:35:26 | Foo output argument [b_] | constructors.cpp:26:15:26:15 | *f [b_] | | constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:35:11:35:26 | Foo output argument [b_] | | constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:36:11:36:37 | Foo output argument [a_] | -| constructors.cpp:36:11:36:37 | Foo output argument [a_] | constructors.cpp:46:9:46:9 | Argument 0 indirection [a_] | -| constructors.cpp:36:11:36:37 | Foo output argument [b_] | constructors.cpp:46:9:46:9 | Argument 0 indirection [b_] | +| constructors.cpp:36:11:36:37 | Foo output argument [a_] | constructors.cpp:26:15:26:15 | *f [a_] | +| constructors.cpp:36:11:36:37 | Foo output argument [b_] | constructors.cpp:26:15:26:15 | *f [b_] | | constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:36:11:36:37 | Foo output argument [b_] | -| constructors.cpp:40:9:40:9 | Argument 0 indirection [a_] | constructors.cpp:26:15:26:15 | *f [a_] | -| constructors.cpp:43:9:43:9 | Argument 0 indirection [b_] | constructors.cpp:26:15:26:15 | *f [b_] | -| constructors.cpp:46:9:46:9 | Argument 0 indirection [a_] | constructors.cpp:26:15:26:15 | *f [a_] | -| constructors.cpp:46:9:46:9 | Argument 0 indirection [b_] | constructors.cpp:26:15:26:15 | *f [b_] | -| simple.cpp:26:15:26:15 | *f [a_] | simple.cpp:28:10:28:10 | Argument -1 indirection [a_] | -| simple.cpp:26:15:26:15 | *f [b_] | simple.cpp:28:10:28:10 | Argument -1 indirection [b_] | -| simple.cpp:26:15:26:15 | *f [b_] | simple.cpp:29:10:29:10 | Argument -1 indirection [b_] | -| simple.cpp:28:10:28:10 | Argument -1 indirection [a_] | simple.cpp:28:12:28:12 | call to a | -| simple.cpp:28:10:28:10 | Argument -1 indirection [b_] | simple.cpp:28:10:28:10 | a output argument [b_] | -| simple.cpp:28:10:28:10 | a output argument [b_] | simple.cpp:29:10:29:10 | Argument -1 indirection [b_] | -| simple.cpp:29:10:29:10 | Argument -1 indirection [b_] | simple.cpp:29:12:29:12 | call to b | -| simple.cpp:39:5:39:5 | setA output argument [a_] | simple.cpp:45:9:45:9 | Argument 0 indirection [a_] | +| simple.cpp:26:15:26:15 | *f [a_] | simple.cpp:28:12:28:12 | call to a | +| simple.cpp:26:15:26:15 | *f [b_] | simple.cpp:28:10:28:10 | a output argument [b_] | +| simple.cpp:26:15:26:15 | *f [b_] | simple.cpp:29:12:29:12 | call to b | +| simple.cpp:28:10:28:10 | a output argument [b_] | simple.cpp:29:12:29:12 | call to b | +| simple.cpp:39:5:39:5 | setA output argument [a_] | simple.cpp:26:15:26:15 | *f [a_] | | simple.cpp:39:12:39:21 | call to user_input | simple.cpp:39:5:39:5 | setA output argument [a_] | -| simple.cpp:40:5:40:5 | setB output argument [b_] | simple.cpp:48:9:48:9 | Argument 0 indirection [b_] | +| simple.cpp:40:5:40:5 | setB output argument [b_] | simple.cpp:26:15:26:15 | *f [b_] | | simple.cpp:40:12:40:21 | call to user_input | simple.cpp:40:5:40:5 | setB output argument [b_] | -| simple.cpp:41:5:41:5 | setA output argument [a_] | simple.cpp:42:5:42:5 | Argument -1 indirection [a_] | -| simple.cpp:41:5:41:5 | setA output argument [a_] | simple.cpp:51:9:51:9 | Argument 0 indirection [a_] | +| simple.cpp:41:5:41:5 | setA output argument [a_] | simple.cpp:26:15:26:15 | *f [a_] | +| simple.cpp:41:5:41:5 | setA output argument [a_] | simple.cpp:42:5:42:5 | setB output argument [a_] | | simple.cpp:41:12:41:21 | call to user_input | simple.cpp:41:5:41:5 | setA output argument [a_] | -| simple.cpp:42:5:42:5 | Argument -1 indirection [a_] | simple.cpp:42:5:42:5 | setB output argument [a_] | -| simple.cpp:42:5:42:5 | setB output argument [a_] | simple.cpp:51:9:51:9 | Argument 0 indirection [a_] | -| simple.cpp:42:5:42:5 | setB output argument [b_] | simple.cpp:51:9:51:9 | Argument 0 indirection [b_] | +| simple.cpp:42:5:42:5 | setB output argument [a_] | simple.cpp:26:15:26:15 | *f [a_] | +| simple.cpp:42:5:42:5 | setB output argument [b_] | simple.cpp:26:15:26:15 | *f [b_] | | simple.cpp:42:12:42:21 | call to user_input | simple.cpp:42:5:42:5 | setB output argument [b_] | -| simple.cpp:45:9:45:9 | Argument 0 indirection [a_] | simple.cpp:26:15:26:15 | *f [a_] | -| simple.cpp:48:9:48:9 | Argument 0 indirection [b_] | simple.cpp:26:15:26:15 | *f [b_] | -| simple.cpp:51:9:51:9 | Argument 0 indirection [a_] | simple.cpp:26:15:26:15 | *f [a_] | -| simple.cpp:51:9:51:9 | Argument 0 indirection [b_] | simple.cpp:26:15:26:15 | *f [b_] | | simple.cpp:65:5:65:22 | Store [i] | simple.cpp:66:12:66:12 | Store [i] | | simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:5:65:22 | Store [i] | | simple.cpp:66:12:66:12 | Store [i] | simple.cpp:67:13:67:13 | i | -| simple.cpp:83:9:83:28 | Chi [f1] | simple.cpp:84:14:84:20 | Argument -1 indirection [f1] | +| simple.cpp:83:9:83:28 | Chi [f1] | simple.cpp:84:14:84:20 | call to getf2f1 | | simple.cpp:83:9:83:28 | Store | simple.cpp:83:9:83:28 | Chi [f1] | | simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | Store | -| simple.cpp:84:14:84:20 | Argument -1 indirection [f1] | simple.cpp:84:14:84:20 | call to getf2f1 | | simple.cpp:92:5:92:22 | Store [i] | simple.cpp:93:20:93:20 | Store [i] | | simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:5:92:22 | Store [i] | | simple.cpp:93:20:93:20 | Store [i] | simple.cpp:94:13:94:13 | i | | struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:12:15:12 | a | -| struct_init.c:20:20:20:29 | Chi [a] | struct_init.c:24:10:24:12 | Argument 0 indirection [a] | +| struct_init.c:20:20:20:29 | Chi [a] | struct_init.c:14:24:14:25 | *ab [a] | | struct_init.c:20:20:20:29 | Store | struct_init.c:20:20:20:29 | Chi [a] | | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:20:20:29 | Store | | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a | -| struct_init.c:24:10:24:12 | Argument 0 indirection [a] | struct_init.c:14:24:14:25 | *ab [a] | -| struct_init.c:27:7:27:16 | Chi [a] | struct_init.c:36:10:36:24 | Argument 0 indirection [a] | +| struct_init.c:27:7:27:16 | Chi [a] | struct_init.c:14:24:14:25 | *ab [a] | | struct_init.c:27:7:27:16 | Store | struct_init.c:27:7:27:16 | Chi [a] | | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:7:27:16 | Store | | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a | -| struct_init.c:36:10:36:24 | Argument 0 indirection [a] | struct_init.c:14:24:14:25 | *ab [a] | nodes | A.cpp:55:5:55:5 | set output argument [c] | semmle.label | set output argument [c] | | A.cpp:55:12:55:19 | (C *)... | semmle.label | (C *)... | | A.cpp:55:12:55:19 | new | semmle.label | new | -| A.cpp:56:10:56:10 | Argument -1 indirection [c] | semmle.label | Argument -1 indirection [c] | | A.cpp:56:13:56:15 | call to get | semmle.label | call to get | -| A.cpp:57:10:57:25 | Argument -1 indirection [c] | semmle.label | Argument -1 indirection [c] | | A.cpp:57:11:57:24 | B output argument [c] | semmle.label | B output argument [c] | | A.cpp:57:17:57:23 | new | semmle.label | new | | A.cpp:57:28:57:30 | call to get | semmle.label | call to get | | A.cpp:98:12:98:18 | new | semmle.label | new | | A.cpp:100:5:100:13 | Chi [a] | semmle.label | Chi [a] | | A.cpp:100:5:100:13 | Store | semmle.label | Store | -| A.cpp:101:8:101:9 | Argument 0 indirection [a] | semmle.label | Argument 0 indirection [a] | | A.cpp:103:14:103:14 | *c [a] | semmle.label | *c [a] | | A.cpp:107:16:107:16 | a | semmle.label | a | | A.cpp:126:5:126:5 | Chi [c] | semmle.label | Chi [c] | @@ -272,8 +234,6 @@ nodes | A.cpp:154:13:154:13 | c | semmle.label | c | | C.cpp:18:12:18:18 | C output argument [s1] | semmle.label | C output argument [s1] | | C.cpp:18:12:18:18 | C output argument [s3] | semmle.label | C output argument [s3] | -| C.cpp:19:5:19:5 | Argument -1 indirection [s1] | semmle.label | Argument -1 indirection [s1] | -| C.cpp:19:5:19:5 | Argument -1 indirection [s3] | semmle.label | Argument -1 indirection [s3] | | C.cpp:22:12:22:21 | Chi [s1] | semmle.label | Chi [s1] | | C.cpp:22:12:22:21 | Store | semmle.label | Store | | C.cpp:22:12:22:21 | new | semmle.label | new | @@ -361,20 +321,16 @@ nodes | arrays.cpp:37:24:37:27 | data | semmle.label | data | | by_reference.cpp:50:3:50:3 | setDirectly output argument [a] | semmle.label | setDirectly output argument [a] | | by_reference.cpp:50:17:50:26 | call to user_input | semmle.label | call to user_input | -| by_reference.cpp:51:8:51:8 | Argument -1 indirection [a] | semmle.label | Argument -1 indirection [a] | | by_reference.cpp:51:10:51:20 | call to getDirectly | semmle.label | call to getDirectly | | by_reference.cpp:56:3:56:3 | setIndirectly output argument [a] | semmle.label | setIndirectly output argument [a] | | by_reference.cpp:56:19:56:28 | call to user_input | semmle.label | call to user_input | -| by_reference.cpp:57:8:57:8 | Argument -1 indirection [a] | semmle.label | Argument -1 indirection [a] | | by_reference.cpp:57:10:57:22 | call to getIndirectly | semmle.label | call to getIndirectly | | by_reference.cpp:62:3:62:3 | setThroughNonMember output argument [a] | semmle.label | setThroughNonMember output argument [a] | | by_reference.cpp:62:25:62:34 | call to user_input | semmle.label | call to user_input | -| by_reference.cpp:63:8:63:8 | Argument -1 indirection [a] | semmle.label | Argument -1 indirection [a] | | by_reference.cpp:63:10:63:28 | call to getThroughNonMember | semmle.label | call to getThroughNonMember | | by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] | semmle.label | nonMemberSetA output argument [a] | | by_reference.cpp:68:21:68:30 | call to user_input | semmle.label | call to user_input | | by_reference.cpp:69:8:69:20 | call to nonMemberGetA | semmle.label | call to nonMemberGetA | -| by_reference.cpp:69:22:69:23 | Argument 0 indirection [a] | semmle.label | Argument 0 indirection [a] | | by_reference.cpp:84:3:84:25 | Chi [a] | semmle.label | Chi [a] | | by_reference.cpp:84:3:84:25 | Store | semmle.label | Store | | by_reference.cpp:84:14:84:23 | call to user_input | semmle.label | call to user_input | @@ -417,11 +373,8 @@ nodes | by_reference.cpp:136:16:136:16 | a | semmle.label | a | | complex.cpp:40:17:40:17 | *b [a_] | semmle.label | *b [a_] | | complex.cpp:40:17:40:17 | *b [b_] | semmle.label | *b [b_] | -| complex.cpp:51:16:51:16 | Argument -1 indirection [a_] | semmle.label | Argument -1 indirection [a_] | -| complex.cpp:51:16:51:16 | Argument -1 indirection [b_] | semmle.label | Argument -1 indirection [b_] | | complex.cpp:51:16:51:16 | a output argument [b_] | semmle.label | a output argument [b_] | | complex.cpp:51:18:51:18 | call to a | semmle.label | call to a | -| complex.cpp:52:16:52:16 | Argument -1 indirection [b_] | semmle.label | Argument -1 indirection [b_] | | complex.cpp:52:18:52:18 | call to b | semmle.label | call to b | | complex.cpp:62:12:62:12 | setA output argument [a_] | semmle.label | setA output argument [a_] | | complex.cpp:62:19:62:28 | call to user_input | semmle.label | call to user_input | @@ -429,21 +382,13 @@ nodes | complex.cpp:63:19:63:28 | call to user_input | semmle.label | call to user_input | | complex.cpp:64:12:64:12 | setA output argument [a_] | semmle.label | setA output argument [a_] | | complex.cpp:64:19:64:28 | call to user_input | semmle.label | call to user_input | -| complex.cpp:65:12:65:12 | Argument -1 indirection [a_] | semmle.label | Argument -1 indirection [a_] | | complex.cpp:65:12:65:12 | setB output argument [a_] | semmle.label | setB output argument [a_] | | complex.cpp:65:12:65:12 | setB output argument [b_] | semmle.label | setB output argument [b_] | | complex.cpp:65:19:65:28 | call to user_input | semmle.label | call to user_input | -| complex.cpp:68:7:68:8 | Argument 0 indirection [a_] | semmle.label | Argument 0 indirection [a_] | -| complex.cpp:71:7:71:8 | Argument 0 indirection [b_] | semmle.label | Argument 0 indirection [b_] | -| complex.cpp:74:7:74:8 | Argument 0 indirection [a_] | semmle.label | Argument 0 indirection [a_] | -| complex.cpp:74:7:74:8 | Argument 0 indirection [b_] | semmle.label | Argument 0 indirection [b_] | | constructors.cpp:26:15:26:15 | *f [a_] | semmle.label | *f [a_] | | constructors.cpp:26:15:26:15 | *f [b_] | semmle.label | *f [b_] | -| constructors.cpp:28:10:28:10 | Argument -1 indirection [a_] | semmle.label | Argument -1 indirection [a_] | -| constructors.cpp:28:10:28:10 | Argument -1 indirection [b_] | semmle.label | Argument -1 indirection [b_] | | constructors.cpp:28:10:28:10 | a output argument [b_] | semmle.label | a output argument [b_] | | constructors.cpp:28:12:28:12 | call to a | semmle.label | call to a | -| constructors.cpp:29:10:29:10 | Argument -1 indirection [b_] | semmle.label | Argument -1 indirection [b_] | | constructors.cpp:29:12:29:12 | call to b | semmle.label | call to b | | constructors.cpp:34:11:34:20 | call to user_input | semmle.label | call to user_input | | constructors.cpp:34:11:34:26 | Foo output argument [a_] | semmle.label | Foo output argument [a_] | @@ -453,17 +398,10 @@ nodes | constructors.cpp:36:11:36:37 | Foo output argument [a_] | semmle.label | Foo output argument [a_] | | constructors.cpp:36:11:36:37 | Foo output argument [b_] | semmle.label | Foo output argument [b_] | | constructors.cpp:36:25:36:34 | call to user_input | semmle.label | call to user_input | -| constructors.cpp:40:9:40:9 | Argument 0 indirection [a_] | semmle.label | Argument 0 indirection [a_] | -| constructors.cpp:43:9:43:9 | Argument 0 indirection [b_] | semmle.label | Argument 0 indirection [b_] | -| constructors.cpp:46:9:46:9 | Argument 0 indirection [a_] | semmle.label | Argument 0 indirection [a_] | -| constructors.cpp:46:9:46:9 | Argument 0 indirection [b_] | semmle.label | Argument 0 indirection [b_] | | simple.cpp:26:15:26:15 | *f [a_] | semmle.label | *f [a_] | | simple.cpp:26:15:26:15 | *f [b_] | semmle.label | *f [b_] | -| simple.cpp:28:10:28:10 | Argument -1 indirection [a_] | semmle.label | Argument -1 indirection [a_] | -| simple.cpp:28:10:28:10 | Argument -1 indirection [b_] | semmle.label | Argument -1 indirection [b_] | | simple.cpp:28:10:28:10 | a output argument [b_] | semmle.label | a output argument [b_] | | simple.cpp:28:12:28:12 | call to a | semmle.label | call to a | -| simple.cpp:29:10:29:10 | Argument -1 indirection [b_] | semmle.label | Argument -1 indirection [b_] | | simple.cpp:29:12:29:12 | call to b | semmle.label | call to b | | simple.cpp:39:5:39:5 | setA output argument [a_] | semmle.label | setA output argument [a_] | | simple.cpp:39:12:39:21 | call to user_input | semmle.label | call to user_input | @@ -471,14 +409,9 @@ nodes | simple.cpp:40:12:40:21 | call to user_input | semmle.label | call to user_input | | simple.cpp:41:5:41:5 | setA output argument [a_] | semmle.label | setA output argument [a_] | | simple.cpp:41:12:41:21 | call to user_input | semmle.label | call to user_input | -| simple.cpp:42:5:42:5 | Argument -1 indirection [a_] | semmle.label | Argument -1 indirection [a_] | | simple.cpp:42:5:42:5 | setB output argument [a_] | semmle.label | setB output argument [a_] | | simple.cpp:42:5:42:5 | setB output argument [b_] | semmle.label | setB output argument [b_] | | simple.cpp:42:12:42:21 | call to user_input | semmle.label | call to user_input | -| simple.cpp:45:9:45:9 | Argument 0 indirection [a_] | semmle.label | Argument 0 indirection [a_] | -| simple.cpp:48:9:48:9 | Argument 0 indirection [b_] | semmle.label | Argument 0 indirection [b_] | -| simple.cpp:51:9:51:9 | Argument 0 indirection [a_] | semmle.label | Argument 0 indirection [a_] | -| simple.cpp:51:9:51:9 | Argument 0 indirection [b_] | semmle.label | Argument 0 indirection [b_] | | simple.cpp:65:5:65:22 | Store [i] | semmle.label | Store [i] | | simple.cpp:65:11:65:20 | call to user_input | semmle.label | call to user_input | | simple.cpp:66:12:66:12 | Store [i] | semmle.label | Store [i] | @@ -486,7 +419,6 @@ nodes | simple.cpp:83:9:83:28 | Chi [f1] | semmle.label | Chi [f1] | | simple.cpp:83:9:83:28 | Store | semmle.label | Store | | simple.cpp:83:17:83:26 | call to user_input | semmle.label | call to user_input | -| simple.cpp:84:14:84:20 | Argument -1 indirection [f1] | semmle.label | Argument -1 indirection [f1] | | simple.cpp:84:14:84:20 | call to getf2f1 | semmle.label | call to getf2f1 | | simple.cpp:92:5:92:22 | Store [i] | semmle.label | Store [i] | | simple.cpp:92:11:92:20 | call to user_input | semmle.label | call to user_input | @@ -498,12 +430,10 @@ nodes | struct_init.c:20:20:20:29 | Store | semmle.label | Store | | struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input | | struct_init.c:22:11:22:11 | a | semmle.label | a | -| struct_init.c:24:10:24:12 | Argument 0 indirection [a] | semmle.label | Argument 0 indirection [a] | | struct_init.c:27:7:27:16 | Chi [a] | semmle.label | Chi [a] | | struct_init.c:27:7:27:16 | Store | semmle.label | Store | | struct_init.c:27:7:27:16 | call to user_input | semmle.label | call to user_input | | struct_init.c:31:23:31:23 | a | semmle.label | a | -| struct_init.c:36:10:36:24 | Argument 0 indirection [a] | semmle.label | Argument 0 indirection [a] | #select | A.cpp:56:13:56:15 | call to get | A.cpp:55:12:55:19 | (C *)... | A.cpp:56:13:56:15 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | (C *)... | (C *)... | | A.cpp:56:13:56:15 | call to get | A.cpp:55:12:55:19 | new | A.cpp:56:13:56:15 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | new | new | From eb67986916e55bd253c7a9fe995bdf7e3240a593 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 2 Oct 2020 14:11:07 +0200 Subject: [PATCH 180/411] Python: Exlucde only command injection sinks in os and subprocess --- .../CWE-078/CommandInjection.ql | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/python/ql/src/experimental/Security-new-dataflow/CWE-078/CommandInjection.ql b/python/ql/src/experimental/Security-new-dataflow/CWE-078/CommandInjection.ql index 49aa1cd1885..b1672ad995a 100755 --- a/python/ql/src/experimental/Security-new-dataflow/CWE-078/CommandInjection.ql +++ b/python/ql/src/experimental/Security-new-dataflow/CWE-078/CommandInjection.ql @@ -35,25 +35,26 @@ class CommandInjectionConfiguration extends TaintTracking::Configuration { // proc = subprocess.Popen(cmd, ...) // ``` // any time we would report flow to the `os.popen` sink, we can ALSO report the flow - // from the `cmd` parameter to the `subprocess.Popen` sink -- obviously we don't want - // that. + // from the `cmd` parameter to the `subprocess.Popen` sink -- obviously we don't + // want that. // // However, simply removing taint edges out of a sink is not a good enough solution, - // since we would only flag one of the `os.system` calls in the following example due - // to use-use flow + // since we would only flag one of the `os.system` calls in the following example + // due to use-use flow // ```py // os.system(cmd) // os.system(cmd) // ``` // - // Best solution I could come up with is to exclude all sinks inside the standard - // library -- this does have a downside: If we have overlooked a function in the - // standard library that internally runs a command, we no longer give an alert :| + // Best solution I could come up with is to exclude all sinks inside the `os` and + // `subprocess` modules. This does have a downside: If we have overlooked a function + // in any of these, that internally runs a command, we no longer give an alert :| // - // This does not only affect `os.popen`, but also the helper functions in `subprocess`. See + // This does not only affect `os.popen`, but also the helper functions in + // `subprocess`. See: // https://github.com/python/cpython/blob/fa7ce080175f65d678a7d5756c94f82887fc9803/Lib/os.py#L974 // https://github.com/python/cpython/blob/fa7ce080175f65d678a7d5756c94f82887fc9803/Lib/subprocess.py#L341 - not sink.getLocation().getFile().inStdlib() + not sink.getScope().getEnclosingModule().getName() in ["os", "subprocess"] } } From e5b9ac8d9c38af3d214b52943bc1375eea7a49f2 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 2 Oct 2020 14:12:41 +0200 Subject: [PATCH 181/411] Python: Use getCommand as tag in ConceptsTest --- .../stdlib/SystemCommandExecution.py | 104 +++++++++--------- .../test/experimental/meta/ConceptsTest.qll | 4 +- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py b/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py index 8d6b1211614..ad4223a8c4b 100644 --- a/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py +++ b/python/ql/test/experimental/library-tests/frameworks/stdlib/SystemCommandExecution.py @@ -13,8 +13,8 @@ import os # can't use a string literal with spaces in the tags of an InlineExpectationsTest, so using variables :| -os.popen("cmd1; cmd2") # $SystemCommandExecution_getCommand="cmd1; cmd2" -os.system("cmd1; cmd2") # $SystemCommandExecution_getCommand="cmd1; cmd2" +os.popen("cmd1; cmd2") # $getCommand="cmd1; cmd2" +os.system("cmd1; cmd2") # $getCommand="cmd1; cmd2" def os_members(): @@ -24,8 +24,8 @@ def os_members(): # :| from os import popen, system - popen("cmd1; cmd2") # $SystemCommandExecution_getCommand="cmd1; cmd2" - system("cmd1; cmd2") # $SystemCommandExecution_getCommand="cmd1; cmd2" + popen("cmd1; cmd2") # $getCommand="cmd1; cmd2" + system("cmd1; cmd2") # $getCommand="cmd1; cmd2" ######################################## @@ -36,92 +36,92 @@ def os_members(): # clever in our analysis that discards that code, I used `if UNKNOWN` instead if UNKNOWN: env = {"FOO": "foo"} - os.execl("executable", "", "arg0") # $SystemCommandExecution_getCommand="executable" - os.execle("executable", "", "arg0", env) # $SystemCommandExecution_getCommand="executable" - os.execlp("executable", "", "arg0") # $SystemCommandExecution_getCommand="executable" - os.execlpe("executable", "", "arg0", env) # $SystemCommandExecution_getCommand="executable" - os.execv("executable", ["", "arg0"]) # $SystemCommandExecution_getCommand="executable" - os.execve("executable", ["", "arg0"], env) # $SystemCommandExecution_getCommand="executable" - os.execvp("executable", ["", "arg0"]) # $SystemCommandExecution_getCommand="executable" - os.execvpe("executable", ["", "arg0"], env) # $SystemCommandExecution_getCommand="executable" + os.execl("executable", "", "arg0") # $getCommand="executable" + os.execle("executable", "", "arg0", env) # $getCommand="executable" + os.execlp("executable", "", "arg0") # $getCommand="executable" + os.execlpe("executable", "", "arg0", env) # $getCommand="executable" + os.execv("executable", ["", "arg0"]) # $getCommand="executable" + os.execve("executable", ["", "arg0"], env) # $getCommand="executable" + os.execvp("executable", ["", "arg0"]) # $getCommand="executable" + os.execvpe("executable", ["", "arg0"], env) # $getCommand="executable" ######################################## # https://docs.python.org/3.8/library/os.html#os.spawnl env = {"FOO": "foo"} -os.spawnl(os.P_WAIT, "executable", "", "arg0") # $SystemCommandExecution_getCommand="executable" -os.spawnle(os.P_WAIT, "executable", "", "arg0", env) # $SystemCommandExecution_getCommand="executable" -os.spawnlp(os.P_WAIT, "executable", "", "arg0") # $SystemCommandExecution_getCommand="executable" -os.spawnlpe(os.P_WAIT, "executable", "", "arg0", env) # $SystemCommandExecution_getCommand="executable" -os.spawnv(os.P_WAIT, "executable", ["", "arg0"]) # $SystemCommandExecution_getCommand="executable" -os.spawnve(os.P_WAIT, "executable", ["", "arg0"], env) # $SystemCommandExecution_getCommand="executable" -os.spawnvp(os.P_WAIT, "executable", ["", "arg0"]) # $SystemCommandExecution_getCommand="executable" -os.spawnvpe(os.P_WAIT, "executable", ["", "arg0"], env) # $SystemCommandExecution_getCommand="executable" +os.spawnl(os.P_WAIT, "executable", "", "arg0") # $getCommand="executable" +os.spawnle(os.P_WAIT, "executable", "", "arg0", env) # $getCommand="executable" +os.spawnlp(os.P_WAIT, "executable", "", "arg0") # $getCommand="executable" +os.spawnlpe(os.P_WAIT, "executable", "", "arg0", env) # $getCommand="executable" +os.spawnv(os.P_WAIT, "executable", ["", "arg0"]) # $getCommand="executable" +os.spawnve(os.P_WAIT, "executable", ["", "arg0"], env) # $getCommand="executable" +os.spawnvp(os.P_WAIT, "executable", ["", "arg0"]) # $getCommand="executable" +os.spawnvpe(os.P_WAIT, "executable", ["", "arg0"], env) # $getCommand="executable" # Added in Python 3.8 -os.posix_spawn("executable", ["", "arg0"], env) # $SystemCommandExecution_getCommand="executable" -os.posix_spawnp("executable", ["", "arg0"], env) # $SystemCommandExecution_getCommand="executable" +os.posix_spawn("executable", ["", "arg0"], env) # $getCommand="executable" +os.posix_spawnp("executable", ["", "arg0"], env) # $getCommand="executable" ######################################## import subprocess -subprocess.Popen("cmd1; cmd2", shell=True) # $SystemCommandExecution_getCommand="cmd1; cmd2" -subprocess.Popen("cmd1; cmd2", shell="truthy string") # $SystemCommandExecution_getCommand="cmd1; cmd2" -subprocess.Popen(["cmd1; cmd2", "shell-arg"], shell=True) # $SystemCommandExecution_getCommand="cmd1; cmd2" -subprocess.Popen("cmd1; cmd2", shell=True, executable="/bin/bash") # $SystemCommandExecution_getCommand="cmd1; cmd2" $SystemCommandExecution_getCommand="/bin/bash" +subprocess.Popen("cmd1; cmd2", shell=True) # $getCommand="cmd1; cmd2" +subprocess.Popen("cmd1; cmd2", shell="truthy string") # $getCommand="cmd1; cmd2" +subprocess.Popen(["cmd1; cmd2", "shell-arg"], shell=True) # $getCommand="cmd1; cmd2" +subprocess.Popen("cmd1; cmd2", shell=True, executable="/bin/bash") # $getCommand="cmd1; cmd2" $getCommand="/bin/bash" -subprocess.Popen("executable") # $SystemCommandExecution_getCommand="executable" -subprocess.Popen(["executable", "arg0"]) # $SystemCommandExecution_getCommand="executable" -subprocess.Popen("", executable="executable") # $SystemCommandExecution_getCommand="executable" -subprocess.Popen(["", "arg0"], executable="executable") # $SystemCommandExecution_getCommand="executable" +subprocess.Popen("executable") # $getCommand="executable" +subprocess.Popen(["executable", "arg0"]) # $getCommand="executable" +subprocess.Popen("", executable="executable") # $getCommand="executable" +subprocess.Popen(["", "arg0"], executable="executable") # $getCommand="executable" # call/check_call/check_output/run all work like Popen from a command execution point of view -subprocess.call(["executable", "arg0"]) # $SystemCommandExecution_getCommand="executable" -subprocess.check_call(["executable", "arg0"]) # $SystemCommandExecution_getCommand="executable" -subprocess.check_output(["executable", "arg0"]) # $SystemCommandExecution_getCommand="executable" -subprocess.run(["executable", "arg0"]) # $SystemCommandExecution_getCommand="executable" +subprocess.call(["executable", "arg0"]) # $getCommand="executable" +subprocess.check_call(["executable", "arg0"]) # $getCommand="executable" +subprocess.check_output(["executable", "arg0"]) # $getCommand="executable" +subprocess.run(["executable", "arg0"]) # $getCommand="executable" ######################################## # actively using known shell as the executable -subprocess.Popen(["/bin/sh", "-c", "vuln"]) # $SystemCommandExecution_getCommand="/bin/sh" $f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["/bin/bash", "-c", "vuln"]) # $SystemCommandExecution_getCommand="/bin/bash" $f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["/bin/dash", "-c", "vuln"]) # $SystemCommandExecution_getCommand="/bin/dash" $f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["/bin/zsh", "-c", "vuln"]) # $SystemCommandExecution_getCommand="/bin/zsh" $f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["/bin/sh", "-c", "vuln"]) # $getCommand="/bin/sh" $f-:getCommand="vuln" +subprocess.Popen(["/bin/bash", "-c", "vuln"]) # $getCommand="/bin/bash" $f-:getCommand="vuln" +subprocess.Popen(["/bin/dash", "-c", "vuln"]) # $getCommand="/bin/dash" $f-:getCommand="vuln" +subprocess.Popen(["/bin/zsh", "-c", "vuln"]) # $getCommand="/bin/zsh" $f-:getCommand="vuln" -subprocess.Popen(["sh", "-c", "vuln"]) # $SystemCommandExecution_getCommand="sh" $f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["bash", "-c", "vuln"]) # $SystemCommandExecution_getCommand="bash" $f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["dash", "-c", "vuln"]) # $SystemCommandExecution_getCommand="dash" $f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["zsh", "-c", "vuln"]) # $SystemCommandExecution_getCommand="zsh" $f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["sh", "-c", "vuln"]) # $getCommand="sh" $f-:getCommand="vuln" +subprocess.Popen(["bash", "-c", "vuln"]) # $getCommand="bash" $f-:getCommand="vuln" +subprocess.Popen(["dash", "-c", "vuln"]) # $getCommand="dash" $f-:getCommand="vuln" +subprocess.Popen(["zsh", "-c", "vuln"]) # $getCommand="zsh" $f-:getCommand="vuln" # Check that we don't consider ANY argument a command injection sink -subprocess.Popen(["sh", "/bin/python"]) # $SystemCommandExecution_getCommand="sh" +subprocess.Popen(["sh", "/bin/python"]) # $getCommand="sh" -subprocess.Popen(["cmd.exe", "/c", "vuln"]) # $SystemCommandExecution_getCommand="cmd.exe" $f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["cmd.exe", "/C", "vuln"]) # $SystemCommandExecution_getCommand="cmd.exe" $f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["cmd", "/c", "vuln"]) # $SystemCommandExecution_getCommand="cmd" $f-:SystemCommandExecution_getCommand="vuln" -subprocess.Popen(["cmd", "/C", "vuln"]) # $SystemCommandExecution_getCommand="cmd" $f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["cmd.exe", "/c", "vuln"]) # $getCommand="cmd.exe" $f-:getCommand="vuln" +subprocess.Popen(["cmd.exe", "/C", "vuln"]) # $getCommand="cmd.exe" $f-:getCommand="vuln" +subprocess.Popen(["cmd", "/c", "vuln"]) # $getCommand="cmd" $f-:getCommand="vuln" +subprocess.Popen(["cmd", "/C", "vuln"]) # $getCommand="cmd" $f-:getCommand="vuln" -subprocess.Popen(["", "-c", "vuln"], executable="/bin/bash") # $SystemCommandExecution_getCommand="/bin/bash" $f-:SystemCommandExecution_getCommand="vuln" +subprocess.Popen(["", "-c", "vuln"], executable="/bin/bash") # $getCommand="/bin/bash" $f-:getCommand="vuln" if UNKNOWN: - os.execl("/bin/sh", "", "-c", "vuln") # $SystemCommandExecution_getCommand="/bin/sh" $f-:SystemCommandExecution_getCommand="vuln" + os.execl("/bin/sh", "", "-c", "vuln") # $getCommand="/bin/sh" $f-:getCommand="vuln" -os.spawnl(os.P_WAIT, "/bin/sh", "", "-c", "vuln") # $SystemCommandExecution_getCommand="/bin/sh" $f-:SystemCommandExecution_getCommand="vuln" +os.spawnl(os.P_WAIT, "/bin/sh", "", "-c", "vuln") # $getCommand="/bin/sh" $f-:getCommand="vuln" ######################################## # Passing arguments by reference args = ["/bin/sh", "-c", "vuln"] -subprocess.Popen(args) # $SystemCommandExecution_getCommand=args +subprocess.Popen(args) # $getCommand=args args = "" use_shell = False exe = "executable" -subprocess.Popen(args, shell=use_shell, executable=exe) # $f+:SystemCommandExecution_getCommand=args $SystemCommandExecution_getCommand=exe +subprocess.Popen(args, shell=use_shell, executable=exe) # $f+:getCommand=args $getCommand=exe ################################################################################ diff --git a/python/ql/test/experimental/meta/ConceptsTest.qll b/python/ql/test/experimental/meta/ConceptsTest.qll index 258cffc694b..eb798823d50 100644 --- a/python/ql/test/experimental/meta/ConceptsTest.qll +++ b/python/ql/test/experimental/meta/ConceptsTest.qll @@ -19,7 +19,7 @@ string value_from_expr(Expr e) { class SystemCommandExecutionTest extends InlineExpectationsTest { SystemCommandExecutionTest() { this = "SystemCommandExecutionTest" } - override string getARelevantTag() { result = "SystemCommandExecution_getCommand" } + override string getARelevantTag() { result = "getCommand" } override predicate hasActualResult(Location location, string element, string tag, string value) { exists(SystemCommandExecution sce, DataFlow::Node command | @@ -28,7 +28,7 @@ class SystemCommandExecutionTest extends InlineExpectationsTest { location = command.getLocation() and element = command.toString() and value = value_from_expr(command.asExpr()) and - tag = "SystemCommandExecution_getCommand" + tag = "getCommand" ) } } From 17f0ac4b208991ddbf4f04a0fe52b135ee1df043 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 16 Sep 2020 14:19:02 +0200 Subject: [PATCH 182/411] C#: Add more CFG assertion tests --- .../library-tests/controlflow/graph/Assert.cs | 130 ++ .../controlflow/graph/BasicBlock.expected | 70 + .../controlflow/graph/Condition.expected | 113 ++ .../controlflow/graph/Dominance.expected | 1311 +++++++++++++++++ .../graph/EnclosingCallable.expected | 579 ++++++++ .../controlflow/graph/EntryElement.expected | 352 +++++ .../controlflow/graph/ExitElement.expected | 412 ++++++ .../controlflow/graph/NodeGraph.expected | 520 +++++++ .../controlflow/graph/Nodes.expected | 298 ++++ .../controlflow/guards/AbstractValue.expected | 20 +- .../guards/BooleanGuardedExpr.expected | 3 +- .../guards/GuardedControlFlowNode.expected | 9 +- .../controlflow/guards/GuardedExpr.expected | 4 +- .../controlflow/guards/Guards.cs | 7 + .../controlflow/guards/Implications.expected | 27 +- .../controlflow/guards/Splitting.cs | 1 + csharp/ql/test/query-tests/Nullness/Assert.cs | 4 +- .../Nullness/Implications.expected | 12 +- .../query-tests/Nullness/NullMaybe.expected | 6 +- 19 files changed, 3854 insertions(+), 24 deletions(-) create mode 100644 csharp/ql/test/library-tests/controlflow/graph/Assert.cs diff --git a/csharp/ql/test/library-tests/controlflow/graph/Assert.cs b/csharp/ql/test/library-tests/controlflow/graph/Assert.cs new file mode 100644 index 00000000000..3c7ebb08ff1 --- /dev/null +++ b/csharp/ql/test/library-tests/controlflow/graph/Assert.cs @@ -0,0 +1,130 @@ +using System; +using System.Diagnostics; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +class AssertTests +{ + void M1(bool b) + { + string s = b ? null : ""; + Debug.Assert(s != null); + Console.WriteLine(s.Length); + } + + void M2(bool b) + { + string s = b ? null : ""; + Assert.IsNull(s); + Console.WriteLine(s.Length); + } + + void M3(bool b) + { + string s = b ? null : ""; + Assert.IsNotNull(s); + Console.WriteLine(s.Length); + } + + void M4(bool b) + { + string s = b ? null : ""; + Assert.IsTrue(s == null); + Console.WriteLine(s.Length); + } + + void M5(bool b) + { + string s = b ? null : ""; + Assert.IsTrue(s != null); + Console.WriteLine(s.Length); + } + + void M6(bool b) + { + string s = b ? null : ""; + Assert.IsFalse(s != null); + Console.WriteLine(s.Length); + } + + void M7(bool b) + { + string s = b ? null : ""; + Assert.IsFalse(s == null); + Console.WriteLine(s.Length); + } + + void M8(bool b) + { + string s = b ? null : ""; + Assert.IsTrue(s != null && b); + Console.WriteLine(s.Length); + } + + void M9(bool b) + { + string s = b ? null : ""; + Assert.IsFalse(s == null || b); + Console.WriteLine(s.Length); + } + + void M10(bool b) + { + string s = b ? null : ""; + Assert.IsTrue(s == null && b); + Console.WriteLine(s.Length); + } + + void M11(bool b) + { + string s = b ? null : ""; + Assert.IsFalse(s != null || b); + Console.WriteLine(s.Length); + } + + void M12(bool b) + { + string s = b ? null : ""; + Debug.Assert(s != null); + Console.WriteLine(s.Length); + + s = b ? null : ""; + Assert.IsNull(s); + Console.WriteLine(s.Length); + + s = b ? null : ""; + Assert.IsNotNull(s); + Console.WriteLine(s.Length); + + s = b ? null : ""; + Assert.IsTrue(s == null); + Console.WriteLine(s.Length); + + s = b ? null : ""; + Assert.IsTrue(s != null); + Console.WriteLine(s.Length); + + s = b ? null : ""; + Assert.IsFalse(s != null); + Console.WriteLine(s.Length); + + s = b ? null : ""; + Assert.IsFalse(s == null); + Console.WriteLine(s.Length); + + s = b ? null : ""; + Assert.IsTrue(s != null && b); + Console.WriteLine(s.Length); + + s = b ? null : ""; + Assert.IsFalse(s == null || !b); + Console.WriteLine(s.Length); + + s = b ? null : ""; + Assert.IsTrue(s == null && b); + Console.WriteLine(s.Length); + + s = b ? null : ""; + Assert.IsFalse(s != null || !b); + Console.WriteLine(s.Length); + } +} diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index d7ca5bdd073..d5921114b9b 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -15,6 +15,76 @@ | ArrayCreation.cs:5:12:5:13 | enter M2 | ArrayCreation.cs:5:12:5:13 | exit M2 | 5 | | ArrayCreation.cs:7:11:7:12 | enter M3 | ArrayCreation.cs:7:11:7:12 | exit M3 | 6 | | ArrayCreation.cs:9:12:9:13 | enter M4 | ArrayCreation.cs:9:12:9:13 | exit M4 | 10 | +| Assert.cs:7:10:7:11 | enter M1 | Assert.cs:9:20:9:20 | access to parameter b | 5 | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:7:10:7:11 | exit M1 | 11 | +| Assert.cs:9:24:9:27 | null | Assert.cs:9:24:9:27 | null | 1 | +| Assert.cs:9:31:9:32 | "" | Assert.cs:9:31:9:32 | "" | 1 | +| Assert.cs:14:10:14:11 | enter M2 | Assert.cs:16:20:16:20 | access to parameter b | 5 | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:14:10:14:11 | exit M2 | 9 | +| Assert.cs:16:24:16:27 | null | Assert.cs:16:24:16:27 | null | 1 | +| Assert.cs:16:31:16:32 | "" | Assert.cs:16:31:16:32 | "" | 1 | +| Assert.cs:21:10:21:11 | enter M3 | Assert.cs:23:20:23:20 | access to parameter b | 5 | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:21:10:21:11 | exit M3 | 9 | +| Assert.cs:23:24:23:27 | null | Assert.cs:23:24:23:27 | null | 1 | +| Assert.cs:23:31:23:32 | "" | Assert.cs:23:31:23:32 | "" | 1 | +| Assert.cs:28:10:28:11 | enter M4 | Assert.cs:30:20:30:20 | access to parameter b | 5 | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:28:10:28:11 | exit M4 | 11 | +| Assert.cs:30:24:30:27 | null | Assert.cs:30:24:30:27 | null | 1 | +| Assert.cs:30:31:30:32 | "" | Assert.cs:30:31:30:32 | "" | 1 | +| Assert.cs:35:10:35:11 | enter M5 | Assert.cs:37:20:37:20 | access to parameter b | 5 | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:35:10:35:11 | exit M5 | 11 | +| Assert.cs:37:24:37:27 | null | Assert.cs:37:24:37:27 | null | 1 | +| Assert.cs:37:31:37:32 | "" | Assert.cs:37:31:37:32 | "" | 1 | +| Assert.cs:42:10:42:11 | enter M6 | Assert.cs:44:20:44:20 | access to parameter b | 5 | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:42:10:42:11 | exit M6 | 11 | +| Assert.cs:44:24:44:27 | null | Assert.cs:44:24:44:27 | null | 1 | +| Assert.cs:44:31:44:32 | "" | Assert.cs:44:31:44:32 | "" | 1 | +| Assert.cs:49:10:49:11 | enter M7 | Assert.cs:51:20:51:20 | access to parameter b | 5 | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:49:10:49:11 | exit M7 | 11 | +| Assert.cs:51:24:51:27 | null | Assert.cs:51:24:51:27 | null | 1 | +| Assert.cs:51:31:51:32 | "" | Assert.cs:51:31:51:32 | "" | 1 | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:58:20:58:20 | access to parameter b | 5 | +| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:59:23:59:31 | ... != ... | 6 | +| Assert.cs:58:24:58:27 | null | Assert.cs:58:24:58:27 | null | 1 | +| Assert.cs:58:31:58:32 | "" | Assert.cs:58:31:58:32 | "" | 1 | +| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:56:10:56:11 | exit M8 | 6 | +| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:59:36:59:36 | access to parameter b | 1 | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:65:20:65:20 | access to parameter b | 5 | +| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:66:24:66:32 | ... == ... | 6 | +| Assert.cs:65:24:65:27 | null | Assert.cs:65:24:65:27 | null | 1 | +| Assert.cs:65:31:65:32 | "" | Assert.cs:65:31:65:32 | "" | 1 | +| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:63:10:63:11 | exit M9 | 6 | +| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:66:37:66:37 | access to parameter b | 1 | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:72:20:72:20 | access to parameter b | 5 | +| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:73:23:73:31 | ... == ... | 6 | +| Assert.cs:72:24:72:27 | null | Assert.cs:72:24:72:27 | null | 1 | +| Assert.cs:72:31:72:32 | "" | Assert.cs:72:31:72:32 | "" | 1 | +| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:70:10:70:12 | exit M10 | 6 | +| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:73:36:73:36 | access to parameter b | 1 | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:79:20:79:20 | access to parameter b | 5 | +| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:80:24:80:32 | ... != ... | 6 | +| Assert.cs:79:24:79:27 | null | Assert.cs:79:24:79:27 | null | 1 | +| Assert.cs:79:31:79:32 | "" | Assert.cs:79:31:79:32 | "" | 1 | +| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:77:10:77:12 | exit M11 | 6 | +| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:80:37:80:37 | access to parameter b | 1 | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:86:20:86:20 | access to parameter b | 5 | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | 101 | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | 101 | +| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | 15 | +| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | 15 | +| Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | 1 | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | 1 | +| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | 15 | +| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | 15 | +| Assert.cs:119:37:119:38 | [b (line 84): false] !... | Assert.cs:119:38:119:38 | [b (line 84): false] access to parameter b | 2 | +| Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | 2 | +| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:126:24:126:25 | "" | 9 | +| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:126:17:126:20 | null | 9 | +| Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | 1 | +| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | 1 | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:127:24:127:32 | ... != ... | 6 | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:84:10:84:12 | exit M12 | 6 | +| Assert.cs:127:37:127:38 | !... | Assert.cs:127:38:127:38 | access to parameter b | 2 | | Assignments.cs:3:10:3:10 | enter M | Assignments.cs:3:10:3:10 | exit M | 33 | | Assignments.cs:14:18:14:35 | enter (...) => ... | Assignments.cs:14:18:14:35 | exit (...) => ... | 3 | | Assignments.cs:17:40:17:40 | enter + | Assignments.cs:17:40:17:40 | exit + | 5 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected index ea7fcbfc50f..ba6816e4233 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected @@ -1,4 +1,51 @@ conditionBlock +| Assert.cs:7:10:7:11 | enter M1 | Assert.cs:9:24:9:27 | null | true | +| Assert.cs:7:10:7:11 | enter M1 | Assert.cs:9:31:9:32 | "" | false | +| Assert.cs:14:10:14:11 | enter M2 | Assert.cs:16:24:16:27 | null | true | +| Assert.cs:14:10:14:11 | enter M2 | Assert.cs:16:31:16:32 | "" | false | +| Assert.cs:21:10:21:11 | enter M3 | Assert.cs:23:24:23:27 | null | true | +| Assert.cs:21:10:21:11 | enter M3 | Assert.cs:23:31:23:32 | "" | false | +| Assert.cs:28:10:28:11 | enter M4 | Assert.cs:30:24:30:27 | null | true | +| Assert.cs:28:10:28:11 | enter M4 | Assert.cs:30:31:30:32 | "" | false | +| Assert.cs:35:10:35:11 | enter M5 | Assert.cs:37:24:37:27 | null | true | +| Assert.cs:35:10:35:11 | enter M5 | Assert.cs:37:31:37:32 | "" | false | +| Assert.cs:42:10:42:11 | enter M6 | Assert.cs:44:24:44:27 | null | true | +| Assert.cs:42:10:42:11 | enter M6 | Assert.cs:44:31:44:32 | "" | false | +| Assert.cs:49:10:49:11 | enter M7 | Assert.cs:51:24:51:27 | null | true | +| Assert.cs:49:10:49:11 | enter M7 | Assert.cs:51:31:51:32 | "" | false | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:58:24:58:27 | null | true | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:58:31:58:32 | "" | false | +| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:59:36:59:36 | access to parameter b | true | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:65:24:65:27 | null | true | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:65:31:65:32 | "" | false | +| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:66:37:66:37 | access to parameter b | false | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:72:24:72:27 | null | true | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:72:31:72:32 | "" | false | +| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:73:36:73:36 | access to parameter b | true | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:79:24:79:27 | null | true | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:79:31:79:32 | "" | false | +| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:80:37:80:37 | access to parameter b | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:86:24:86:27 | [b (line 84): true] null | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:86:31:86:32 | [b (line 84): false] "" | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:37:119:38 | [b (line 84): false] !... | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:37:119:38 | [b (line 84): true] !... | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | true | +| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:119:37:119:38 | [b (line 84): false] !... | false | +| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:119:37:119:38 | [b (line 84): true] !... | false | +| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | true | +| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:127:37:127:38 | !... | false | | BreakInTry.cs:7:13:11:13 | foreach (... ... in ...) ... | BreakInTry.cs:7:26:7:28 | String arg | false | | BreakInTry.cs:7:13:11:13 | foreach (... ... in ...) ... | BreakInTry.cs:10:21:10:26 | break; | false | | BreakInTry.cs:7:26:7:28 | String arg | BreakInTry.cs:10:21:10:26 | break; | true | @@ -792,6 +839,72 @@ conditionBlock | cflow.cs:264:25:264:25 | access to local variable i | cflow.cs:268:9:276:9 | try {...} ... | false | | cflow.cs:298:10:298:10 | enter M | cflow.cs:300:56:300:56 | access to parameter s | false | conditionFlow +| Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:9:24:9:27 | null | true | +| Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:9:31:9:32 | "" | false | +| Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:16:24:16:27 | null | true | +| Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:16:31:16:32 | "" | false | +| Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:23:24:23:27 | null | true | +| Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:23:31:23:32 | "" | false | +| Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:30:24:30:27 | null | true | +| Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:30:31:30:32 | "" | false | +| Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:37:24:37:27 | null | true | +| Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:37:31:37:32 | "" | false | +| Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:44:24:44:27 | null | true | +| Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:44:31:44:32 | "" | false | +| Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:51:24:51:27 | null | true | +| Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:51:31:51:32 | "" | false | +| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:24:58:27 | null | true | +| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:31:58:32 | "" | false | +| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:9:59:37 | call to method IsTrue | false | +| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:36:59:36 | access to parameter b | true | +| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:24:65:27 | null | true | +| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:31:65:32 | "" | false | +| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:9:66:38 | call to method IsFalse | true | +| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:37:66:37 | access to parameter b | false | +| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:24:72:27 | null | true | +| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:31:72:32 | "" | false | +| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:9:73:37 | call to method IsTrue | false | +| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:36:73:36 | access to parameter b | true | +| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:24:79:27 | null | true | +| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:31:79:32 | "" | false | +| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:9:80:38 | call to method IsFalse | true | +| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:37:80:37 | access to parameter b | false | +| Assert.cs:86:20:86:20 | access to parameter b | Assert.cs:86:24:86:27 | [b (line 84): true] null | true | +| Assert.cs:86:20:86:20 | access to parameter b | Assert.cs:86:31:86:32 | [b (line 84): false] "" | false | +| Assert.cs:90:13:90:13 | [b (line 84): false] access to parameter b | Assert.cs:90:24:90:25 | [b (line 84): false] "" | false | +| Assert.cs:90:13:90:13 | [b (line 84): true] access to parameter b | Assert.cs:90:17:90:20 | [b (line 84): true] null | true | +| Assert.cs:94:13:94:13 | [b (line 84): false] access to parameter b | Assert.cs:94:24:94:25 | [b (line 84): false] "" | false | +| Assert.cs:94:13:94:13 | [b (line 84): true] access to parameter b | Assert.cs:94:17:94:20 | [b (line 84): true] null | true | +| Assert.cs:98:13:98:13 | [b (line 84): false] access to parameter b | Assert.cs:98:24:98:25 | [b (line 84): false] "" | false | +| Assert.cs:98:13:98:13 | [b (line 84): true] access to parameter b | Assert.cs:98:17:98:20 | [b (line 84): true] null | true | +| Assert.cs:102:13:102:13 | [b (line 84): false] access to parameter b | Assert.cs:102:24:102:25 | [b (line 84): false] "" | false | +| Assert.cs:102:13:102:13 | [b (line 84): true] access to parameter b | Assert.cs:102:17:102:20 | [b (line 84): true] null | true | +| Assert.cs:106:13:106:13 | [b (line 84): false] access to parameter b | Assert.cs:106:24:106:25 | [b (line 84): false] "" | false | +| Assert.cs:106:13:106:13 | [b (line 84): true] access to parameter b | Assert.cs:106:17:106:20 | [b (line 84): true] null | true | +| Assert.cs:110:13:110:13 | [b (line 84): false] access to parameter b | Assert.cs:110:24:110:25 | [b (line 84): false] "" | false | +| Assert.cs:110:13:110:13 | [b (line 84): true] access to parameter b | Assert.cs:110:17:110:20 | [b (line 84): true] null | true | +| Assert.cs:114:13:114:13 | [b (line 84): false] access to parameter b | Assert.cs:114:24:114:25 | [b (line 84): false] "" | false | +| Assert.cs:114:13:114:13 | [b (line 84): true] access to parameter b | Assert.cs:114:17:114:20 | [b (line 84): true] null | true | +| Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | false | +| Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | true | +| Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | false | +| Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | Assert.cs:118:24:118:25 | [b (line 84): false] "" | false | +| Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | Assert.cs:118:17:118:20 | [b (line 84): true] null | true | +| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | true | +| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | Assert.cs:119:37:119:38 | [b (line 84): false] !... | false | +| Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | true | +| Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:37:119:38 | [b (line 84): true] !... | false | +| Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | Assert.cs:122:24:122:25 | [b (line 84): false] "" | false | +| Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | Assert.cs:122:17:122:20 | [b (line 84): true] null | true | +| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | false | +| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | true | +| Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | false | +| Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | Assert.cs:126:24:126:25 | "" | false | +| Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | Assert.cs:126:17:126:20 | null | true | +| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:9:127:39 | call to method IsFalse | true | +| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:37:127:38 | !... | false | | BreakInTry.cs:9:21:9:31 | ... == ... | BreakInTry.cs:7:13:11:13 | foreach (... ... in ...) ... | false | | BreakInTry.cs:9:21:9:31 | ... == ... | BreakInTry.cs:10:21:10:26 | break; | true | | BreakInTry.cs:15:17:15:28 | ... == ... | BreakInTry.cs:3:10:3:11 | exit M1 | false | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index 773e3cd0204..75d607cd710 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -308,6 +308,491 @@ dominance | ArrayCreation.cs:9:43:9:50 | { ..., ... } | ArrayCreation.cs:9:31:9:52 | { ..., ... } | | ArrayCreation.cs:9:45:9:45 | 2 | ArrayCreation.cs:9:48:9:48 | 3 | | ArrayCreation.cs:9:48:9:48 | 3 | ArrayCreation.cs:9:43:9:50 | { ..., ... } | +| Assert.cs:7:10:7:11 | enter M1 | Assert.cs:8:5:12:5 | {...} | +| Assert.cs:8:5:12:5 | {...} | Assert.cs:9:9:9:33 | ... ...; | +| Assert.cs:9:9:9:33 | ... ...; | Assert.cs:9:20:9:32 | ... ? ... : ... | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:10:9:10:32 | ...; | +| Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:9:24:9:27 | null | +| Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:9:31:9:32 | "" | +| Assert.cs:9:20:9:32 | ... ? ... : ... | Assert.cs:9:20:9:20 | access to parameter b | +| Assert.cs:10:9:10:31 | call to method Assert | Assert.cs:11:9:11:36 | ...; | +| Assert.cs:10:9:10:32 | ...; | Assert.cs:10:22:10:22 | access to local variable s | +| Assert.cs:10:22:10:22 | access to local variable s | Assert.cs:10:27:10:30 | null | +| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:9:10:31 | call to method Assert | +| Assert.cs:10:27:10:30 | null | Assert.cs:10:22:10:30 | ... != ... | +| Assert.cs:11:9:11:35 | call to method WriteLine | Assert.cs:7:10:7:11 | exit M1 | +| Assert.cs:11:9:11:36 | ...; | Assert.cs:11:27:11:27 | access to local variable s | +| Assert.cs:11:27:11:27 | access to local variable s | Assert.cs:11:27:11:34 | access to property Length | +| Assert.cs:11:27:11:34 | access to property Length | Assert.cs:11:9:11:35 | call to method WriteLine | +| Assert.cs:14:10:14:11 | enter M2 | Assert.cs:15:5:19:5 | {...} | +| Assert.cs:15:5:19:5 | {...} | Assert.cs:16:9:16:33 | ... ...; | +| Assert.cs:16:9:16:33 | ... ...; | Assert.cs:16:20:16:32 | ... ? ... : ... | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:17:9:17:25 | ...; | +| Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:16:24:16:27 | null | +| Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:16:31:16:32 | "" | +| Assert.cs:16:20:16:32 | ... ? ... : ... | Assert.cs:16:20:16:20 | access to parameter b | +| Assert.cs:17:9:17:24 | call to method IsNull | Assert.cs:18:9:18:36 | ...; | +| Assert.cs:17:9:17:25 | ...; | Assert.cs:17:23:17:23 | access to local variable s | +| Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:17:9:17:24 | call to method IsNull | +| Assert.cs:18:9:18:35 | call to method WriteLine | Assert.cs:14:10:14:11 | exit M2 | +| Assert.cs:18:9:18:36 | ...; | Assert.cs:18:27:18:27 | access to local variable s | +| Assert.cs:18:27:18:27 | access to local variable s | Assert.cs:18:27:18:34 | access to property Length | +| Assert.cs:18:27:18:34 | access to property Length | Assert.cs:18:9:18:35 | call to method WriteLine | +| Assert.cs:21:10:21:11 | enter M3 | Assert.cs:22:5:26:5 | {...} | +| Assert.cs:22:5:26:5 | {...} | Assert.cs:23:9:23:33 | ... ...; | +| Assert.cs:23:9:23:33 | ... ...; | Assert.cs:23:20:23:32 | ... ? ... : ... | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:24:9:24:28 | ...; | +| Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:23:24:23:27 | null | +| Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:23:31:23:32 | "" | +| Assert.cs:23:20:23:32 | ... ? ... : ... | Assert.cs:23:20:23:20 | access to parameter b | +| Assert.cs:24:9:24:27 | call to method IsNotNull | Assert.cs:25:9:25:36 | ...; | +| Assert.cs:24:9:24:28 | ...; | Assert.cs:24:26:24:26 | access to local variable s | +| Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:24:9:24:27 | call to method IsNotNull | +| Assert.cs:25:9:25:35 | call to method WriteLine | Assert.cs:21:10:21:11 | exit M3 | +| Assert.cs:25:9:25:36 | ...; | Assert.cs:25:27:25:27 | access to local variable s | +| Assert.cs:25:27:25:27 | access to local variable s | Assert.cs:25:27:25:34 | access to property Length | +| Assert.cs:25:27:25:34 | access to property Length | Assert.cs:25:9:25:35 | call to method WriteLine | +| Assert.cs:28:10:28:11 | enter M4 | Assert.cs:29:5:33:5 | {...} | +| Assert.cs:29:5:33:5 | {...} | Assert.cs:30:9:30:33 | ... ...; | +| Assert.cs:30:9:30:33 | ... ...; | Assert.cs:30:20:30:32 | ... ? ... : ... | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:31:9:31:33 | ...; | +| Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:30:24:30:27 | null | +| Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:30:31:30:32 | "" | +| Assert.cs:30:20:30:32 | ... ? ... : ... | Assert.cs:30:20:30:20 | access to parameter b | +| Assert.cs:31:9:31:32 | call to method IsTrue | Assert.cs:32:9:32:36 | ...; | +| Assert.cs:31:9:31:33 | ...; | Assert.cs:31:23:31:23 | access to local variable s | +| Assert.cs:31:23:31:23 | access to local variable s | Assert.cs:31:28:31:31 | null | +| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:9:31:32 | call to method IsTrue | +| Assert.cs:31:28:31:31 | null | Assert.cs:31:23:31:31 | ... == ... | +| Assert.cs:32:9:32:35 | call to method WriteLine | Assert.cs:28:10:28:11 | exit M4 | +| Assert.cs:32:9:32:36 | ...; | Assert.cs:32:27:32:27 | access to local variable s | +| Assert.cs:32:27:32:27 | access to local variable s | Assert.cs:32:27:32:34 | access to property Length | +| Assert.cs:32:27:32:34 | access to property Length | Assert.cs:32:9:32:35 | call to method WriteLine | +| Assert.cs:35:10:35:11 | enter M5 | Assert.cs:36:5:40:5 | {...} | +| Assert.cs:36:5:40:5 | {...} | Assert.cs:37:9:37:33 | ... ...; | +| Assert.cs:37:9:37:33 | ... ...; | Assert.cs:37:20:37:32 | ... ? ... : ... | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:38:9:38:33 | ...; | +| Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:37:24:37:27 | null | +| Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:37:31:37:32 | "" | +| Assert.cs:37:20:37:32 | ... ? ... : ... | Assert.cs:37:20:37:20 | access to parameter b | +| Assert.cs:38:9:38:32 | call to method IsTrue | Assert.cs:39:9:39:36 | ...; | +| Assert.cs:38:9:38:33 | ...; | Assert.cs:38:23:38:23 | access to local variable s | +| Assert.cs:38:23:38:23 | access to local variable s | Assert.cs:38:28:38:31 | null | +| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:9:38:32 | call to method IsTrue | +| Assert.cs:38:28:38:31 | null | Assert.cs:38:23:38:31 | ... != ... | +| Assert.cs:39:9:39:35 | call to method WriteLine | Assert.cs:35:10:35:11 | exit M5 | +| Assert.cs:39:9:39:36 | ...; | Assert.cs:39:27:39:27 | access to local variable s | +| Assert.cs:39:27:39:27 | access to local variable s | Assert.cs:39:27:39:34 | access to property Length | +| Assert.cs:39:27:39:34 | access to property Length | Assert.cs:39:9:39:35 | call to method WriteLine | +| Assert.cs:42:10:42:11 | enter M6 | Assert.cs:43:5:47:5 | {...} | +| Assert.cs:43:5:47:5 | {...} | Assert.cs:44:9:44:33 | ... ...; | +| Assert.cs:44:9:44:33 | ... ...; | Assert.cs:44:20:44:32 | ... ? ... : ... | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:45:9:45:34 | ...; | +| Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:44:24:44:27 | null | +| Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:44:31:44:32 | "" | +| Assert.cs:44:20:44:32 | ... ? ... : ... | Assert.cs:44:20:44:20 | access to parameter b | +| Assert.cs:45:9:45:33 | call to method IsFalse | Assert.cs:46:9:46:36 | ...; | +| Assert.cs:45:9:45:34 | ...; | Assert.cs:45:24:45:24 | access to local variable s | +| Assert.cs:45:24:45:24 | access to local variable s | Assert.cs:45:29:45:32 | null | +| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:9:45:33 | call to method IsFalse | +| Assert.cs:45:29:45:32 | null | Assert.cs:45:24:45:32 | ... != ... | +| Assert.cs:46:9:46:35 | call to method WriteLine | Assert.cs:42:10:42:11 | exit M6 | +| Assert.cs:46:9:46:36 | ...; | Assert.cs:46:27:46:27 | access to local variable s | +| Assert.cs:46:27:46:27 | access to local variable s | Assert.cs:46:27:46:34 | access to property Length | +| Assert.cs:46:27:46:34 | access to property Length | Assert.cs:46:9:46:35 | call to method WriteLine | +| Assert.cs:49:10:49:11 | enter M7 | Assert.cs:50:5:54:5 | {...} | +| Assert.cs:50:5:54:5 | {...} | Assert.cs:51:9:51:33 | ... ...; | +| Assert.cs:51:9:51:33 | ... ...; | Assert.cs:51:20:51:32 | ... ? ... : ... | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:52:9:52:34 | ...; | +| Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:51:24:51:27 | null | +| Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:51:31:51:32 | "" | +| Assert.cs:51:20:51:32 | ... ? ... : ... | Assert.cs:51:20:51:20 | access to parameter b | +| Assert.cs:52:9:52:33 | call to method IsFalse | Assert.cs:53:9:53:36 | ...; | +| Assert.cs:52:9:52:34 | ...; | Assert.cs:52:24:52:24 | access to local variable s | +| Assert.cs:52:24:52:24 | access to local variable s | Assert.cs:52:29:52:32 | null | +| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:9:52:33 | call to method IsFalse | +| Assert.cs:52:29:52:32 | null | Assert.cs:52:24:52:32 | ... == ... | +| Assert.cs:53:9:53:35 | call to method WriteLine | Assert.cs:49:10:49:11 | exit M7 | +| Assert.cs:53:9:53:36 | ...; | Assert.cs:53:27:53:27 | access to local variable s | +| Assert.cs:53:27:53:27 | access to local variable s | Assert.cs:53:27:53:34 | access to property Length | +| Assert.cs:53:27:53:34 | access to property Length | Assert.cs:53:9:53:35 | call to method WriteLine | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:57:5:61:5 | {...} | +| Assert.cs:57:5:61:5 | {...} | Assert.cs:58:9:58:33 | ... ...; | +| Assert.cs:58:9:58:33 | ... ...; | Assert.cs:58:20:58:32 | ... ? ... : ... | +| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:59:9:59:38 | ...; | +| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:24:58:27 | null | +| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:31:58:32 | "" | +| Assert.cs:58:20:58:32 | ... ? ... : ... | Assert.cs:58:20:58:20 | access to parameter b | +| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:60:9:60:36 | ...; | +| Assert.cs:59:9:59:38 | ...; | Assert.cs:59:23:59:36 | ... && ... | +| Assert.cs:59:23:59:23 | access to local variable s | Assert.cs:59:28:59:31 | null | +| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:9:59:37 | call to method IsTrue | +| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:36:59:36 | access to parameter b | +| Assert.cs:59:23:59:36 | ... && ... | Assert.cs:59:23:59:23 | access to local variable s | +| Assert.cs:59:28:59:31 | null | Assert.cs:59:23:59:31 | ... != ... | +| Assert.cs:60:9:60:35 | call to method WriteLine | Assert.cs:56:10:56:11 | exit M8 | +| Assert.cs:60:9:60:36 | ...; | Assert.cs:60:27:60:27 | access to local variable s | +| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:60:27:60:34 | access to property Length | +| Assert.cs:60:27:60:34 | access to property Length | Assert.cs:60:9:60:35 | call to method WriteLine | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:64:5:68:5 | {...} | +| Assert.cs:64:5:68:5 | {...} | Assert.cs:65:9:65:33 | ... ...; | +| Assert.cs:65:9:65:33 | ... ...; | Assert.cs:65:20:65:32 | ... ? ... : ... | +| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:66:9:66:39 | ...; | +| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:24:65:27 | null | +| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:31:65:32 | "" | +| Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:65:20:65:20 | access to parameter b | +| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:67:9:67:36 | ...; | +| Assert.cs:66:9:66:39 | ...; | Assert.cs:66:24:66:37 | ... \|\| ... | +| Assert.cs:66:24:66:24 | access to local variable s | Assert.cs:66:29:66:32 | null | +| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:9:66:38 | call to method IsFalse | +| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:37:66:37 | access to parameter b | +| Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:66:24:66:24 | access to local variable s | +| Assert.cs:66:29:66:32 | null | Assert.cs:66:24:66:32 | ... == ... | +| Assert.cs:67:9:67:35 | call to method WriteLine | Assert.cs:63:10:63:11 | exit M9 | +| Assert.cs:67:9:67:36 | ...; | Assert.cs:67:27:67:27 | access to local variable s | +| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:67:27:67:34 | access to property Length | +| Assert.cs:67:27:67:34 | access to property Length | Assert.cs:67:9:67:35 | call to method WriteLine | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:71:5:75:5 | {...} | +| Assert.cs:71:5:75:5 | {...} | Assert.cs:72:9:72:33 | ... ...; | +| Assert.cs:72:9:72:33 | ... ...; | Assert.cs:72:20:72:32 | ... ? ... : ... | +| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:73:9:73:38 | ...; | +| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:24:72:27 | null | +| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:31:72:32 | "" | +| Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:72:20:72:20 | access to parameter b | +| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:74:9:74:36 | ...; | +| Assert.cs:73:9:73:38 | ...; | Assert.cs:73:23:73:36 | ... && ... | +| Assert.cs:73:23:73:23 | access to local variable s | Assert.cs:73:28:73:31 | null | +| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:9:73:37 | call to method IsTrue | +| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:36:73:36 | access to parameter b | +| Assert.cs:73:23:73:36 | ... && ... | Assert.cs:73:23:73:23 | access to local variable s | +| Assert.cs:73:28:73:31 | null | Assert.cs:73:23:73:31 | ... == ... | +| Assert.cs:74:9:74:35 | call to method WriteLine | Assert.cs:70:10:70:12 | exit M10 | +| Assert.cs:74:9:74:36 | ...; | Assert.cs:74:27:74:27 | access to local variable s | +| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:74:27:74:34 | access to property Length | +| Assert.cs:74:27:74:34 | access to property Length | Assert.cs:74:9:74:35 | call to method WriteLine | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:78:5:82:5 | {...} | +| Assert.cs:78:5:82:5 | {...} | Assert.cs:79:9:79:33 | ... ...; | +| Assert.cs:79:9:79:33 | ... ...; | Assert.cs:79:20:79:32 | ... ? ... : ... | +| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:80:9:80:39 | ...; | +| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:24:79:27 | null | +| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:31:79:32 | "" | +| Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:79:20:79:20 | access to parameter b | +| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:81:9:81:36 | ...; | +| Assert.cs:80:9:80:39 | ...; | Assert.cs:80:24:80:37 | ... \|\| ... | +| Assert.cs:80:24:80:24 | access to local variable s | Assert.cs:80:29:80:32 | null | +| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:9:80:38 | call to method IsFalse | +| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:37:80:37 | access to parameter b | +| Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:24:80:24 | access to local variable s | +| Assert.cs:80:29:80:32 | null | Assert.cs:80:24:80:32 | ... != ... | +| Assert.cs:81:9:81:35 | call to method WriteLine | Assert.cs:77:10:77:12 | exit M11 | +| Assert.cs:81:9:81:36 | ...; | Assert.cs:81:27:81:27 | access to local variable s | +| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:81:27:81:34 | access to property Length | +| Assert.cs:81:27:81:34 | access to property Length | Assert.cs:81:9:81:35 | call to method WriteLine | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:85:5:129:5 | {...} | +| Assert.cs:85:5:129:5 | {...} | Assert.cs:86:9:86:33 | ... ...; | +| Assert.cs:86:9:86:33 | ... ...; | Assert.cs:86:20:86:32 | ... ? ... : ... | +| Assert.cs:86:16:86:32 | [b (line 84): false] String s = ... | Assert.cs:87:9:87:32 | [b (line 84): false] ...; | +| Assert.cs:86:16:86:32 | [b (line 84): true] String s = ... | Assert.cs:87:9:87:32 | [b (line 84): true] ...; | +| Assert.cs:86:20:86:20 | access to parameter b | Assert.cs:86:24:86:27 | [b (line 84): true] null | +| Assert.cs:86:20:86:20 | access to parameter b | Assert.cs:86:31:86:32 | [b (line 84): false] "" | +| Assert.cs:86:20:86:32 | ... ? ... : ... | Assert.cs:86:20:86:20 | access to parameter b | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:86:16:86:32 | [b (line 84): true] String s = ... | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:86:16:86:32 | [b (line 84): false] String s = ... | +| Assert.cs:87:9:87:31 | [b (line 84): false] call to method Assert | Assert.cs:88:9:88:36 | [b (line 84): false] ...; | +| Assert.cs:87:9:87:31 | [b (line 84): true] call to method Assert | Assert.cs:88:9:88:36 | [b (line 84): true] ...; | +| Assert.cs:87:9:87:32 | [b (line 84): false] ...; | Assert.cs:87:22:87:22 | [b (line 84): false] access to local variable s | +| Assert.cs:87:9:87:32 | [b (line 84): true] ...; | Assert.cs:87:22:87:22 | [b (line 84): true] access to local variable s | +| Assert.cs:87:22:87:22 | [b (line 84): false] access to local variable s | Assert.cs:87:27:87:30 | [b (line 84): false] null | +| Assert.cs:87:22:87:22 | [b (line 84): true] access to local variable s | Assert.cs:87:27:87:30 | [b (line 84): true] null | +| Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | Assert.cs:87:9:87:31 | [b (line 84): false] call to method Assert | +| Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | Assert.cs:87:9:87:31 | [b (line 84): true] call to method Assert | +| Assert.cs:87:27:87:30 | [b (line 84): false] null | Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | +| Assert.cs:87:27:87:30 | [b (line 84): true] null | Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | +| Assert.cs:88:9:88:35 | [b (line 84): false] call to method WriteLine | Assert.cs:90:9:90:26 | [b (line 84): false] ...; | +| Assert.cs:88:9:88:35 | [b (line 84): true] call to method WriteLine | Assert.cs:90:9:90:26 | [b (line 84): true] ...; | +| Assert.cs:88:9:88:36 | [b (line 84): false] ...; | Assert.cs:88:27:88:27 | [b (line 84): false] access to local variable s | +| Assert.cs:88:9:88:36 | [b (line 84): true] ...; | Assert.cs:88:27:88:27 | [b (line 84): true] access to local variable s | +| Assert.cs:88:27:88:27 | [b (line 84): false] access to local variable s | Assert.cs:88:27:88:34 | [b (line 84): false] access to property Length | +| Assert.cs:88:27:88:27 | [b (line 84): true] access to local variable s | Assert.cs:88:27:88:34 | [b (line 84): true] access to property Length | +| Assert.cs:88:27:88:34 | [b (line 84): false] access to property Length | Assert.cs:88:9:88:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:88:27:88:34 | [b (line 84): true] access to property Length | Assert.cs:88:9:88:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:90:9:90:25 | [b (line 84): false] ... = ... | Assert.cs:91:9:91:25 | [b (line 84): false] ...; | +| Assert.cs:90:9:90:25 | [b (line 84): true] ... = ... | Assert.cs:91:9:91:25 | [b (line 84): true] ...; | +| Assert.cs:90:9:90:26 | [b (line 84): false] ...; | Assert.cs:90:13:90:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:90:9:90:26 | [b (line 84): true] ...; | Assert.cs:90:13:90:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:90:13:90:13 | [b (line 84): false] access to parameter b | Assert.cs:90:24:90:25 | [b (line 84): false] "" | +| Assert.cs:90:13:90:13 | [b (line 84): true] access to parameter b | Assert.cs:90:17:90:20 | [b (line 84): true] null | +| Assert.cs:90:13:90:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:90:13:90:13 | [b (line 84): false] access to parameter b | +| Assert.cs:90:13:90:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:90:13:90:13 | [b (line 84): true] access to parameter b | +| Assert.cs:90:17:90:20 | [b (line 84): true] null | Assert.cs:90:9:90:25 | [b (line 84): true] ... = ... | +| Assert.cs:90:24:90:25 | [b (line 84): false] "" | Assert.cs:90:9:90:25 | [b (line 84): false] ... = ... | +| Assert.cs:91:9:91:24 | [b (line 84): false] call to method IsNull | Assert.cs:92:9:92:36 | [b (line 84): false] ...; | +| Assert.cs:91:9:91:24 | [b (line 84): true] call to method IsNull | Assert.cs:92:9:92:36 | [b (line 84): true] ...; | +| Assert.cs:91:9:91:25 | [b (line 84): false] ...; | Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | +| Assert.cs:91:9:91:25 | [b (line 84): true] ...; | Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | +| Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | Assert.cs:91:9:91:24 | [b (line 84): false] call to method IsNull | +| Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | Assert.cs:91:9:91:24 | [b (line 84): true] call to method IsNull | +| Assert.cs:92:9:92:35 | [b (line 84): false] call to method WriteLine | Assert.cs:94:9:94:26 | [b (line 84): false] ...; | +| Assert.cs:92:9:92:35 | [b (line 84): true] call to method WriteLine | Assert.cs:94:9:94:26 | [b (line 84): true] ...; | +| Assert.cs:92:9:92:36 | [b (line 84): false] ...; | Assert.cs:92:27:92:27 | [b (line 84): false] access to local variable s | +| Assert.cs:92:9:92:36 | [b (line 84): true] ...; | Assert.cs:92:27:92:27 | [b (line 84): true] access to local variable s | +| Assert.cs:92:27:92:27 | [b (line 84): false] access to local variable s | Assert.cs:92:27:92:34 | [b (line 84): false] access to property Length | +| Assert.cs:92:27:92:27 | [b (line 84): true] access to local variable s | Assert.cs:92:27:92:34 | [b (line 84): true] access to property Length | +| Assert.cs:92:27:92:34 | [b (line 84): false] access to property Length | Assert.cs:92:9:92:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:92:27:92:34 | [b (line 84): true] access to property Length | Assert.cs:92:9:92:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:94:9:94:25 | [b (line 84): false] ... = ... | Assert.cs:95:9:95:28 | [b (line 84): false] ...; | +| Assert.cs:94:9:94:25 | [b (line 84): true] ... = ... | Assert.cs:95:9:95:28 | [b (line 84): true] ...; | +| Assert.cs:94:9:94:26 | [b (line 84): false] ...; | Assert.cs:94:13:94:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:94:9:94:26 | [b (line 84): true] ...; | Assert.cs:94:13:94:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:94:13:94:13 | [b (line 84): false] access to parameter b | Assert.cs:94:24:94:25 | [b (line 84): false] "" | +| Assert.cs:94:13:94:13 | [b (line 84): true] access to parameter b | Assert.cs:94:17:94:20 | [b (line 84): true] null | +| Assert.cs:94:13:94:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:94:13:94:13 | [b (line 84): false] access to parameter b | +| Assert.cs:94:13:94:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:94:13:94:13 | [b (line 84): true] access to parameter b | +| Assert.cs:94:17:94:20 | [b (line 84): true] null | Assert.cs:94:9:94:25 | [b (line 84): true] ... = ... | +| Assert.cs:94:24:94:25 | [b (line 84): false] "" | Assert.cs:94:9:94:25 | [b (line 84): false] ... = ... | +| Assert.cs:95:9:95:27 | [b (line 84): false] call to method IsNotNull | Assert.cs:96:9:96:36 | [b (line 84): false] ...; | +| Assert.cs:95:9:95:27 | [b (line 84): true] call to method IsNotNull | Assert.cs:96:9:96:36 | [b (line 84): true] ...; | +| Assert.cs:95:9:95:28 | [b (line 84): false] ...; | Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | +| Assert.cs:95:9:95:28 | [b (line 84): true] ...; | Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | +| Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | Assert.cs:95:9:95:27 | [b (line 84): false] call to method IsNotNull | +| Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | Assert.cs:95:9:95:27 | [b (line 84): true] call to method IsNotNull | +| Assert.cs:96:9:96:35 | [b (line 84): false] call to method WriteLine | Assert.cs:98:9:98:26 | [b (line 84): false] ...; | +| Assert.cs:96:9:96:35 | [b (line 84): true] call to method WriteLine | Assert.cs:98:9:98:26 | [b (line 84): true] ...; | +| Assert.cs:96:9:96:36 | [b (line 84): false] ...; | Assert.cs:96:27:96:27 | [b (line 84): false] access to local variable s | +| Assert.cs:96:9:96:36 | [b (line 84): true] ...; | Assert.cs:96:27:96:27 | [b (line 84): true] access to local variable s | +| Assert.cs:96:27:96:27 | [b (line 84): false] access to local variable s | Assert.cs:96:27:96:34 | [b (line 84): false] access to property Length | +| Assert.cs:96:27:96:27 | [b (line 84): true] access to local variable s | Assert.cs:96:27:96:34 | [b (line 84): true] access to property Length | +| Assert.cs:96:27:96:34 | [b (line 84): false] access to property Length | Assert.cs:96:9:96:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:96:27:96:34 | [b (line 84): true] access to property Length | Assert.cs:96:9:96:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:98:9:98:25 | [b (line 84): false] ... = ... | Assert.cs:99:9:99:33 | [b (line 84): false] ...; | +| Assert.cs:98:9:98:25 | [b (line 84): true] ... = ... | Assert.cs:99:9:99:33 | [b (line 84): true] ...; | +| Assert.cs:98:9:98:26 | [b (line 84): false] ...; | Assert.cs:98:13:98:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:98:9:98:26 | [b (line 84): true] ...; | Assert.cs:98:13:98:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:98:13:98:13 | [b (line 84): false] access to parameter b | Assert.cs:98:24:98:25 | [b (line 84): false] "" | +| Assert.cs:98:13:98:13 | [b (line 84): true] access to parameter b | Assert.cs:98:17:98:20 | [b (line 84): true] null | +| Assert.cs:98:13:98:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:98:13:98:13 | [b (line 84): false] access to parameter b | +| Assert.cs:98:13:98:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:98:13:98:13 | [b (line 84): true] access to parameter b | +| Assert.cs:98:17:98:20 | [b (line 84): true] null | Assert.cs:98:9:98:25 | [b (line 84): true] ... = ... | +| Assert.cs:98:24:98:25 | [b (line 84): false] "" | Assert.cs:98:9:98:25 | [b (line 84): false] ... = ... | +| Assert.cs:99:9:99:32 | [b (line 84): false] call to method IsTrue | Assert.cs:100:9:100:36 | [b (line 84): false] ...; | +| Assert.cs:99:9:99:32 | [b (line 84): true] call to method IsTrue | Assert.cs:100:9:100:36 | [b (line 84): true] ...; | +| Assert.cs:99:9:99:33 | [b (line 84): false] ...; | Assert.cs:99:23:99:23 | [b (line 84): false] access to local variable s | +| Assert.cs:99:9:99:33 | [b (line 84): true] ...; | Assert.cs:99:23:99:23 | [b (line 84): true] access to local variable s | +| Assert.cs:99:23:99:23 | [b (line 84): false] access to local variable s | Assert.cs:99:28:99:31 | [b (line 84): false] null | +| Assert.cs:99:23:99:23 | [b (line 84): true] access to local variable s | Assert.cs:99:28:99:31 | [b (line 84): true] null | +| Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | Assert.cs:99:9:99:32 | [b (line 84): false] call to method IsTrue | +| Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | Assert.cs:99:9:99:32 | [b (line 84): true] call to method IsTrue | +| Assert.cs:99:28:99:31 | [b (line 84): false] null | Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | +| Assert.cs:99:28:99:31 | [b (line 84): true] null | Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | +| Assert.cs:100:9:100:35 | [b (line 84): false] call to method WriteLine | Assert.cs:102:9:102:26 | [b (line 84): false] ...; | +| Assert.cs:100:9:100:35 | [b (line 84): true] call to method WriteLine | Assert.cs:102:9:102:26 | [b (line 84): true] ...; | +| Assert.cs:100:9:100:36 | [b (line 84): false] ...; | Assert.cs:100:27:100:27 | [b (line 84): false] access to local variable s | +| Assert.cs:100:9:100:36 | [b (line 84): true] ...; | Assert.cs:100:27:100:27 | [b (line 84): true] access to local variable s | +| Assert.cs:100:27:100:27 | [b (line 84): false] access to local variable s | Assert.cs:100:27:100:34 | [b (line 84): false] access to property Length | +| Assert.cs:100:27:100:27 | [b (line 84): true] access to local variable s | Assert.cs:100:27:100:34 | [b (line 84): true] access to property Length | +| Assert.cs:100:27:100:34 | [b (line 84): false] access to property Length | Assert.cs:100:9:100:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:100:27:100:34 | [b (line 84): true] access to property Length | Assert.cs:100:9:100:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:102:9:102:25 | [b (line 84): false] ... = ... | Assert.cs:103:9:103:33 | [b (line 84): false] ...; | +| Assert.cs:102:9:102:25 | [b (line 84): true] ... = ... | Assert.cs:103:9:103:33 | [b (line 84): true] ...; | +| Assert.cs:102:9:102:26 | [b (line 84): false] ...; | Assert.cs:102:13:102:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:102:9:102:26 | [b (line 84): true] ...; | Assert.cs:102:13:102:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:102:13:102:13 | [b (line 84): false] access to parameter b | Assert.cs:102:24:102:25 | [b (line 84): false] "" | +| Assert.cs:102:13:102:13 | [b (line 84): true] access to parameter b | Assert.cs:102:17:102:20 | [b (line 84): true] null | +| Assert.cs:102:13:102:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:102:13:102:13 | [b (line 84): false] access to parameter b | +| Assert.cs:102:13:102:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:102:13:102:13 | [b (line 84): true] access to parameter b | +| Assert.cs:102:17:102:20 | [b (line 84): true] null | Assert.cs:102:9:102:25 | [b (line 84): true] ... = ... | +| Assert.cs:102:24:102:25 | [b (line 84): false] "" | Assert.cs:102:9:102:25 | [b (line 84): false] ... = ... | +| Assert.cs:103:9:103:32 | [b (line 84): false] call to method IsTrue | Assert.cs:104:9:104:36 | [b (line 84): false] ...; | +| Assert.cs:103:9:103:32 | [b (line 84): true] call to method IsTrue | Assert.cs:104:9:104:36 | [b (line 84): true] ...; | +| Assert.cs:103:9:103:33 | [b (line 84): false] ...; | Assert.cs:103:23:103:23 | [b (line 84): false] access to local variable s | +| Assert.cs:103:9:103:33 | [b (line 84): true] ...; | Assert.cs:103:23:103:23 | [b (line 84): true] access to local variable s | +| Assert.cs:103:23:103:23 | [b (line 84): false] access to local variable s | Assert.cs:103:28:103:31 | [b (line 84): false] null | +| Assert.cs:103:23:103:23 | [b (line 84): true] access to local variable s | Assert.cs:103:28:103:31 | [b (line 84): true] null | +| Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | Assert.cs:103:9:103:32 | [b (line 84): false] call to method IsTrue | +| Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | Assert.cs:103:9:103:32 | [b (line 84): true] call to method IsTrue | +| Assert.cs:103:28:103:31 | [b (line 84): false] null | Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | +| Assert.cs:103:28:103:31 | [b (line 84): true] null | Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | +| Assert.cs:104:9:104:35 | [b (line 84): false] call to method WriteLine | Assert.cs:106:9:106:26 | [b (line 84): false] ...; | +| Assert.cs:104:9:104:35 | [b (line 84): true] call to method WriteLine | Assert.cs:106:9:106:26 | [b (line 84): true] ...; | +| Assert.cs:104:9:104:36 | [b (line 84): false] ...; | Assert.cs:104:27:104:27 | [b (line 84): false] access to local variable s | +| Assert.cs:104:9:104:36 | [b (line 84): true] ...; | Assert.cs:104:27:104:27 | [b (line 84): true] access to local variable s | +| Assert.cs:104:27:104:27 | [b (line 84): false] access to local variable s | Assert.cs:104:27:104:34 | [b (line 84): false] access to property Length | +| Assert.cs:104:27:104:27 | [b (line 84): true] access to local variable s | Assert.cs:104:27:104:34 | [b (line 84): true] access to property Length | +| Assert.cs:104:27:104:34 | [b (line 84): false] access to property Length | Assert.cs:104:9:104:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:104:27:104:34 | [b (line 84): true] access to property Length | Assert.cs:104:9:104:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:106:9:106:25 | [b (line 84): false] ... = ... | Assert.cs:107:9:107:34 | [b (line 84): false] ...; | +| Assert.cs:106:9:106:25 | [b (line 84): true] ... = ... | Assert.cs:107:9:107:34 | [b (line 84): true] ...; | +| Assert.cs:106:9:106:26 | [b (line 84): false] ...; | Assert.cs:106:13:106:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:106:9:106:26 | [b (line 84): true] ...; | Assert.cs:106:13:106:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:106:13:106:13 | [b (line 84): false] access to parameter b | Assert.cs:106:24:106:25 | [b (line 84): false] "" | +| Assert.cs:106:13:106:13 | [b (line 84): true] access to parameter b | Assert.cs:106:17:106:20 | [b (line 84): true] null | +| Assert.cs:106:13:106:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:106:13:106:13 | [b (line 84): false] access to parameter b | +| Assert.cs:106:13:106:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:106:13:106:13 | [b (line 84): true] access to parameter b | +| Assert.cs:106:17:106:20 | [b (line 84): true] null | Assert.cs:106:9:106:25 | [b (line 84): true] ... = ... | +| Assert.cs:106:24:106:25 | [b (line 84): false] "" | Assert.cs:106:9:106:25 | [b (line 84): false] ... = ... | +| Assert.cs:107:9:107:33 | [b (line 84): false] call to method IsFalse | Assert.cs:108:9:108:36 | [b (line 84): false] ...; | +| Assert.cs:107:9:107:33 | [b (line 84): true] call to method IsFalse | Assert.cs:108:9:108:36 | [b (line 84): true] ...; | +| Assert.cs:107:9:107:34 | [b (line 84): false] ...; | Assert.cs:107:24:107:24 | [b (line 84): false] access to local variable s | +| Assert.cs:107:9:107:34 | [b (line 84): true] ...; | Assert.cs:107:24:107:24 | [b (line 84): true] access to local variable s | +| Assert.cs:107:24:107:24 | [b (line 84): false] access to local variable s | Assert.cs:107:29:107:32 | [b (line 84): false] null | +| Assert.cs:107:24:107:24 | [b (line 84): true] access to local variable s | Assert.cs:107:29:107:32 | [b (line 84): true] null | +| Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | Assert.cs:107:9:107:33 | [b (line 84): false] call to method IsFalse | +| Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | Assert.cs:107:9:107:33 | [b (line 84): true] call to method IsFalse | +| Assert.cs:107:29:107:32 | [b (line 84): false] null | Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | +| Assert.cs:107:29:107:32 | [b (line 84): true] null | Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | +| Assert.cs:108:9:108:35 | [b (line 84): false] call to method WriteLine | Assert.cs:110:9:110:26 | [b (line 84): false] ...; | +| Assert.cs:108:9:108:35 | [b (line 84): true] call to method WriteLine | Assert.cs:110:9:110:26 | [b (line 84): true] ...; | +| Assert.cs:108:9:108:36 | [b (line 84): false] ...; | Assert.cs:108:27:108:27 | [b (line 84): false] access to local variable s | +| Assert.cs:108:9:108:36 | [b (line 84): true] ...; | Assert.cs:108:27:108:27 | [b (line 84): true] access to local variable s | +| Assert.cs:108:27:108:27 | [b (line 84): false] access to local variable s | Assert.cs:108:27:108:34 | [b (line 84): false] access to property Length | +| Assert.cs:108:27:108:27 | [b (line 84): true] access to local variable s | Assert.cs:108:27:108:34 | [b (line 84): true] access to property Length | +| Assert.cs:108:27:108:34 | [b (line 84): false] access to property Length | Assert.cs:108:9:108:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:108:27:108:34 | [b (line 84): true] access to property Length | Assert.cs:108:9:108:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:110:9:110:25 | [b (line 84): false] ... = ... | Assert.cs:111:9:111:34 | [b (line 84): false] ...; | +| Assert.cs:110:9:110:25 | [b (line 84): true] ... = ... | Assert.cs:111:9:111:34 | [b (line 84): true] ...; | +| Assert.cs:110:9:110:26 | [b (line 84): false] ...; | Assert.cs:110:13:110:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:110:9:110:26 | [b (line 84): true] ...; | Assert.cs:110:13:110:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:110:13:110:13 | [b (line 84): false] access to parameter b | Assert.cs:110:24:110:25 | [b (line 84): false] "" | +| Assert.cs:110:13:110:13 | [b (line 84): true] access to parameter b | Assert.cs:110:17:110:20 | [b (line 84): true] null | +| Assert.cs:110:13:110:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:110:13:110:13 | [b (line 84): false] access to parameter b | +| Assert.cs:110:13:110:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:110:13:110:13 | [b (line 84): true] access to parameter b | +| Assert.cs:110:17:110:20 | [b (line 84): true] null | Assert.cs:110:9:110:25 | [b (line 84): true] ... = ... | +| Assert.cs:110:24:110:25 | [b (line 84): false] "" | Assert.cs:110:9:110:25 | [b (line 84): false] ... = ... | +| Assert.cs:111:9:111:33 | [b (line 84): false] call to method IsFalse | Assert.cs:112:9:112:36 | [b (line 84): false] ...; | +| Assert.cs:111:9:111:33 | [b (line 84): true] call to method IsFalse | Assert.cs:112:9:112:36 | [b (line 84): true] ...; | +| Assert.cs:111:9:111:34 | [b (line 84): false] ...; | Assert.cs:111:24:111:24 | [b (line 84): false] access to local variable s | +| Assert.cs:111:9:111:34 | [b (line 84): true] ...; | Assert.cs:111:24:111:24 | [b (line 84): true] access to local variable s | +| Assert.cs:111:24:111:24 | [b (line 84): false] access to local variable s | Assert.cs:111:29:111:32 | [b (line 84): false] null | +| Assert.cs:111:24:111:24 | [b (line 84): true] access to local variable s | Assert.cs:111:29:111:32 | [b (line 84): true] null | +| Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | Assert.cs:111:9:111:33 | [b (line 84): false] call to method IsFalse | +| Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | Assert.cs:111:9:111:33 | [b (line 84): true] call to method IsFalse | +| Assert.cs:111:29:111:32 | [b (line 84): false] null | Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | +| Assert.cs:111:29:111:32 | [b (line 84): true] null | Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | +| Assert.cs:112:9:112:35 | [b (line 84): false] call to method WriteLine | Assert.cs:114:9:114:26 | [b (line 84): false] ...; | +| Assert.cs:112:9:112:35 | [b (line 84): true] call to method WriteLine | Assert.cs:114:9:114:26 | [b (line 84): true] ...; | +| Assert.cs:112:9:112:36 | [b (line 84): false] ...; | Assert.cs:112:27:112:27 | [b (line 84): false] access to local variable s | +| Assert.cs:112:9:112:36 | [b (line 84): true] ...; | Assert.cs:112:27:112:27 | [b (line 84): true] access to local variable s | +| Assert.cs:112:27:112:27 | [b (line 84): false] access to local variable s | Assert.cs:112:27:112:34 | [b (line 84): false] access to property Length | +| Assert.cs:112:27:112:27 | [b (line 84): true] access to local variable s | Assert.cs:112:27:112:34 | [b (line 84): true] access to property Length | +| Assert.cs:112:27:112:34 | [b (line 84): false] access to property Length | Assert.cs:112:9:112:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:112:27:112:34 | [b (line 84): true] access to property Length | Assert.cs:112:9:112:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:114:9:114:25 | [b (line 84): false] ... = ... | Assert.cs:115:9:115:38 | [b (line 84): false] ...; | +| Assert.cs:114:9:114:25 | [b (line 84): true] ... = ... | Assert.cs:115:9:115:38 | [b (line 84): true] ...; | +| Assert.cs:114:9:114:26 | [b (line 84): false] ...; | Assert.cs:114:13:114:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:114:9:114:26 | [b (line 84): true] ...; | Assert.cs:114:13:114:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:114:13:114:13 | [b (line 84): false] access to parameter b | Assert.cs:114:24:114:25 | [b (line 84): false] "" | +| Assert.cs:114:13:114:13 | [b (line 84): true] access to parameter b | Assert.cs:114:17:114:20 | [b (line 84): true] null | +| Assert.cs:114:13:114:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:114:13:114:13 | [b (line 84): false] access to parameter b | +| Assert.cs:114:13:114:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:114:13:114:13 | [b (line 84): true] access to parameter b | +| Assert.cs:114:17:114:20 | [b (line 84): true] null | Assert.cs:114:9:114:25 | [b (line 84): true] ... = ... | +| Assert.cs:114:24:114:25 | [b (line 84): false] "" | Assert.cs:114:9:114:25 | [b (line 84): false] ... = ... | +| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:116:9:116:36 | [b (line 84): false] ...; | +| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:116:9:116:36 | [b (line 84): true] ...; | +| Assert.cs:115:9:115:38 | [b (line 84): false] ...; | Assert.cs:115:23:115:36 | [b (line 84): false] ... && ... | +| Assert.cs:115:9:115:38 | [b (line 84): true] ...; | Assert.cs:115:23:115:36 | [b (line 84): true] ... && ... | +| Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | Assert.cs:115:28:115:31 | [b (line 84): false] null | +| Assert.cs:115:23:115:23 | [b (line 84): true] access to local variable s | Assert.cs:115:28:115:31 | [b (line 84): true] null | +| Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:115:23:115:36 | [b (line 84): false] ... && ... | Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | +| Assert.cs:115:23:115:36 | [b (line 84): true] ... && ... | Assert.cs:115:23:115:23 | [b (line 84): true] access to local variable s | +| Assert.cs:115:28:115:31 | [b (line 84): false] null | Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | +| Assert.cs:115:28:115:31 | [b (line 84): true] null | Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | +| Assert.cs:116:9:116:35 | [b (line 84): false] call to method WriteLine | Assert.cs:118:9:118:26 | [b (line 84): false] ...; | +| Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | Assert.cs:118:9:118:26 | [b (line 84): true] ...; | +| Assert.cs:116:9:116:36 | [b (line 84): false] ...; | Assert.cs:116:27:116:27 | [b (line 84): false] access to local variable s | +| Assert.cs:116:9:116:36 | [b (line 84): true] ...; | Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | +| Assert.cs:116:27:116:27 | [b (line 84): false] access to local variable s | Assert.cs:116:27:116:34 | [b (line 84): false] access to property Length | +| Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | +| Assert.cs:116:27:116:34 | [b (line 84): false] access to property Length | Assert.cs:116:9:116:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:118:9:118:25 | [b (line 84): false] ... = ... | Assert.cs:119:9:119:40 | [b (line 84): false] ...; | +| Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | Assert.cs:119:9:119:40 | [b (line 84): true] ...; | +| Assert.cs:118:9:118:26 | [b (line 84): false] ...; | Assert.cs:118:13:118:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:118:9:118:26 | [b (line 84): true] ...; | Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | Assert.cs:118:24:118:25 | [b (line 84): false] "" | +| Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | Assert.cs:118:17:118:20 | [b (line 84): true] null | +| Assert.cs:118:13:118:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | +| Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | +| Assert.cs:118:17:118:20 | [b (line 84): true] null | Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | +| Assert.cs:118:24:118:25 | [b (line 84): false] "" | Assert.cs:118:9:118:25 | [b (line 84): false] ... = ... | +| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:120:9:120:36 | [b (line 84): false] ...; | +| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:120:9:120:36 | [b (line 84): true] ...; | +| Assert.cs:119:9:119:40 | [b (line 84): false] ...; | Assert.cs:119:24:119:38 | [b (line 84): false] ... \|\| ... | +| Assert.cs:119:9:119:40 | [b (line 84): true] ...; | Assert.cs:119:24:119:38 | [b (line 84): true] ... \|\| ... | +| Assert.cs:119:24:119:24 | [b (line 84): false] access to local variable s | Assert.cs:119:29:119:32 | [b (line 84): false] null | +| Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | Assert.cs:119:29:119:32 | [b (line 84): true] null | +| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | +| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | Assert.cs:119:37:119:38 | [b (line 84): false] !... | +| Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | +| Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:119:24:119:38 | [b (line 84): false] ... \|\| ... | Assert.cs:119:24:119:24 | [b (line 84): false] access to local variable s | +| Assert.cs:119:24:119:38 | [b (line 84): true] ... \|\| ... | Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | +| Assert.cs:119:29:119:32 | [b (line 84): false] null | Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | +| Assert.cs:119:29:119:32 | [b (line 84): true] null | Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | +| Assert.cs:119:37:119:38 | [b (line 84): false] !... | Assert.cs:119:38:119:38 | [b (line 84): false] access to parameter b | +| Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | +| Assert.cs:120:9:120:35 | [b (line 84): false] call to method WriteLine | Assert.cs:122:9:122:26 | [b (line 84): false] ...; | +| Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | Assert.cs:122:9:122:26 | [b (line 84): true] ...; | +| Assert.cs:120:9:120:36 | [b (line 84): false] ...; | Assert.cs:120:27:120:27 | [b (line 84): false] access to local variable s | +| Assert.cs:120:9:120:36 | [b (line 84): true] ...; | Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | +| Assert.cs:120:27:120:27 | [b (line 84): false] access to local variable s | Assert.cs:120:27:120:34 | [b (line 84): false] access to property Length | +| Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | +| Assert.cs:120:27:120:34 | [b (line 84): false] access to property Length | Assert.cs:120:9:120:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:122:9:122:25 | [b (line 84): false] ... = ... | Assert.cs:123:9:123:38 | [b (line 84): false] ...; | +| Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | Assert.cs:123:9:123:38 | [b (line 84): true] ...; | +| Assert.cs:122:9:122:26 | [b (line 84): false] ...; | Assert.cs:122:13:122:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:122:9:122:26 | [b (line 84): true] ...; | Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | Assert.cs:122:24:122:25 | [b (line 84): false] "" | +| Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | Assert.cs:122:17:122:20 | [b (line 84): true] null | +| Assert.cs:122:13:122:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | +| Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | +| Assert.cs:122:17:122:20 | [b (line 84): true] null | Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | +| Assert.cs:122:24:122:25 | [b (line 84): false] "" | Assert.cs:122:9:122:25 | [b (line 84): false] ... = ... | +| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:124:9:124:36 | [b (line 84): false] ...; | +| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:124:9:124:36 | [b (line 84): true] ...; | +| Assert.cs:123:9:123:38 | [b (line 84): false] ...; | Assert.cs:123:23:123:36 | [b (line 84): false] ... && ... | +| Assert.cs:123:9:123:38 | [b (line 84): true] ...; | Assert.cs:123:23:123:36 | [b (line 84): true] ... && ... | +| Assert.cs:123:23:123:23 | [b (line 84): false] access to local variable s | Assert.cs:123:28:123:31 | [b (line 84): false] null | +| Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | Assert.cs:123:28:123:31 | [b (line 84): true] null | +| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | +| Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:123:23:123:36 | [b (line 84): false] ... && ... | Assert.cs:123:23:123:23 | [b (line 84): false] access to local variable s | +| Assert.cs:123:23:123:36 | [b (line 84): true] ... && ... | Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | +| Assert.cs:123:28:123:31 | [b (line 84): false] null | Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | +| Assert.cs:123:28:123:31 | [b (line 84): true] null | Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | +| Assert.cs:124:9:124:35 | [b (line 84): false] call to method WriteLine | Assert.cs:126:9:126:26 | [b (line 84): false] ...; | +| Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | Assert.cs:126:9:126:26 | [b (line 84): true] ...; | +| Assert.cs:124:9:124:36 | [b (line 84): false] ...; | Assert.cs:124:27:124:27 | [b (line 84): false] access to local variable s | +| Assert.cs:124:9:124:36 | [b (line 84): true] ...; | Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | +| Assert.cs:124:27:124:27 | [b (line 84): false] access to local variable s | Assert.cs:124:27:124:34 | [b (line 84): false] access to property Length | +| Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | +| Assert.cs:124:27:124:34 | [b (line 84): false] access to property Length | Assert.cs:124:9:124:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:127:9:127:40 | ...; | +| Assert.cs:126:9:126:26 | [b (line 84): false] ...; | Assert.cs:126:13:126:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:126:9:126:26 | [b (line 84): true] ...; | Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | Assert.cs:126:24:126:25 | "" | +| Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | Assert.cs:126:17:126:20 | null | +| Assert.cs:126:13:126:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | +| Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:128:9:128:36 | ...; | +| Assert.cs:127:9:127:40 | ...; | Assert.cs:127:24:127:38 | ... \|\| ... | +| Assert.cs:127:24:127:24 | access to local variable s | Assert.cs:127:29:127:32 | null | +| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:9:127:39 | call to method IsFalse | +| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:37:127:38 | !... | +| Assert.cs:127:24:127:38 | ... \|\| ... | Assert.cs:127:24:127:24 | access to local variable s | +| Assert.cs:127:29:127:32 | null | Assert.cs:127:24:127:32 | ... != ... | +| Assert.cs:127:37:127:38 | !... | Assert.cs:127:38:127:38 | access to parameter b | +| Assert.cs:128:9:128:35 | call to method WriteLine | Assert.cs:84:10:84:12 | exit M12 | +| Assert.cs:128:9:128:36 | ...; | Assert.cs:128:27:128:27 | access to local variable s | +| Assert.cs:128:27:128:27 | access to local variable s | Assert.cs:128:27:128:34 | access to property Length | +| Assert.cs:128:27:128:34 | access to property Length | Assert.cs:128:9:128:35 | call to method WriteLine | | Assignments.cs:3:10:3:10 | enter M | Assignments.cs:4:5:15:5 | {...} | | Assignments.cs:4:5:15:5 | {...} | Assignments.cs:5:9:5:18 | ... ...; | | Assignments.cs:5:9:5:18 | ... ...; | Assignments.cs:5:17:5:17 | 0 | @@ -3516,6 +4001,491 @@ postDominance | ArrayCreation.cs:9:43:9:50 | { ..., ... } | ArrayCreation.cs:9:48:9:48 | 3 | | ArrayCreation.cs:9:45:9:45 | 2 | ArrayCreation.cs:9:33:9:40 | { ..., ... } | | ArrayCreation.cs:9:48:9:48 | 3 | ArrayCreation.cs:9:45:9:45 | 2 | +| Assert.cs:7:10:7:11 | exit M1 | Assert.cs:11:9:11:35 | call to method WriteLine | +| Assert.cs:8:5:12:5 | {...} | Assert.cs:7:10:7:11 | enter M1 | +| Assert.cs:9:9:9:33 | ... ...; | Assert.cs:8:5:12:5 | {...} | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:9:24:9:27 | null | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:9:31:9:32 | "" | +| Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:9:20:9:32 | ... ? ... : ... | +| Assert.cs:9:20:9:32 | ... ? ... : ... | Assert.cs:9:9:9:33 | ... ...; | +| Assert.cs:10:9:10:31 | call to method Assert | Assert.cs:10:22:10:30 | ... != ... | +| Assert.cs:10:9:10:32 | ...; | Assert.cs:9:16:9:32 | String s = ... | +| Assert.cs:10:22:10:22 | access to local variable s | Assert.cs:10:9:10:32 | ...; | +| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:27:10:30 | null | +| Assert.cs:10:27:10:30 | null | Assert.cs:10:22:10:22 | access to local variable s | +| Assert.cs:11:9:11:35 | call to method WriteLine | Assert.cs:11:27:11:34 | access to property Length | +| Assert.cs:11:9:11:36 | ...; | Assert.cs:10:9:10:31 | call to method Assert | +| Assert.cs:11:27:11:27 | access to local variable s | Assert.cs:11:9:11:36 | ...; | +| Assert.cs:11:27:11:34 | access to property Length | Assert.cs:11:27:11:27 | access to local variable s | +| Assert.cs:14:10:14:11 | exit M2 | Assert.cs:18:9:18:35 | call to method WriteLine | +| Assert.cs:15:5:19:5 | {...} | Assert.cs:14:10:14:11 | enter M2 | +| Assert.cs:16:9:16:33 | ... ...; | Assert.cs:15:5:19:5 | {...} | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:16:24:16:27 | null | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:16:31:16:32 | "" | +| Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:16:20:16:32 | ... ? ... : ... | +| Assert.cs:16:20:16:32 | ... ? ... : ... | Assert.cs:16:9:16:33 | ... ...; | +| Assert.cs:17:9:17:24 | call to method IsNull | Assert.cs:17:23:17:23 | access to local variable s | +| Assert.cs:17:9:17:25 | ...; | Assert.cs:16:16:16:32 | String s = ... | +| Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:17:9:17:25 | ...; | +| Assert.cs:18:9:18:35 | call to method WriteLine | Assert.cs:18:27:18:34 | access to property Length | +| Assert.cs:18:9:18:36 | ...; | Assert.cs:17:9:17:24 | call to method IsNull | +| Assert.cs:18:27:18:27 | access to local variable s | Assert.cs:18:9:18:36 | ...; | +| Assert.cs:18:27:18:34 | access to property Length | Assert.cs:18:27:18:27 | access to local variable s | +| Assert.cs:21:10:21:11 | exit M3 | Assert.cs:25:9:25:35 | call to method WriteLine | +| Assert.cs:22:5:26:5 | {...} | Assert.cs:21:10:21:11 | enter M3 | +| Assert.cs:23:9:23:33 | ... ...; | Assert.cs:22:5:26:5 | {...} | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:23:24:23:27 | null | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:23:31:23:32 | "" | +| Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:23:20:23:32 | ... ? ... : ... | +| Assert.cs:23:20:23:32 | ... ? ... : ... | Assert.cs:23:9:23:33 | ... ...; | +| Assert.cs:24:9:24:27 | call to method IsNotNull | Assert.cs:24:26:24:26 | access to local variable s | +| Assert.cs:24:9:24:28 | ...; | Assert.cs:23:16:23:32 | String s = ... | +| Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:24:9:24:28 | ...; | +| Assert.cs:25:9:25:35 | call to method WriteLine | Assert.cs:25:27:25:34 | access to property Length | +| Assert.cs:25:9:25:36 | ...; | Assert.cs:24:9:24:27 | call to method IsNotNull | +| Assert.cs:25:27:25:27 | access to local variable s | Assert.cs:25:9:25:36 | ...; | +| Assert.cs:25:27:25:34 | access to property Length | Assert.cs:25:27:25:27 | access to local variable s | +| Assert.cs:28:10:28:11 | exit M4 | Assert.cs:32:9:32:35 | call to method WriteLine | +| Assert.cs:29:5:33:5 | {...} | Assert.cs:28:10:28:11 | enter M4 | +| Assert.cs:30:9:30:33 | ... ...; | Assert.cs:29:5:33:5 | {...} | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:30:24:30:27 | null | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:30:31:30:32 | "" | +| Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:30:20:30:32 | ... ? ... : ... | +| Assert.cs:30:20:30:32 | ... ? ... : ... | Assert.cs:30:9:30:33 | ... ...; | +| Assert.cs:31:9:31:32 | call to method IsTrue | Assert.cs:31:23:31:31 | ... == ... | +| Assert.cs:31:9:31:33 | ...; | Assert.cs:30:16:30:32 | String s = ... | +| Assert.cs:31:23:31:23 | access to local variable s | Assert.cs:31:9:31:33 | ...; | +| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:28:31:31 | null | +| Assert.cs:31:28:31:31 | null | Assert.cs:31:23:31:23 | access to local variable s | +| Assert.cs:32:9:32:35 | call to method WriteLine | Assert.cs:32:27:32:34 | access to property Length | +| Assert.cs:32:9:32:36 | ...; | Assert.cs:31:9:31:32 | call to method IsTrue | +| Assert.cs:32:27:32:27 | access to local variable s | Assert.cs:32:9:32:36 | ...; | +| Assert.cs:32:27:32:34 | access to property Length | Assert.cs:32:27:32:27 | access to local variable s | +| Assert.cs:35:10:35:11 | exit M5 | Assert.cs:39:9:39:35 | call to method WriteLine | +| Assert.cs:36:5:40:5 | {...} | Assert.cs:35:10:35:11 | enter M5 | +| Assert.cs:37:9:37:33 | ... ...; | Assert.cs:36:5:40:5 | {...} | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:37:24:37:27 | null | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:37:31:37:32 | "" | +| Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:37:20:37:32 | ... ? ... : ... | +| Assert.cs:37:20:37:32 | ... ? ... : ... | Assert.cs:37:9:37:33 | ... ...; | +| Assert.cs:38:9:38:32 | call to method IsTrue | Assert.cs:38:23:38:31 | ... != ... | +| Assert.cs:38:9:38:33 | ...; | Assert.cs:37:16:37:32 | String s = ... | +| Assert.cs:38:23:38:23 | access to local variable s | Assert.cs:38:9:38:33 | ...; | +| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:28:38:31 | null | +| Assert.cs:38:28:38:31 | null | Assert.cs:38:23:38:23 | access to local variable s | +| Assert.cs:39:9:39:35 | call to method WriteLine | Assert.cs:39:27:39:34 | access to property Length | +| Assert.cs:39:9:39:36 | ...; | Assert.cs:38:9:38:32 | call to method IsTrue | +| Assert.cs:39:27:39:27 | access to local variable s | Assert.cs:39:9:39:36 | ...; | +| Assert.cs:39:27:39:34 | access to property Length | Assert.cs:39:27:39:27 | access to local variable s | +| Assert.cs:42:10:42:11 | exit M6 | Assert.cs:46:9:46:35 | call to method WriteLine | +| Assert.cs:43:5:47:5 | {...} | Assert.cs:42:10:42:11 | enter M6 | +| Assert.cs:44:9:44:33 | ... ...; | Assert.cs:43:5:47:5 | {...} | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:44:24:44:27 | null | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:44:31:44:32 | "" | +| Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:44:20:44:32 | ... ? ... : ... | +| Assert.cs:44:20:44:32 | ... ? ... : ... | Assert.cs:44:9:44:33 | ... ...; | +| Assert.cs:45:9:45:33 | call to method IsFalse | Assert.cs:45:24:45:32 | ... != ... | +| Assert.cs:45:9:45:34 | ...; | Assert.cs:44:16:44:32 | String s = ... | +| Assert.cs:45:24:45:24 | access to local variable s | Assert.cs:45:9:45:34 | ...; | +| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:29:45:32 | null | +| Assert.cs:45:29:45:32 | null | Assert.cs:45:24:45:24 | access to local variable s | +| Assert.cs:46:9:46:35 | call to method WriteLine | Assert.cs:46:27:46:34 | access to property Length | +| Assert.cs:46:9:46:36 | ...; | Assert.cs:45:9:45:33 | call to method IsFalse | +| Assert.cs:46:27:46:27 | access to local variable s | Assert.cs:46:9:46:36 | ...; | +| Assert.cs:46:27:46:34 | access to property Length | Assert.cs:46:27:46:27 | access to local variable s | +| Assert.cs:49:10:49:11 | exit M7 | Assert.cs:53:9:53:35 | call to method WriteLine | +| Assert.cs:50:5:54:5 | {...} | Assert.cs:49:10:49:11 | enter M7 | +| Assert.cs:51:9:51:33 | ... ...; | Assert.cs:50:5:54:5 | {...} | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:51:24:51:27 | null | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:51:31:51:32 | "" | +| Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:51:20:51:32 | ... ? ... : ... | +| Assert.cs:51:20:51:32 | ... ? ... : ... | Assert.cs:51:9:51:33 | ... ...; | +| Assert.cs:52:9:52:33 | call to method IsFalse | Assert.cs:52:24:52:32 | ... == ... | +| Assert.cs:52:9:52:34 | ...; | Assert.cs:51:16:51:32 | String s = ... | +| Assert.cs:52:24:52:24 | access to local variable s | Assert.cs:52:9:52:34 | ...; | +| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:29:52:32 | null | +| Assert.cs:52:29:52:32 | null | Assert.cs:52:24:52:24 | access to local variable s | +| Assert.cs:53:9:53:35 | call to method WriteLine | Assert.cs:53:27:53:34 | access to property Length | +| Assert.cs:53:9:53:36 | ...; | Assert.cs:52:9:52:33 | call to method IsFalse | +| Assert.cs:53:27:53:27 | access to local variable s | Assert.cs:53:9:53:36 | ...; | +| Assert.cs:53:27:53:34 | access to property Length | Assert.cs:53:27:53:27 | access to local variable s | +| Assert.cs:56:10:56:11 | exit M8 | Assert.cs:60:9:60:35 | call to method WriteLine | +| Assert.cs:57:5:61:5 | {...} | Assert.cs:56:10:56:11 | enter M8 | +| Assert.cs:58:9:58:33 | ... ...; | Assert.cs:57:5:61:5 | {...} | +| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:58:24:58:27 | null | +| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:58:31:58:32 | "" | +| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:20:58:32 | ... ? ... : ... | +| Assert.cs:58:20:58:32 | ... ? ... : ... | Assert.cs:58:9:58:33 | ... ...; | +| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:59:23:59:31 | ... != ... | +| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:59:36:59:36 | access to parameter b | +| Assert.cs:59:9:59:38 | ...; | Assert.cs:58:16:58:32 | String s = ... | +| Assert.cs:59:23:59:23 | access to local variable s | Assert.cs:59:23:59:36 | ... && ... | +| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:28:59:31 | null | +| Assert.cs:59:23:59:36 | ... && ... | Assert.cs:59:9:59:38 | ...; | +| Assert.cs:59:28:59:31 | null | Assert.cs:59:23:59:23 | access to local variable s | +| Assert.cs:60:9:60:35 | call to method WriteLine | Assert.cs:60:27:60:34 | access to property Length | +| Assert.cs:60:9:60:36 | ...; | Assert.cs:59:9:59:37 | call to method IsTrue | +| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:60:9:60:36 | ...; | +| Assert.cs:60:27:60:34 | access to property Length | Assert.cs:60:27:60:27 | access to local variable s | +| Assert.cs:63:10:63:11 | exit M9 | Assert.cs:67:9:67:35 | call to method WriteLine | +| Assert.cs:64:5:68:5 | {...} | Assert.cs:63:10:63:11 | enter M9 | +| Assert.cs:65:9:65:33 | ... ...; | Assert.cs:64:5:68:5 | {...} | +| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:65:24:65:27 | null | +| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:65:31:65:32 | "" | +| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:20:65:32 | ... ? ... : ... | +| Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:65:9:65:33 | ... ...; | +| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:66:24:66:32 | ... == ... | +| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:66:37:66:37 | access to parameter b | +| Assert.cs:66:9:66:39 | ...; | Assert.cs:65:16:65:32 | String s = ... | +| Assert.cs:66:24:66:24 | access to local variable s | Assert.cs:66:24:66:37 | ... \|\| ... | +| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:29:66:32 | null | +| Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:66:9:66:39 | ...; | +| Assert.cs:66:29:66:32 | null | Assert.cs:66:24:66:24 | access to local variable s | +| Assert.cs:67:9:67:35 | call to method WriteLine | Assert.cs:67:27:67:34 | access to property Length | +| Assert.cs:67:9:67:36 | ...; | Assert.cs:66:9:66:38 | call to method IsFalse | +| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:67:9:67:36 | ...; | +| Assert.cs:67:27:67:34 | access to property Length | Assert.cs:67:27:67:27 | access to local variable s | +| Assert.cs:70:10:70:12 | exit M10 | Assert.cs:74:9:74:35 | call to method WriteLine | +| Assert.cs:71:5:75:5 | {...} | Assert.cs:70:10:70:12 | enter M10 | +| Assert.cs:72:9:72:33 | ... ...; | Assert.cs:71:5:75:5 | {...} | +| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:72:24:72:27 | null | +| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:72:31:72:32 | "" | +| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:20:72:32 | ... ? ... : ... | +| Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:72:9:72:33 | ... ...; | +| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:73:23:73:31 | ... == ... | +| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:73:36:73:36 | access to parameter b | +| Assert.cs:73:9:73:38 | ...; | Assert.cs:72:16:72:32 | String s = ... | +| Assert.cs:73:23:73:23 | access to local variable s | Assert.cs:73:23:73:36 | ... && ... | +| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:28:73:31 | null | +| Assert.cs:73:23:73:36 | ... && ... | Assert.cs:73:9:73:38 | ...; | +| Assert.cs:73:28:73:31 | null | Assert.cs:73:23:73:23 | access to local variable s | +| Assert.cs:74:9:74:35 | call to method WriteLine | Assert.cs:74:27:74:34 | access to property Length | +| Assert.cs:74:9:74:36 | ...; | Assert.cs:73:9:73:37 | call to method IsTrue | +| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:74:9:74:36 | ...; | +| Assert.cs:74:27:74:34 | access to property Length | Assert.cs:74:27:74:27 | access to local variable s | +| Assert.cs:77:10:77:12 | exit M11 | Assert.cs:81:9:81:35 | call to method WriteLine | +| Assert.cs:78:5:82:5 | {...} | Assert.cs:77:10:77:12 | enter M11 | +| Assert.cs:79:9:79:33 | ... ...; | Assert.cs:78:5:82:5 | {...} | +| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:79:24:79:27 | null | +| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:79:31:79:32 | "" | +| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:32 | ... ? ... : ... | +| Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:79:9:79:33 | ... ...; | +| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:80:24:80:32 | ... != ... | +| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:80:37:80:37 | access to parameter b | +| Assert.cs:80:9:80:39 | ...; | Assert.cs:79:16:79:32 | String s = ... | +| Assert.cs:80:24:80:24 | access to local variable s | Assert.cs:80:24:80:37 | ... \|\| ... | +| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:29:80:32 | null | +| Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:9:80:39 | ...; | +| Assert.cs:80:29:80:32 | null | Assert.cs:80:24:80:24 | access to local variable s | +| Assert.cs:81:9:81:35 | call to method WriteLine | Assert.cs:81:27:81:34 | access to property Length | +| Assert.cs:81:9:81:36 | ...; | Assert.cs:80:9:80:38 | call to method IsFalse | +| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:81:9:81:36 | ...; | +| Assert.cs:81:27:81:34 | access to property Length | Assert.cs:81:27:81:27 | access to local variable s | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:128:9:128:35 | call to method WriteLine | +| Assert.cs:85:5:129:5 | {...} | Assert.cs:84:10:84:12 | enter M12 | +| Assert.cs:86:9:86:33 | ... ...; | Assert.cs:85:5:129:5 | {...} | +| Assert.cs:86:16:86:32 | [b (line 84): false] String s = ... | Assert.cs:86:31:86:32 | [b (line 84): false] "" | +| Assert.cs:86:16:86:32 | [b (line 84): true] String s = ... | Assert.cs:86:24:86:27 | [b (line 84): true] null | +| Assert.cs:86:20:86:20 | access to parameter b | Assert.cs:86:20:86:32 | ... ? ... : ... | +| Assert.cs:86:20:86:32 | ... ? ... : ... | Assert.cs:86:9:86:33 | ... ...; | +| Assert.cs:87:9:87:31 | [b (line 84): false] call to method Assert | Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | +| Assert.cs:87:9:87:31 | [b (line 84): true] call to method Assert | Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | +| Assert.cs:87:9:87:32 | [b (line 84): false] ...; | Assert.cs:86:16:86:32 | [b (line 84): false] String s = ... | +| Assert.cs:87:9:87:32 | [b (line 84): true] ...; | Assert.cs:86:16:86:32 | [b (line 84): true] String s = ... | +| Assert.cs:87:22:87:22 | [b (line 84): false] access to local variable s | Assert.cs:87:9:87:32 | [b (line 84): false] ...; | +| Assert.cs:87:22:87:22 | [b (line 84): true] access to local variable s | Assert.cs:87:9:87:32 | [b (line 84): true] ...; | +| Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | Assert.cs:87:27:87:30 | [b (line 84): false] null | +| Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | Assert.cs:87:27:87:30 | [b (line 84): true] null | +| Assert.cs:87:27:87:30 | [b (line 84): false] null | Assert.cs:87:22:87:22 | [b (line 84): false] access to local variable s | +| Assert.cs:87:27:87:30 | [b (line 84): true] null | Assert.cs:87:22:87:22 | [b (line 84): true] access to local variable s | +| Assert.cs:88:9:88:35 | [b (line 84): false] call to method WriteLine | Assert.cs:88:27:88:34 | [b (line 84): false] access to property Length | +| Assert.cs:88:9:88:35 | [b (line 84): true] call to method WriteLine | Assert.cs:88:27:88:34 | [b (line 84): true] access to property Length | +| Assert.cs:88:9:88:36 | [b (line 84): false] ...; | Assert.cs:87:9:87:31 | [b (line 84): false] call to method Assert | +| Assert.cs:88:9:88:36 | [b (line 84): true] ...; | Assert.cs:87:9:87:31 | [b (line 84): true] call to method Assert | +| Assert.cs:88:27:88:27 | [b (line 84): false] access to local variable s | Assert.cs:88:9:88:36 | [b (line 84): false] ...; | +| Assert.cs:88:27:88:27 | [b (line 84): true] access to local variable s | Assert.cs:88:9:88:36 | [b (line 84): true] ...; | +| Assert.cs:88:27:88:34 | [b (line 84): false] access to property Length | Assert.cs:88:27:88:27 | [b (line 84): false] access to local variable s | +| Assert.cs:88:27:88:34 | [b (line 84): true] access to property Length | Assert.cs:88:27:88:27 | [b (line 84): true] access to local variable s | +| Assert.cs:90:9:90:25 | [b (line 84): false] ... = ... | Assert.cs:90:24:90:25 | [b (line 84): false] "" | +| Assert.cs:90:9:90:25 | [b (line 84): true] ... = ... | Assert.cs:90:17:90:20 | [b (line 84): true] null | +| Assert.cs:90:9:90:26 | [b (line 84): false] ...; | Assert.cs:88:9:88:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:90:9:90:26 | [b (line 84): true] ...; | Assert.cs:88:9:88:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:90:13:90:13 | [b (line 84): false] access to parameter b | Assert.cs:90:13:90:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:90:13:90:13 | [b (line 84): true] access to parameter b | Assert.cs:90:13:90:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:90:13:90:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:90:9:90:26 | [b (line 84): false] ...; | +| Assert.cs:90:13:90:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:90:9:90:26 | [b (line 84): true] ...; | +| Assert.cs:90:17:90:20 | [b (line 84): true] null | Assert.cs:90:13:90:13 | [b (line 84): true] access to parameter b | +| Assert.cs:90:24:90:25 | [b (line 84): false] "" | Assert.cs:90:13:90:13 | [b (line 84): false] access to parameter b | +| Assert.cs:91:9:91:24 | [b (line 84): false] call to method IsNull | Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | +| Assert.cs:91:9:91:24 | [b (line 84): true] call to method IsNull | Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | +| Assert.cs:91:9:91:25 | [b (line 84): false] ...; | Assert.cs:90:9:90:25 | [b (line 84): false] ... = ... | +| Assert.cs:91:9:91:25 | [b (line 84): true] ...; | Assert.cs:90:9:90:25 | [b (line 84): true] ... = ... | +| Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | Assert.cs:91:9:91:25 | [b (line 84): false] ...; | +| Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | Assert.cs:91:9:91:25 | [b (line 84): true] ...; | +| Assert.cs:92:9:92:35 | [b (line 84): false] call to method WriteLine | Assert.cs:92:27:92:34 | [b (line 84): false] access to property Length | +| Assert.cs:92:9:92:35 | [b (line 84): true] call to method WriteLine | Assert.cs:92:27:92:34 | [b (line 84): true] access to property Length | +| Assert.cs:92:9:92:36 | [b (line 84): false] ...; | Assert.cs:91:9:91:24 | [b (line 84): false] call to method IsNull | +| Assert.cs:92:9:92:36 | [b (line 84): true] ...; | Assert.cs:91:9:91:24 | [b (line 84): true] call to method IsNull | +| Assert.cs:92:27:92:27 | [b (line 84): false] access to local variable s | Assert.cs:92:9:92:36 | [b (line 84): false] ...; | +| Assert.cs:92:27:92:27 | [b (line 84): true] access to local variable s | Assert.cs:92:9:92:36 | [b (line 84): true] ...; | +| Assert.cs:92:27:92:34 | [b (line 84): false] access to property Length | Assert.cs:92:27:92:27 | [b (line 84): false] access to local variable s | +| Assert.cs:92:27:92:34 | [b (line 84): true] access to property Length | Assert.cs:92:27:92:27 | [b (line 84): true] access to local variable s | +| Assert.cs:94:9:94:25 | [b (line 84): false] ... = ... | Assert.cs:94:24:94:25 | [b (line 84): false] "" | +| Assert.cs:94:9:94:25 | [b (line 84): true] ... = ... | Assert.cs:94:17:94:20 | [b (line 84): true] null | +| Assert.cs:94:9:94:26 | [b (line 84): false] ...; | Assert.cs:92:9:92:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:94:9:94:26 | [b (line 84): true] ...; | Assert.cs:92:9:92:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:94:13:94:13 | [b (line 84): false] access to parameter b | Assert.cs:94:13:94:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:94:13:94:13 | [b (line 84): true] access to parameter b | Assert.cs:94:13:94:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:94:13:94:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:94:9:94:26 | [b (line 84): false] ...; | +| Assert.cs:94:13:94:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:94:9:94:26 | [b (line 84): true] ...; | +| Assert.cs:94:17:94:20 | [b (line 84): true] null | Assert.cs:94:13:94:13 | [b (line 84): true] access to parameter b | +| Assert.cs:94:24:94:25 | [b (line 84): false] "" | Assert.cs:94:13:94:13 | [b (line 84): false] access to parameter b | +| Assert.cs:95:9:95:27 | [b (line 84): false] call to method IsNotNull | Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | +| Assert.cs:95:9:95:27 | [b (line 84): true] call to method IsNotNull | Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | +| Assert.cs:95:9:95:28 | [b (line 84): false] ...; | Assert.cs:94:9:94:25 | [b (line 84): false] ... = ... | +| Assert.cs:95:9:95:28 | [b (line 84): true] ...; | Assert.cs:94:9:94:25 | [b (line 84): true] ... = ... | +| Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | Assert.cs:95:9:95:28 | [b (line 84): false] ...; | +| Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | Assert.cs:95:9:95:28 | [b (line 84): true] ...; | +| Assert.cs:96:9:96:35 | [b (line 84): false] call to method WriteLine | Assert.cs:96:27:96:34 | [b (line 84): false] access to property Length | +| Assert.cs:96:9:96:35 | [b (line 84): true] call to method WriteLine | Assert.cs:96:27:96:34 | [b (line 84): true] access to property Length | +| Assert.cs:96:9:96:36 | [b (line 84): false] ...; | Assert.cs:95:9:95:27 | [b (line 84): false] call to method IsNotNull | +| Assert.cs:96:9:96:36 | [b (line 84): true] ...; | Assert.cs:95:9:95:27 | [b (line 84): true] call to method IsNotNull | +| Assert.cs:96:27:96:27 | [b (line 84): false] access to local variable s | Assert.cs:96:9:96:36 | [b (line 84): false] ...; | +| Assert.cs:96:27:96:27 | [b (line 84): true] access to local variable s | Assert.cs:96:9:96:36 | [b (line 84): true] ...; | +| Assert.cs:96:27:96:34 | [b (line 84): false] access to property Length | Assert.cs:96:27:96:27 | [b (line 84): false] access to local variable s | +| Assert.cs:96:27:96:34 | [b (line 84): true] access to property Length | Assert.cs:96:27:96:27 | [b (line 84): true] access to local variable s | +| Assert.cs:98:9:98:25 | [b (line 84): false] ... = ... | Assert.cs:98:24:98:25 | [b (line 84): false] "" | +| Assert.cs:98:9:98:25 | [b (line 84): true] ... = ... | Assert.cs:98:17:98:20 | [b (line 84): true] null | +| Assert.cs:98:9:98:26 | [b (line 84): false] ...; | Assert.cs:96:9:96:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:98:9:98:26 | [b (line 84): true] ...; | Assert.cs:96:9:96:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:98:13:98:13 | [b (line 84): false] access to parameter b | Assert.cs:98:13:98:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:98:13:98:13 | [b (line 84): true] access to parameter b | Assert.cs:98:13:98:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:98:13:98:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:98:9:98:26 | [b (line 84): false] ...; | +| Assert.cs:98:13:98:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:98:9:98:26 | [b (line 84): true] ...; | +| Assert.cs:98:17:98:20 | [b (line 84): true] null | Assert.cs:98:13:98:13 | [b (line 84): true] access to parameter b | +| Assert.cs:98:24:98:25 | [b (line 84): false] "" | Assert.cs:98:13:98:13 | [b (line 84): false] access to parameter b | +| Assert.cs:99:9:99:32 | [b (line 84): false] call to method IsTrue | Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | +| Assert.cs:99:9:99:32 | [b (line 84): true] call to method IsTrue | Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | +| Assert.cs:99:9:99:33 | [b (line 84): false] ...; | Assert.cs:98:9:98:25 | [b (line 84): false] ... = ... | +| Assert.cs:99:9:99:33 | [b (line 84): true] ...; | Assert.cs:98:9:98:25 | [b (line 84): true] ... = ... | +| Assert.cs:99:23:99:23 | [b (line 84): false] access to local variable s | Assert.cs:99:9:99:33 | [b (line 84): false] ...; | +| Assert.cs:99:23:99:23 | [b (line 84): true] access to local variable s | Assert.cs:99:9:99:33 | [b (line 84): true] ...; | +| Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | Assert.cs:99:28:99:31 | [b (line 84): false] null | +| Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | Assert.cs:99:28:99:31 | [b (line 84): true] null | +| Assert.cs:99:28:99:31 | [b (line 84): false] null | Assert.cs:99:23:99:23 | [b (line 84): false] access to local variable s | +| Assert.cs:99:28:99:31 | [b (line 84): true] null | Assert.cs:99:23:99:23 | [b (line 84): true] access to local variable s | +| Assert.cs:100:9:100:35 | [b (line 84): false] call to method WriteLine | Assert.cs:100:27:100:34 | [b (line 84): false] access to property Length | +| Assert.cs:100:9:100:35 | [b (line 84): true] call to method WriteLine | Assert.cs:100:27:100:34 | [b (line 84): true] access to property Length | +| Assert.cs:100:9:100:36 | [b (line 84): false] ...; | Assert.cs:99:9:99:32 | [b (line 84): false] call to method IsTrue | +| Assert.cs:100:9:100:36 | [b (line 84): true] ...; | Assert.cs:99:9:99:32 | [b (line 84): true] call to method IsTrue | +| Assert.cs:100:27:100:27 | [b (line 84): false] access to local variable s | Assert.cs:100:9:100:36 | [b (line 84): false] ...; | +| Assert.cs:100:27:100:27 | [b (line 84): true] access to local variable s | Assert.cs:100:9:100:36 | [b (line 84): true] ...; | +| Assert.cs:100:27:100:34 | [b (line 84): false] access to property Length | Assert.cs:100:27:100:27 | [b (line 84): false] access to local variable s | +| Assert.cs:100:27:100:34 | [b (line 84): true] access to property Length | Assert.cs:100:27:100:27 | [b (line 84): true] access to local variable s | +| Assert.cs:102:9:102:25 | [b (line 84): false] ... = ... | Assert.cs:102:24:102:25 | [b (line 84): false] "" | +| Assert.cs:102:9:102:25 | [b (line 84): true] ... = ... | Assert.cs:102:17:102:20 | [b (line 84): true] null | +| Assert.cs:102:9:102:26 | [b (line 84): false] ...; | Assert.cs:100:9:100:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:102:9:102:26 | [b (line 84): true] ...; | Assert.cs:100:9:100:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:102:13:102:13 | [b (line 84): false] access to parameter b | Assert.cs:102:13:102:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:102:13:102:13 | [b (line 84): true] access to parameter b | Assert.cs:102:13:102:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:102:13:102:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:102:9:102:26 | [b (line 84): false] ...; | +| Assert.cs:102:13:102:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:102:9:102:26 | [b (line 84): true] ...; | +| Assert.cs:102:17:102:20 | [b (line 84): true] null | Assert.cs:102:13:102:13 | [b (line 84): true] access to parameter b | +| Assert.cs:102:24:102:25 | [b (line 84): false] "" | Assert.cs:102:13:102:13 | [b (line 84): false] access to parameter b | +| Assert.cs:103:9:103:32 | [b (line 84): false] call to method IsTrue | Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | +| Assert.cs:103:9:103:32 | [b (line 84): true] call to method IsTrue | Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | +| Assert.cs:103:9:103:33 | [b (line 84): false] ...; | Assert.cs:102:9:102:25 | [b (line 84): false] ... = ... | +| Assert.cs:103:9:103:33 | [b (line 84): true] ...; | Assert.cs:102:9:102:25 | [b (line 84): true] ... = ... | +| Assert.cs:103:23:103:23 | [b (line 84): false] access to local variable s | Assert.cs:103:9:103:33 | [b (line 84): false] ...; | +| Assert.cs:103:23:103:23 | [b (line 84): true] access to local variable s | Assert.cs:103:9:103:33 | [b (line 84): true] ...; | +| Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | Assert.cs:103:28:103:31 | [b (line 84): false] null | +| Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | Assert.cs:103:28:103:31 | [b (line 84): true] null | +| Assert.cs:103:28:103:31 | [b (line 84): false] null | Assert.cs:103:23:103:23 | [b (line 84): false] access to local variable s | +| Assert.cs:103:28:103:31 | [b (line 84): true] null | Assert.cs:103:23:103:23 | [b (line 84): true] access to local variable s | +| Assert.cs:104:9:104:35 | [b (line 84): false] call to method WriteLine | Assert.cs:104:27:104:34 | [b (line 84): false] access to property Length | +| Assert.cs:104:9:104:35 | [b (line 84): true] call to method WriteLine | Assert.cs:104:27:104:34 | [b (line 84): true] access to property Length | +| Assert.cs:104:9:104:36 | [b (line 84): false] ...; | Assert.cs:103:9:103:32 | [b (line 84): false] call to method IsTrue | +| Assert.cs:104:9:104:36 | [b (line 84): true] ...; | Assert.cs:103:9:103:32 | [b (line 84): true] call to method IsTrue | +| Assert.cs:104:27:104:27 | [b (line 84): false] access to local variable s | Assert.cs:104:9:104:36 | [b (line 84): false] ...; | +| Assert.cs:104:27:104:27 | [b (line 84): true] access to local variable s | Assert.cs:104:9:104:36 | [b (line 84): true] ...; | +| Assert.cs:104:27:104:34 | [b (line 84): false] access to property Length | Assert.cs:104:27:104:27 | [b (line 84): false] access to local variable s | +| Assert.cs:104:27:104:34 | [b (line 84): true] access to property Length | Assert.cs:104:27:104:27 | [b (line 84): true] access to local variable s | +| Assert.cs:106:9:106:25 | [b (line 84): false] ... = ... | Assert.cs:106:24:106:25 | [b (line 84): false] "" | +| Assert.cs:106:9:106:25 | [b (line 84): true] ... = ... | Assert.cs:106:17:106:20 | [b (line 84): true] null | +| Assert.cs:106:9:106:26 | [b (line 84): false] ...; | Assert.cs:104:9:104:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:106:9:106:26 | [b (line 84): true] ...; | Assert.cs:104:9:104:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:106:13:106:13 | [b (line 84): false] access to parameter b | Assert.cs:106:13:106:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:106:13:106:13 | [b (line 84): true] access to parameter b | Assert.cs:106:13:106:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:106:13:106:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:106:9:106:26 | [b (line 84): false] ...; | +| Assert.cs:106:13:106:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:106:9:106:26 | [b (line 84): true] ...; | +| Assert.cs:106:17:106:20 | [b (line 84): true] null | Assert.cs:106:13:106:13 | [b (line 84): true] access to parameter b | +| Assert.cs:106:24:106:25 | [b (line 84): false] "" | Assert.cs:106:13:106:13 | [b (line 84): false] access to parameter b | +| Assert.cs:107:9:107:33 | [b (line 84): false] call to method IsFalse | Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | +| Assert.cs:107:9:107:33 | [b (line 84): true] call to method IsFalse | Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | +| Assert.cs:107:9:107:34 | [b (line 84): false] ...; | Assert.cs:106:9:106:25 | [b (line 84): false] ... = ... | +| Assert.cs:107:9:107:34 | [b (line 84): true] ...; | Assert.cs:106:9:106:25 | [b (line 84): true] ... = ... | +| Assert.cs:107:24:107:24 | [b (line 84): false] access to local variable s | Assert.cs:107:9:107:34 | [b (line 84): false] ...; | +| Assert.cs:107:24:107:24 | [b (line 84): true] access to local variable s | Assert.cs:107:9:107:34 | [b (line 84): true] ...; | +| Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | Assert.cs:107:29:107:32 | [b (line 84): false] null | +| Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | Assert.cs:107:29:107:32 | [b (line 84): true] null | +| Assert.cs:107:29:107:32 | [b (line 84): false] null | Assert.cs:107:24:107:24 | [b (line 84): false] access to local variable s | +| Assert.cs:107:29:107:32 | [b (line 84): true] null | Assert.cs:107:24:107:24 | [b (line 84): true] access to local variable s | +| Assert.cs:108:9:108:35 | [b (line 84): false] call to method WriteLine | Assert.cs:108:27:108:34 | [b (line 84): false] access to property Length | +| Assert.cs:108:9:108:35 | [b (line 84): true] call to method WriteLine | Assert.cs:108:27:108:34 | [b (line 84): true] access to property Length | +| Assert.cs:108:9:108:36 | [b (line 84): false] ...; | Assert.cs:107:9:107:33 | [b (line 84): false] call to method IsFalse | +| Assert.cs:108:9:108:36 | [b (line 84): true] ...; | Assert.cs:107:9:107:33 | [b (line 84): true] call to method IsFalse | +| Assert.cs:108:27:108:27 | [b (line 84): false] access to local variable s | Assert.cs:108:9:108:36 | [b (line 84): false] ...; | +| Assert.cs:108:27:108:27 | [b (line 84): true] access to local variable s | Assert.cs:108:9:108:36 | [b (line 84): true] ...; | +| Assert.cs:108:27:108:34 | [b (line 84): false] access to property Length | Assert.cs:108:27:108:27 | [b (line 84): false] access to local variable s | +| Assert.cs:108:27:108:34 | [b (line 84): true] access to property Length | Assert.cs:108:27:108:27 | [b (line 84): true] access to local variable s | +| Assert.cs:110:9:110:25 | [b (line 84): false] ... = ... | Assert.cs:110:24:110:25 | [b (line 84): false] "" | +| Assert.cs:110:9:110:25 | [b (line 84): true] ... = ... | Assert.cs:110:17:110:20 | [b (line 84): true] null | +| Assert.cs:110:9:110:26 | [b (line 84): false] ...; | Assert.cs:108:9:108:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:110:9:110:26 | [b (line 84): true] ...; | Assert.cs:108:9:108:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:110:13:110:13 | [b (line 84): false] access to parameter b | Assert.cs:110:13:110:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:110:13:110:13 | [b (line 84): true] access to parameter b | Assert.cs:110:13:110:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:110:13:110:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:110:9:110:26 | [b (line 84): false] ...; | +| Assert.cs:110:13:110:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:110:9:110:26 | [b (line 84): true] ...; | +| Assert.cs:110:17:110:20 | [b (line 84): true] null | Assert.cs:110:13:110:13 | [b (line 84): true] access to parameter b | +| Assert.cs:110:24:110:25 | [b (line 84): false] "" | Assert.cs:110:13:110:13 | [b (line 84): false] access to parameter b | +| Assert.cs:111:9:111:33 | [b (line 84): false] call to method IsFalse | Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | +| Assert.cs:111:9:111:33 | [b (line 84): true] call to method IsFalse | Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | +| Assert.cs:111:9:111:34 | [b (line 84): false] ...; | Assert.cs:110:9:110:25 | [b (line 84): false] ... = ... | +| Assert.cs:111:9:111:34 | [b (line 84): true] ...; | Assert.cs:110:9:110:25 | [b (line 84): true] ... = ... | +| Assert.cs:111:24:111:24 | [b (line 84): false] access to local variable s | Assert.cs:111:9:111:34 | [b (line 84): false] ...; | +| Assert.cs:111:24:111:24 | [b (line 84): true] access to local variable s | Assert.cs:111:9:111:34 | [b (line 84): true] ...; | +| Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | Assert.cs:111:29:111:32 | [b (line 84): false] null | +| Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | Assert.cs:111:29:111:32 | [b (line 84): true] null | +| Assert.cs:111:29:111:32 | [b (line 84): false] null | Assert.cs:111:24:111:24 | [b (line 84): false] access to local variable s | +| Assert.cs:111:29:111:32 | [b (line 84): true] null | Assert.cs:111:24:111:24 | [b (line 84): true] access to local variable s | +| Assert.cs:112:9:112:35 | [b (line 84): false] call to method WriteLine | Assert.cs:112:27:112:34 | [b (line 84): false] access to property Length | +| Assert.cs:112:9:112:35 | [b (line 84): true] call to method WriteLine | Assert.cs:112:27:112:34 | [b (line 84): true] access to property Length | +| Assert.cs:112:9:112:36 | [b (line 84): false] ...; | Assert.cs:111:9:111:33 | [b (line 84): false] call to method IsFalse | +| Assert.cs:112:9:112:36 | [b (line 84): true] ...; | Assert.cs:111:9:111:33 | [b (line 84): true] call to method IsFalse | +| Assert.cs:112:27:112:27 | [b (line 84): false] access to local variable s | Assert.cs:112:9:112:36 | [b (line 84): false] ...; | +| Assert.cs:112:27:112:27 | [b (line 84): true] access to local variable s | Assert.cs:112:9:112:36 | [b (line 84): true] ...; | +| Assert.cs:112:27:112:34 | [b (line 84): false] access to property Length | Assert.cs:112:27:112:27 | [b (line 84): false] access to local variable s | +| Assert.cs:112:27:112:34 | [b (line 84): true] access to property Length | Assert.cs:112:27:112:27 | [b (line 84): true] access to local variable s | +| Assert.cs:114:9:114:25 | [b (line 84): false] ... = ... | Assert.cs:114:24:114:25 | [b (line 84): false] "" | +| Assert.cs:114:9:114:25 | [b (line 84): true] ... = ... | Assert.cs:114:17:114:20 | [b (line 84): true] null | +| Assert.cs:114:9:114:26 | [b (line 84): false] ...; | Assert.cs:112:9:112:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:114:9:114:26 | [b (line 84): true] ...; | Assert.cs:112:9:112:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:114:13:114:13 | [b (line 84): false] access to parameter b | Assert.cs:114:13:114:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:114:13:114:13 | [b (line 84): true] access to parameter b | Assert.cs:114:13:114:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:114:13:114:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:114:9:114:26 | [b (line 84): false] ...; | +| Assert.cs:114:13:114:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:114:9:114:26 | [b (line 84): true] ...; | +| Assert.cs:114:17:114:20 | [b (line 84): true] null | Assert.cs:114:13:114:13 | [b (line 84): true] access to parameter b | +| Assert.cs:114:24:114:25 | [b (line 84): false] "" | Assert.cs:114:13:114:13 | [b (line 84): false] access to parameter b | +| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | +| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | +| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:115:9:115:38 | [b (line 84): false] ...; | Assert.cs:114:9:114:25 | [b (line 84): false] ... = ... | +| Assert.cs:115:9:115:38 | [b (line 84): true] ...; | Assert.cs:114:9:114:25 | [b (line 84): true] ... = ... | +| Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | Assert.cs:115:23:115:36 | [b (line 84): false] ... && ... | +| Assert.cs:115:23:115:23 | [b (line 84): true] access to local variable s | Assert.cs:115:23:115:36 | [b (line 84): true] ... && ... | +| Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:28:115:31 | [b (line 84): false] null | +| Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:28:115:31 | [b (line 84): true] null | +| Assert.cs:115:23:115:36 | [b (line 84): false] ... && ... | Assert.cs:115:9:115:38 | [b (line 84): false] ...; | +| Assert.cs:115:23:115:36 | [b (line 84): true] ... && ... | Assert.cs:115:9:115:38 | [b (line 84): true] ...; | +| Assert.cs:115:28:115:31 | [b (line 84): false] null | Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | +| Assert.cs:115:28:115:31 | [b (line 84): true] null | Assert.cs:115:23:115:23 | [b (line 84): true] access to local variable s | +| Assert.cs:116:9:116:35 | [b (line 84): false] call to method WriteLine | Assert.cs:116:27:116:34 | [b (line 84): false] access to property Length | +| Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | +| Assert.cs:116:9:116:36 | [b (line 84): false] ...; | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:116:9:116:36 | [b (line 84): true] ...; | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:116:27:116:27 | [b (line 84): false] access to local variable s | Assert.cs:116:9:116:36 | [b (line 84): false] ...; | +| Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | Assert.cs:116:9:116:36 | [b (line 84): true] ...; | +| Assert.cs:116:27:116:34 | [b (line 84): false] access to property Length | Assert.cs:116:27:116:27 | [b (line 84): false] access to local variable s | +| Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | +| Assert.cs:118:9:118:25 | [b (line 84): false] ... = ... | Assert.cs:118:24:118:25 | [b (line 84): false] "" | +| Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | Assert.cs:118:17:118:20 | [b (line 84): true] null | +| Assert.cs:118:9:118:26 | [b (line 84): false] ...; | Assert.cs:116:9:116:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:118:9:118:26 | [b (line 84): true] ...; | Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | Assert.cs:118:13:118:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:118:13:118:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:118:9:118:26 | [b (line 84): false] ...; | +| Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:118:9:118:26 | [b (line 84): true] ...; | +| Assert.cs:118:17:118:20 | [b (line 84): true] null | Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | +| Assert.cs:118:24:118:25 | [b (line 84): false] "" | Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | +| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | +| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:119:38:119:38 | [b (line 84): false] access to parameter b | +| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | +| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | +| Assert.cs:119:9:119:40 | [b (line 84): false] ...; | Assert.cs:118:9:118:25 | [b (line 84): false] ... = ... | +| Assert.cs:119:9:119:40 | [b (line 84): true] ...; | Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | +| Assert.cs:119:24:119:24 | [b (line 84): false] access to local variable s | Assert.cs:119:24:119:38 | [b (line 84): false] ... \|\| ... | +| Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | Assert.cs:119:24:119:38 | [b (line 84): true] ... \|\| ... | +| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | Assert.cs:119:29:119:32 | [b (line 84): false] null | +| Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:29:119:32 | [b (line 84): true] null | +| Assert.cs:119:24:119:38 | [b (line 84): false] ... \|\| ... | Assert.cs:119:9:119:40 | [b (line 84): false] ...; | +| Assert.cs:119:24:119:38 | [b (line 84): true] ... \|\| ... | Assert.cs:119:9:119:40 | [b (line 84): true] ...; | +| Assert.cs:119:29:119:32 | [b (line 84): false] null | Assert.cs:119:24:119:24 | [b (line 84): false] access to local variable s | +| Assert.cs:119:29:119:32 | [b (line 84): true] null | Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | +| Assert.cs:119:38:119:38 | [b (line 84): false] access to parameter b | Assert.cs:119:37:119:38 | [b (line 84): false] !... | +| Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:120:9:120:35 | [b (line 84): false] call to method WriteLine | Assert.cs:120:27:120:34 | [b (line 84): false] access to property Length | +| Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | +| Assert.cs:120:9:120:36 | [b (line 84): false] ...; | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | +| Assert.cs:120:9:120:36 | [b (line 84): true] ...; | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | +| Assert.cs:120:27:120:27 | [b (line 84): false] access to local variable s | Assert.cs:120:9:120:36 | [b (line 84): false] ...; | +| Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | Assert.cs:120:9:120:36 | [b (line 84): true] ...; | +| Assert.cs:120:27:120:34 | [b (line 84): false] access to property Length | Assert.cs:120:27:120:27 | [b (line 84): false] access to local variable s | +| Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | +| Assert.cs:122:9:122:25 | [b (line 84): false] ... = ... | Assert.cs:122:24:122:25 | [b (line 84): false] "" | +| Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | Assert.cs:122:17:122:20 | [b (line 84): true] null | +| Assert.cs:122:9:122:26 | [b (line 84): false] ...; | Assert.cs:120:9:120:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:122:9:122:26 | [b (line 84): true] ...; | Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | Assert.cs:122:13:122:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:122:13:122:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:122:9:122:26 | [b (line 84): false] ...; | +| Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:122:9:122:26 | [b (line 84): true] ...; | +| Assert.cs:122:17:122:20 | [b (line 84): true] null | Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | +| Assert.cs:122:24:122:25 | [b (line 84): false] "" | Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | +| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | +| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | +| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | +| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:123:9:123:38 | [b (line 84): false] ...; | Assert.cs:122:9:122:25 | [b (line 84): false] ... = ... | +| Assert.cs:123:9:123:38 | [b (line 84): true] ...; | Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | +| Assert.cs:123:23:123:23 | [b (line 84): false] access to local variable s | Assert.cs:123:23:123:36 | [b (line 84): false] ... && ... | +| Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | Assert.cs:123:23:123:36 | [b (line 84): true] ... && ... | +| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | Assert.cs:123:28:123:31 | [b (line 84): false] null | +| Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:28:123:31 | [b (line 84): true] null | +| Assert.cs:123:23:123:36 | [b (line 84): false] ... && ... | Assert.cs:123:9:123:38 | [b (line 84): false] ...; | +| Assert.cs:123:23:123:36 | [b (line 84): true] ... && ... | Assert.cs:123:9:123:38 | [b (line 84): true] ...; | +| Assert.cs:123:28:123:31 | [b (line 84): false] null | Assert.cs:123:23:123:23 | [b (line 84): false] access to local variable s | +| Assert.cs:123:28:123:31 | [b (line 84): true] null | Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | +| Assert.cs:124:9:124:35 | [b (line 84): false] call to method WriteLine | Assert.cs:124:27:124:34 | [b (line 84): false] access to property Length | +| Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | +| Assert.cs:124:9:124:36 | [b (line 84): false] ...; | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:124:9:124:36 | [b (line 84): true] ...; | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:124:27:124:27 | [b (line 84): false] access to local variable s | Assert.cs:124:9:124:36 | [b (line 84): false] ...; | +| Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | Assert.cs:124:9:124:36 | [b (line 84): true] ...; | +| Assert.cs:124:27:124:34 | [b (line 84): false] access to property Length | Assert.cs:124:27:124:27 | [b (line 84): false] access to local variable s | +| Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:126:17:126:20 | null | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:126:24:126:25 | "" | +| Assert.cs:126:9:126:26 | [b (line 84): false] ...; | Assert.cs:124:9:124:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:126:9:126:26 | [b (line 84): true] ...; | Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | +| Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | Assert.cs:126:13:126:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | +| Assert.cs:126:13:126:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:126:9:126:26 | [b (line 84): false] ...; | +| Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:126:9:126:26 | [b (line 84): true] ...; | +| Assert.cs:126:17:126:20 | null | Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | +| Assert.cs:126:24:126:25 | "" | Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:127:24:127:32 | ... != ... | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:127:38:127:38 | access to parameter b | +| Assert.cs:127:9:127:40 | ...; | Assert.cs:126:9:126:25 | ... = ... | +| Assert.cs:127:24:127:24 | access to local variable s | Assert.cs:127:24:127:38 | ... \|\| ... | +| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:29:127:32 | null | +| Assert.cs:127:24:127:38 | ... \|\| ... | Assert.cs:127:9:127:40 | ...; | +| Assert.cs:127:29:127:32 | null | Assert.cs:127:24:127:24 | access to local variable s | +| Assert.cs:127:38:127:38 | access to parameter b | Assert.cs:127:37:127:38 | !... | +| Assert.cs:128:9:128:35 | call to method WriteLine | Assert.cs:128:27:128:34 | access to property Length | +| Assert.cs:128:9:128:36 | ...; | Assert.cs:127:9:127:39 | call to method IsFalse | +| Assert.cs:128:27:128:27 | access to local variable s | Assert.cs:128:9:128:36 | ...; | +| Assert.cs:128:27:128:34 | access to property Length | Assert.cs:128:27:128:27 | access to local variable s | | Assignments.cs:3:10:3:10 | exit M | Assignments.cs:14:9:14:35 | ... += ... | | Assignments.cs:4:5:15:5 | {...} | Assignments.cs:3:10:3:10 | enter M | | Assignments.cs:5:9:5:18 | ... ...; | Assignments.cs:4:5:15:5 | {...} | @@ -6353,6 +7323,168 @@ blockDominance | ArrayCreation.cs:5:12:5:13 | enter M2 | ArrayCreation.cs:5:12:5:13 | enter M2 | | ArrayCreation.cs:7:11:7:12 | enter M3 | ArrayCreation.cs:7:11:7:12 | enter M3 | | ArrayCreation.cs:9:12:9:13 | enter M4 | ArrayCreation.cs:9:12:9:13 | enter M4 | +| Assert.cs:7:10:7:11 | enter M1 | Assert.cs:7:10:7:11 | enter M1 | +| Assert.cs:7:10:7:11 | enter M1 | Assert.cs:9:16:9:32 | String s = ... | +| Assert.cs:7:10:7:11 | enter M1 | Assert.cs:9:24:9:27 | null | +| Assert.cs:7:10:7:11 | enter M1 | Assert.cs:9:31:9:32 | "" | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:9:16:9:32 | String s = ... | +| Assert.cs:9:24:9:27 | null | Assert.cs:9:24:9:27 | null | +| Assert.cs:9:31:9:32 | "" | Assert.cs:9:31:9:32 | "" | +| Assert.cs:14:10:14:11 | enter M2 | Assert.cs:14:10:14:11 | enter M2 | +| Assert.cs:14:10:14:11 | enter M2 | Assert.cs:16:16:16:32 | String s = ... | +| Assert.cs:14:10:14:11 | enter M2 | Assert.cs:16:24:16:27 | null | +| Assert.cs:14:10:14:11 | enter M2 | Assert.cs:16:31:16:32 | "" | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:16:16:16:32 | String s = ... | +| Assert.cs:16:24:16:27 | null | Assert.cs:16:24:16:27 | null | +| Assert.cs:16:31:16:32 | "" | Assert.cs:16:31:16:32 | "" | +| Assert.cs:21:10:21:11 | enter M3 | Assert.cs:21:10:21:11 | enter M3 | +| Assert.cs:21:10:21:11 | enter M3 | Assert.cs:23:16:23:32 | String s = ... | +| Assert.cs:21:10:21:11 | enter M3 | Assert.cs:23:24:23:27 | null | +| Assert.cs:21:10:21:11 | enter M3 | Assert.cs:23:31:23:32 | "" | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:23:16:23:32 | String s = ... | +| Assert.cs:23:24:23:27 | null | Assert.cs:23:24:23:27 | null | +| Assert.cs:23:31:23:32 | "" | Assert.cs:23:31:23:32 | "" | +| Assert.cs:28:10:28:11 | enter M4 | Assert.cs:28:10:28:11 | enter M4 | +| Assert.cs:28:10:28:11 | enter M4 | Assert.cs:30:16:30:32 | String s = ... | +| Assert.cs:28:10:28:11 | enter M4 | Assert.cs:30:24:30:27 | null | +| Assert.cs:28:10:28:11 | enter M4 | Assert.cs:30:31:30:32 | "" | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:30:16:30:32 | String s = ... | +| Assert.cs:30:24:30:27 | null | Assert.cs:30:24:30:27 | null | +| Assert.cs:30:31:30:32 | "" | Assert.cs:30:31:30:32 | "" | +| Assert.cs:35:10:35:11 | enter M5 | Assert.cs:35:10:35:11 | enter M5 | +| Assert.cs:35:10:35:11 | enter M5 | Assert.cs:37:16:37:32 | String s = ... | +| Assert.cs:35:10:35:11 | enter M5 | Assert.cs:37:24:37:27 | null | +| Assert.cs:35:10:35:11 | enter M5 | Assert.cs:37:31:37:32 | "" | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:37:16:37:32 | String s = ... | +| Assert.cs:37:24:37:27 | null | Assert.cs:37:24:37:27 | null | +| Assert.cs:37:31:37:32 | "" | Assert.cs:37:31:37:32 | "" | +| Assert.cs:42:10:42:11 | enter M6 | Assert.cs:42:10:42:11 | enter M6 | +| Assert.cs:42:10:42:11 | enter M6 | Assert.cs:44:16:44:32 | String s = ... | +| Assert.cs:42:10:42:11 | enter M6 | Assert.cs:44:24:44:27 | null | +| Assert.cs:42:10:42:11 | enter M6 | Assert.cs:44:31:44:32 | "" | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:44:16:44:32 | String s = ... | +| Assert.cs:44:24:44:27 | null | Assert.cs:44:24:44:27 | null | +| Assert.cs:44:31:44:32 | "" | Assert.cs:44:31:44:32 | "" | +| Assert.cs:49:10:49:11 | enter M7 | Assert.cs:49:10:49:11 | enter M7 | +| Assert.cs:49:10:49:11 | enter M7 | Assert.cs:51:16:51:32 | String s = ... | +| Assert.cs:49:10:49:11 | enter M7 | Assert.cs:51:24:51:27 | null | +| Assert.cs:49:10:49:11 | enter M7 | Assert.cs:51:31:51:32 | "" | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:51:16:51:32 | String s = ... | +| Assert.cs:51:24:51:27 | null | Assert.cs:51:24:51:27 | null | +| Assert.cs:51:31:51:32 | "" | Assert.cs:51:31:51:32 | "" | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:56:10:56:11 | enter M8 | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:58:16:58:32 | String s = ... | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:58:24:58:27 | null | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:58:31:58:32 | "" | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:59:9:59:37 | call to method IsTrue | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:59:36:59:36 | access to parameter b | +| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:58:16:58:32 | String s = ... | +| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:59:9:59:37 | call to method IsTrue | +| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:59:36:59:36 | access to parameter b | +| Assert.cs:58:24:58:27 | null | Assert.cs:58:24:58:27 | null | +| Assert.cs:58:31:58:32 | "" | Assert.cs:58:31:58:32 | "" | +| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:59:9:59:37 | call to method IsTrue | +| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:59:36:59:36 | access to parameter b | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:63:10:63:11 | enter M9 | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:65:16:65:32 | String s = ... | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:65:24:65:27 | null | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:65:31:65:32 | "" | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:66:9:66:38 | call to method IsFalse | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:66:37:66:37 | access to parameter b | +| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:65:16:65:32 | String s = ... | +| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:66:9:66:38 | call to method IsFalse | +| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:66:37:66:37 | access to parameter b | +| Assert.cs:65:24:65:27 | null | Assert.cs:65:24:65:27 | null | +| Assert.cs:65:31:65:32 | "" | Assert.cs:65:31:65:32 | "" | +| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:66:9:66:38 | call to method IsFalse | +| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:66:37:66:37 | access to parameter b | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:70:10:70:12 | enter M10 | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:72:16:72:32 | String s = ... | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:72:24:72:27 | null | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:72:31:72:32 | "" | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:73:9:73:37 | call to method IsTrue | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:73:36:73:36 | access to parameter b | +| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:72:16:72:32 | String s = ... | +| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:73:9:73:37 | call to method IsTrue | +| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:73:36:73:36 | access to parameter b | +| Assert.cs:72:24:72:27 | null | Assert.cs:72:24:72:27 | null | +| Assert.cs:72:31:72:32 | "" | Assert.cs:72:31:72:32 | "" | +| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:73:9:73:37 | call to method IsTrue | +| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:73:36:73:36 | access to parameter b | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:77:10:77:12 | enter M11 | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:79:16:79:32 | String s = ... | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:79:24:79:27 | null | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:79:31:79:32 | "" | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:80:9:80:38 | call to method IsFalse | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:80:37:80:37 | access to parameter b | +| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:79:16:79:32 | String s = ... | +| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:80:9:80:38 | call to method IsFalse | +| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:80:37:80:37 | access to parameter b | +| Assert.cs:79:24:79:27 | null | Assert.cs:79:24:79:27 | null | +| Assert.cs:79:31:79:32 | "" | Assert.cs:79:31:79:32 | "" | +| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:80:9:80:38 | call to method IsFalse | +| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:80:37:80:37 | access to parameter b | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:84:10:84:12 | enter M12 | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:86:24:86:27 | [b (line 84): true] null | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:86:31:86:32 | [b (line 84): false] "" | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:37:119:38 | [b (line 84): false] !... | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:126:9:126:25 | ... = ... | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:127:9:127:39 | call to method IsFalse | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:127:37:127:38 | !... | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:86:24:86:27 | [b (line 84): true] null | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:86:31:86:32 | [b (line 84): false] "" | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:119:37:119:38 | [b (line 84): false] !... | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | +| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | +| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:119:37:119:38 | [b (line 84): false] !... | +| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | +| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | +| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | +| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | +| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | +| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:119:37:119:38 | [b (line 84): false] !... | Assert.cs:119:37:119:38 | [b (line 84): false] !... | +| Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | +| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:126:9:126:25 | ... = ... | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:127:9:127:39 | call to method IsFalse | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:127:37:127:38 | !... | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:127:9:127:39 | call to method IsFalse | +| Assert.cs:127:37:127:38 | !... | Assert.cs:127:37:127:38 | !... | | Assignments.cs:3:10:3:10 | enter M | Assignments.cs:3:10:3:10 | enter M | | Assignments.cs:14:18:14:35 | enter (...) => ... | Assignments.cs:14:18:14:35 | enter (...) => ... | | Assignments.cs:17:40:17:40 | enter + | Assignments.cs:17:40:17:40 | enter + | @@ -8813,6 +9945,185 @@ postBlockDominance | ArrayCreation.cs:5:12:5:13 | enter M2 | ArrayCreation.cs:5:12:5:13 | enter M2 | | ArrayCreation.cs:7:11:7:12 | enter M3 | ArrayCreation.cs:7:11:7:12 | enter M3 | | ArrayCreation.cs:9:12:9:13 | enter M4 | ArrayCreation.cs:9:12:9:13 | enter M4 | +| Assert.cs:7:10:7:11 | enter M1 | Assert.cs:7:10:7:11 | enter M1 | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:7:10:7:11 | enter M1 | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:9:16:9:32 | String s = ... | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:9:24:9:27 | null | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:9:31:9:32 | "" | +| Assert.cs:9:24:9:27 | null | Assert.cs:9:24:9:27 | null | +| Assert.cs:9:31:9:32 | "" | Assert.cs:9:31:9:32 | "" | +| Assert.cs:14:10:14:11 | enter M2 | Assert.cs:14:10:14:11 | enter M2 | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:14:10:14:11 | enter M2 | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:16:16:16:32 | String s = ... | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:16:24:16:27 | null | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:16:31:16:32 | "" | +| Assert.cs:16:24:16:27 | null | Assert.cs:16:24:16:27 | null | +| Assert.cs:16:31:16:32 | "" | Assert.cs:16:31:16:32 | "" | +| Assert.cs:21:10:21:11 | enter M3 | Assert.cs:21:10:21:11 | enter M3 | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:21:10:21:11 | enter M3 | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:23:16:23:32 | String s = ... | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:23:24:23:27 | null | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:23:31:23:32 | "" | +| Assert.cs:23:24:23:27 | null | Assert.cs:23:24:23:27 | null | +| Assert.cs:23:31:23:32 | "" | Assert.cs:23:31:23:32 | "" | +| Assert.cs:28:10:28:11 | enter M4 | Assert.cs:28:10:28:11 | enter M4 | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:28:10:28:11 | enter M4 | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:30:16:30:32 | String s = ... | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:30:24:30:27 | null | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:30:31:30:32 | "" | +| Assert.cs:30:24:30:27 | null | Assert.cs:30:24:30:27 | null | +| Assert.cs:30:31:30:32 | "" | Assert.cs:30:31:30:32 | "" | +| Assert.cs:35:10:35:11 | enter M5 | Assert.cs:35:10:35:11 | enter M5 | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:35:10:35:11 | enter M5 | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:37:16:37:32 | String s = ... | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:37:24:37:27 | null | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:37:31:37:32 | "" | +| Assert.cs:37:24:37:27 | null | Assert.cs:37:24:37:27 | null | +| Assert.cs:37:31:37:32 | "" | Assert.cs:37:31:37:32 | "" | +| Assert.cs:42:10:42:11 | enter M6 | Assert.cs:42:10:42:11 | enter M6 | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:42:10:42:11 | enter M6 | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:44:16:44:32 | String s = ... | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:44:24:44:27 | null | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:44:31:44:32 | "" | +| Assert.cs:44:24:44:27 | null | Assert.cs:44:24:44:27 | null | +| Assert.cs:44:31:44:32 | "" | Assert.cs:44:31:44:32 | "" | +| Assert.cs:49:10:49:11 | enter M7 | Assert.cs:49:10:49:11 | enter M7 | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:49:10:49:11 | enter M7 | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:51:16:51:32 | String s = ... | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:51:24:51:27 | null | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:51:31:51:32 | "" | +| Assert.cs:51:24:51:27 | null | Assert.cs:51:24:51:27 | null | +| Assert.cs:51:31:51:32 | "" | Assert.cs:51:31:51:32 | "" | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:56:10:56:11 | enter M8 | +| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:56:10:56:11 | enter M8 | +| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:58:16:58:32 | String s = ... | +| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:58:24:58:27 | null | +| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:58:31:58:32 | "" | +| Assert.cs:58:24:58:27 | null | Assert.cs:58:24:58:27 | null | +| Assert.cs:58:31:58:32 | "" | Assert.cs:58:31:58:32 | "" | +| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:56:10:56:11 | enter M8 | +| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:58:16:58:32 | String s = ... | +| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:58:24:58:27 | null | +| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:58:31:58:32 | "" | +| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:59:9:59:37 | call to method IsTrue | +| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:59:36:59:36 | access to parameter b | +| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:59:36:59:36 | access to parameter b | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:63:10:63:11 | enter M9 | +| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:63:10:63:11 | enter M9 | +| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:65:16:65:32 | String s = ... | +| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:65:24:65:27 | null | +| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:65:31:65:32 | "" | +| Assert.cs:65:24:65:27 | null | Assert.cs:65:24:65:27 | null | +| Assert.cs:65:31:65:32 | "" | Assert.cs:65:31:65:32 | "" | +| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:63:10:63:11 | enter M9 | +| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:65:16:65:32 | String s = ... | +| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:65:24:65:27 | null | +| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:65:31:65:32 | "" | +| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:66:9:66:38 | call to method IsFalse | +| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:66:37:66:37 | access to parameter b | +| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:66:37:66:37 | access to parameter b | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:70:10:70:12 | enter M10 | +| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:70:10:70:12 | enter M10 | +| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:72:16:72:32 | String s = ... | +| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:72:24:72:27 | null | +| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:72:31:72:32 | "" | +| Assert.cs:72:24:72:27 | null | Assert.cs:72:24:72:27 | null | +| Assert.cs:72:31:72:32 | "" | Assert.cs:72:31:72:32 | "" | +| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:70:10:70:12 | enter M10 | +| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:72:16:72:32 | String s = ... | +| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:72:24:72:27 | null | +| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:72:31:72:32 | "" | +| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:73:9:73:37 | call to method IsTrue | +| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:73:36:73:36 | access to parameter b | +| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:73:36:73:36 | access to parameter b | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:77:10:77:12 | enter M11 | +| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:77:10:77:12 | enter M11 | +| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:79:16:79:32 | String s = ... | +| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:79:24:79:27 | null | +| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:79:31:79:32 | "" | +| Assert.cs:79:24:79:27 | null | Assert.cs:79:24:79:27 | null | +| Assert.cs:79:31:79:32 | "" | Assert.cs:79:31:79:32 | "" | +| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:77:10:77:12 | enter M11 | +| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:79:16:79:32 | String s = ... | +| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:79:24:79:27 | null | +| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:79:31:79:32 | "" | +| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:80:9:80:38 | call to method IsFalse | +| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:80:37:80:37 | access to parameter b | +| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:80:37:80:37 | access to parameter b | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:84:10:84:12 | enter M12 | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:86:24:86:27 | [b (line 84): true] null | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:86:31:86:32 | [b (line 84): false] "" | +| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:86:31:86:32 | [b (line 84): false] "" | +| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:86:24:86:27 | [b (line 84): true] null | +| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:86:31:86:32 | [b (line 84): false] "" | +| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | +| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:119:37:119:38 | [b (line 84): false] !... | +| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:86:24:86:27 | [b (line 84): true] null | +| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | +| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:119:37:119:38 | [b (line 84): false] !... | Assert.cs:119:37:119:38 | [b (line 84): false] !... | +| Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:86:31:86:32 | [b (line 84): false] "" | +| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | +| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:119:37:119:38 | [b (line 84): false] !... | +| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | +| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:86:24:86:27 | [b (line 84): true] null | +| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | +| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | +| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:84:10:84:12 | enter M12 | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:86:24:86:27 | [b (line 84): true] null | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:86:31:86:32 | [b (line 84): false] "" | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:119:37:119:38 | [b (line 84): false] !... | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:126:9:126:25 | ... = ... | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:84:10:84:12 | enter M12 | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:86:24:86:27 | [b (line 84): true] null | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:86:31:86:32 | [b (line 84): false] "" | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:119:37:119:38 | [b (line 84): false] !... | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:126:9:126:25 | ... = ... | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:127:9:127:39 | call to method IsFalse | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:127:37:127:38 | !... | +| Assert.cs:127:37:127:38 | !... | Assert.cs:127:37:127:38 | !... | | Assignments.cs:3:10:3:10 | enter M | Assignments.cs:3:10:3:10 | enter M | | Assignments.cs:14:18:14:35 | enter (...) => ... | Assignments.cs:14:18:14:35 | enter (...) => ... | | Assignments.cs:17:40:17:40 | enter + | Assignments.cs:17:40:17:40 | enter + | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected index 10afd142066..aa8ad433674 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected @@ -325,6 +325,515 @@ nodeEnclosing | ArrayCreation.cs:9:43:9:50 | { ..., ... } | ArrayCreation.cs:9:12:9:13 | M4 | | ArrayCreation.cs:9:45:9:45 | 2 | ArrayCreation.cs:9:12:9:13 | M4 | | ArrayCreation.cs:9:48:9:48 | 3 | ArrayCreation.cs:9:12:9:13 | M4 | +| Assert.cs:7:10:7:11 | enter M1 | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:7:10:7:11 | exit M1 | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:8:5:12:5 | {...} | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:9:9:9:33 | ... ...; | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:9:20:9:32 | ... ? ... : ... | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:9:24:9:27 | null | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:9:31:9:32 | "" | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:10:9:10:31 | call to method Assert | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:10:9:10:32 | ...; | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:10:22:10:22 | access to local variable s | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:10:27:10:30 | null | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:11:9:11:35 | call to method WriteLine | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:11:9:11:36 | ...; | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:11:27:11:27 | access to local variable s | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:11:27:11:34 | access to property Length | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:14:10:14:11 | enter M2 | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:14:10:14:11 | exit M2 | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:15:5:19:5 | {...} | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:16:9:16:33 | ... ...; | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:16:20:16:32 | ... ? ... : ... | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:16:24:16:27 | null | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:16:31:16:32 | "" | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:17:9:17:24 | call to method IsNull | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:17:9:17:25 | ...; | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:18:9:18:35 | call to method WriteLine | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:18:9:18:36 | ...; | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:18:27:18:27 | access to local variable s | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:18:27:18:34 | access to property Length | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:21:10:21:11 | enter M3 | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:21:10:21:11 | exit M3 | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:22:5:26:5 | {...} | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:23:9:23:33 | ... ...; | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:23:20:23:32 | ... ? ... : ... | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:23:24:23:27 | null | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:23:31:23:32 | "" | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:24:9:24:27 | call to method IsNotNull | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:24:9:24:28 | ...; | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:25:9:25:35 | call to method WriteLine | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:25:9:25:36 | ...; | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:25:27:25:27 | access to local variable s | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:25:27:25:34 | access to property Length | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:28:10:28:11 | enter M4 | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:28:10:28:11 | exit M4 | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:29:5:33:5 | {...} | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:30:9:30:33 | ... ...; | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:30:20:30:32 | ... ? ... : ... | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:30:24:30:27 | null | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:30:31:30:32 | "" | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:31:9:31:32 | call to method IsTrue | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:31:9:31:33 | ...; | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:31:23:31:23 | access to local variable s | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:31:28:31:31 | null | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:32:9:32:35 | call to method WriteLine | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:32:9:32:36 | ...; | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:32:27:32:27 | access to local variable s | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:32:27:32:34 | access to property Length | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:35:10:35:11 | enter M5 | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:35:10:35:11 | exit M5 | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:36:5:40:5 | {...} | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:37:9:37:33 | ... ...; | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:37:20:37:32 | ... ? ... : ... | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:37:24:37:27 | null | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:37:31:37:32 | "" | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:38:9:38:32 | call to method IsTrue | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:38:9:38:33 | ...; | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:38:23:38:23 | access to local variable s | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:38:28:38:31 | null | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:39:9:39:35 | call to method WriteLine | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:39:9:39:36 | ...; | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:39:27:39:27 | access to local variable s | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:39:27:39:34 | access to property Length | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:42:10:42:11 | enter M6 | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:42:10:42:11 | exit M6 | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:43:5:47:5 | {...} | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:44:9:44:33 | ... ...; | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:44:20:44:32 | ... ? ... : ... | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:44:24:44:27 | null | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:44:31:44:32 | "" | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:45:9:45:33 | call to method IsFalse | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:45:9:45:34 | ...; | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:45:24:45:24 | access to local variable s | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:45:29:45:32 | null | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:46:9:46:35 | call to method WriteLine | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:46:9:46:36 | ...; | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:46:27:46:27 | access to local variable s | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:46:27:46:34 | access to property Length | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:49:10:49:11 | enter M7 | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:49:10:49:11 | exit M7 | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:50:5:54:5 | {...} | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:51:9:51:33 | ... ...; | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:51:20:51:32 | ... ? ... : ... | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:51:24:51:27 | null | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:51:31:51:32 | "" | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:52:9:52:33 | call to method IsFalse | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:52:9:52:34 | ...; | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:52:24:52:24 | access to local variable s | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:52:29:52:32 | null | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:53:9:53:35 | call to method WriteLine | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:53:9:53:36 | ...; | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:53:27:53:27 | access to local variable s | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:53:27:53:34 | access to property Length | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:56:10:56:11 | exit M8 | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:57:5:61:5 | {...} | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:58:9:58:33 | ... ...; | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:58:20:58:32 | ... ? ... : ... | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:58:24:58:27 | null | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:58:31:58:32 | "" | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:9:59:38 | ...; | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:23:59:23 | access to local variable s | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:23:59:36 | ... && ... | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:28:59:31 | null | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:60:9:60:35 | call to method WriteLine | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:60:9:60:36 | ...; | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:60:27:60:34 | access to property Length | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:63:10:63:11 | exit M9 | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:64:5:68:5 | {...} | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:65:9:65:33 | ... ...; | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:65:24:65:27 | null | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:65:31:65:32 | "" | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:9:66:39 | ...; | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:24:66:24 | access to local variable s | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:29:66:32 | null | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:67:9:67:35 | call to method WriteLine | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:67:9:67:36 | ...; | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:67:27:67:34 | access to property Length | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:70:10:70:12 | exit M10 | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:71:5:75:5 | {...} | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:72:9:72:33 | ... ...; | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:72:24:72:27 | null | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:72:31:72:32 | "" | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:9:73:38 | ...; | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:23:73:23 | access to local variable s | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:23:73:36 | ... && ... | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:28:73:31 | null | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:74:9:74:35 | call to method WriteLine | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:74:9:74:36 | ...; | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:74:27:74:34 | access to property Length | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:77:10:77:12 | exit M11 | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:78:5:82:5 | {...} | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:79:9:79:33 | ... ...; | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:79:24:79:27 | null | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:79:31:79:32 | "" | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:9:80:39 | ...; | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:24:80:24 | access to local variable s | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:29:80:32 | null | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:81:9:81:35 | call to method WriteLine | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:81:9:81:36 | ...; | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:81:27:81:34 | access to property Length | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:85:5:129:5 | {...} | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:86:9:86:33 | ... ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:86:16:86:32 | [b (line 84): false] String s = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:86:16:86:32 | [b (line 84): true] String s = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:86:20:86:20 | access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:86:20:86:32 | ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:9:87:31 | [b (line 84): false] call to method Assert | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:9:87:31 | [b (line 84): true] call to method Assert | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:9:87:32 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:9:87:32 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:22:87:22 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:22:87:22 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:27:87:30 | [b (line 84): false] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:27:87:30 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:88:9:88:35 | [b (line 84): false] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:88:9:88:35 | [b (line 84): true] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:88:9:88:36 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:88:9:88:36 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:88:27:88:27 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:88:27:88:27 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:88:27:88:34 | [b (line 84): false] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:88:27:88:34 | [b (line 84): true] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:90:9:90:25 | [b (line 84): false] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:90:9:90:25 | [b (line 84): true] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:90:9:90:26 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:90:9:90:26 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:90:13:90:13 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:90:13:90:13 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:90:13:90:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:90:13:90:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:90:17:90:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:90:24:90:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:91:9:91:24 | [b (line 84): false] call to method IsNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:91:9:91:24 | [b (line 84): true] call to method IsNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:91:9:91:25 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:91:9:91:25 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:92:9:92:35 | [b (line 84): false] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:92:9:92:35 | [b (line 84): true] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:92:9:92:36 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:92:9:92:36 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:92:27:92:27 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:92:27:92:27 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:92:27:92:34 | [b (line 84): false] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:92:27:92:34 | [b (line 84): true] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:94:9:94:25 | [b (line 84): false] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:94:9:94:25 | [b (line 84): true] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:94:9:94:26 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:94:9:94:26 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:94:13:94:13 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:94:13:94:13 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:94:13:94:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:94:13:94:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:94:17:94:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:94:24:94:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:95:9:95:27 | [b (line 84): false] call to method IsNotNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:95:9:95:27 | [b (line 84): true] call to method IsNotNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:95:9:95:28 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:95:9:95:28 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:96:9:96:35 | [b (line 84): false] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:96:9:96:35 | [b (line 84): true] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:96:9:96:36 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:96:9:96:36 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:96:27:96:27 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:96:27:96:27 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:96:27:96:34 | [b (line 84): false] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:96:27:96:34 | [b (line 84): true] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:98:9:98:25 | [b (line 84): false] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:98:9:98:25 | [b (line 84): true] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:98:9:98:26 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:98:9:98:26 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:98:13:98:13 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:98:13:98:13 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:98:13:98:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:98:13:98:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:98:17:98:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:98:24:98:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:9:99:32 | [b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:9:99:32 | [b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:9:99:33 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:9:99:33 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:23:99:23 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:23:99:23 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:28:99:31 | [b (line 84): false] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:28:99:31 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:100:9:100:35 | [b (line 84): false] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:100:9:100:35 | [b (line 84): true] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:100:9:100:36 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:100:9:100:36 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:100:27:100:27 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:100:27:100:27 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:100:27:100:34 | [b (line 84): false] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:100:27:100:34 | [b (line 84): true] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:102:9:102:25 | [b (line 84): false] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:102:9:102:25 | [b (line 84): true] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:102:9:102:26 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:102:9:102:26 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:102:13:102:13 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:102:13:102:13 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:102:13:102:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:102:13:102:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:102:17:102:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:102:24:102:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:9:103:32 | [b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:9:103:32 | [b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:9:103:33 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:9:103:33 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:23:103:23 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:23:103:23 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:28:103:31 | [b (line 84): false] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:28:103:31 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:104:9:104:35 | [b (line 84): false] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:104:9:104:35 | [b (line 84): true] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:104:9:104:36 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:104:9:104:36 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:104:27:104:27 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:104:27:104:27 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:104:27:104:34 | [b (line 84): false] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:104:27:104:34 | [b (line 84): true] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:106:9:106:25 | [b (line 84): false] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:106:9:106:25 | [b (line 84): true] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:106:9:106:26 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:106:9:106:26 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:106:13:106:13 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:106:13:106:13 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:106:13:106:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:106:13:106:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:106:17:106:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:106:24:106:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:9:107:33 | [b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:9:107:33 | [b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:9:107:34 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:9:107:34 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:24:107:24 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:24:107:24 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:29:107:32 | [b (line 84): false] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:29:107:32 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:108:9:108:35 | [b (line 84): false] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:108:9:108:35 | [b (line 84): true] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:108:9:108:36 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:108:9:108:36 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:108:27:108:27 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:108:27:108:27 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:108:27:108:34 | [b (line 84): false] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:108:27:108:34 | [b (line 84): true] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:110:9:110:25 | [b (line 84): false] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:110:9:110:25 | [b (line 84): true] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:110:9:110:26 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:110:9:110:26 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:110:13:110:13 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:110:13:110:13 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:110:13:110:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:110:13:110:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:110:17:110:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:110:24:110:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:9:111:33 | [b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:9:111:33 | [b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:9:111:34 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:9:111:34 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:24:111:24 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:24:111:24 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:29:111:32 | [b (line 84): false] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:29:111:32 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:112:9:112:35 | [b (line 84): false] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:112:9:112:35 | [b (line 84): true] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:112:9:112:36 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:112:9:112:36 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:112:27:112:27 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:112:27:112:27 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:112:27:112:34 | [b (line 84): false] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:112:27:112:34 | [b (line 84): true] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:114:9:114:25 | [b (line 84): false] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:114:9:114:25 | [b (line 84): true] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:114:9:114:26 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:114:9:114:26 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:114:13:114:13 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:114:13:114:13 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:114:13:114:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:114:13:114:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:114:17:114:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:114:24:114:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:9:115:38 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:9:115:38 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:23:115:23 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:23:115:36 | [b (line 84): false] ... && ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:23:115:36 | [b (line 84): true] ... && ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:28:115:31 | [b (line 84): false] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:28:115:31 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:116:9:116:35 | [b (line 84): false] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:116:9:116:36 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:116:9:116:36 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:116:27:116:27 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:116:27:116:34 | [b (line 84): false] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:118:9:118:25 | [b (line 84): false] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:118:9:118:26 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:118:9:118:26 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:118:13:118:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:118:17:118:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:118:24:118:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:9:119:40 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:9:119:40 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:24:119:24 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:24:119:38 | [b (line 84): false] ... \|\| ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:24:119:38 | [b (line 84): true] ... \|\| ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:29:119:32 | [b (line 84): false] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:29:119:32 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:37:119:38 | [b (line 84): false] !... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:38:119:38 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:120:9:120:35 | [b (line 84): false] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:120:9:120:36 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:120:9:120:36 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:120:27:120:27 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:120:27:120:34 | [b (line 84): false] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:122:9:122:25 | [b (line 84): false] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:122:9:122:26 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:122:9:122:26 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:122:13:122:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:122:17:122:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:122:24:122:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:9:123:38 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:9:123:38 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:23:123:23 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:23:123:36 | [b (line 84): false] ... && ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:23:123:36 | [b (line 84): true] ... && ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:28:123:31 | [b (line 84): false] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:28:123:31 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:124:9:124:35 | [b (line 84): false] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:124:9:124:36 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:124:9:124:36 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:124:27:124:27 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:124:27:124:34 | [b (line 84): false] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:126:9:126:26 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:126:9:126:26 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:126:13:126:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:126:17:126:20 | null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:126:24:126:25 | "" | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:9:127:40 | ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:24:127:24 | access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:24:127:38 | ... \|\| ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:29:127:32 | null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:37:127:38 | !... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:38:127:38 | access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:128:9:128:35 | call to method WriteLine | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:128:9:128:36 | ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:128:27:128:27 | access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:128:27:128:34 | access to property Length | Assert.cs:84:10:84:12 | M12 | | Assignments.cs:3:10:3:10 | enter M | Assignments.cs:3:10:3:10 | M | | Assignments.cs:3:10:3:10 | exit M | Assignments.cs:3:10:3:10 | M | | Assignments.cs:4:5:15:5 | {...} | Assignments.cs:3:10:3:10 | M | @@ -3635,6 +4144,76 @@ blockEnclosing | ArrayCreation.cs:5:12:5:13 | enter M2 | ArrayCreation.cs:5:12:5:13 | M2 | | ArrayCreation.cs:7:11:7:12 | enter M3 | ArrayCreation.cs:7:11:7:12 | M3 | | ArrayCreation.cs:9:12:9:13 | enter M4 | ArrayCreation.cs:9:12:9:13 | M4 | +| Assert.cs:7:10:7:11 | enter M1 | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:9:24:9:27 | null | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:9:31:9:32 | "" | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:14:10:14:11 | enter M2 | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:16:24:16:27 | null | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:16:31:16:32 | "" | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:21:10:21:11 | enter M3 | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:23:24:23:27 | null | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:23:31:23:32 | "" | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:28:10:28:11 | enter M4 | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:30:24:30:27 | null | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:30:31:30:32 | "" | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:35:10:35:11 | enter M5 | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:37:24:37:27 | null | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:37:31:37:32 | "" | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:42:10:42:11 | enter M6 | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:44:24:44:27 | null | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:44:31:44:32 | "" | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:49:10:49:11 | enter M7 | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:51:24:51:27 | null | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:51:31:51:32 | "" | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:58:24:58:27 | null | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:58:31:58:32 | "" | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:65:24:65:27 | null | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:65:31:65:32 | "" | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:72:24:72:27 | null | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:72:31:72:32 | "" | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:79:24:79:27 | null | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:79:31:79:32 | "" | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:37:119:38 | [b (line 84): false] !... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:37:127:38 | !... | Assert.cs:84:10:84:12 | M12 | | Assignments.cs:3:10:3:10 | enter M | Assignments.cs:3:10:3:10 | M | | Assignments.cs:14:18:14:35 | enter (...) => ... | Assignments.cs:14:18:14:35 | (...) => ... | | Assignments.cs:17:40:17:40 | enter + | Assignments.cs:17:40:17:40 | + | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected index cf3a8c054eb..7152bda7d85 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected @@ -307,6 +307,358 @@ | ArrayCreation.cs:9:43:9:50 | { ..., ... } | ArrayCreation.cs:9:45:9:45 | 2 | | ArrayCreation.cs:9:45:9:45 | 2 | ArrayCreation.cs:9:45:9:45 | 2 | | ArrayCreation.cs:9:48:9:48 | 3 | ArrayCreation.cs:9:48:9:48 | 3 | +| Assert.cs:8:5:12:5 | {...} | Assert.cs:8:5:12:5 | {...} | +| Assert.cs:9:9:9:33 | ... ...; | Assert.cs:9:9:9:33 | ... ...; | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:9:20:9:32 | ... ? ... : ... | +| Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:9:20:9:20 | access to parameter b | +| Assert.cs:9:20:9:32 | ... ? ... : ... | Assert.cs:9:20:9:32 | ... ? ... : ... | +| Assert.cs:9:24:9:27 | null | Assert.cs:9:24:9:27 | null | +| Assert.cs:9:31:9:32 | "" | Assert.cs:9:31:9:32 | "" | +| Assert.cs:10:9:10:31 | call to method Assert | Assert.cs:10:22:10:22 | access to local variable s | +| Assert.cs:10:9:10:32 | ...; | Assert.cs:10:9:10:32 | ...; | +| Assert.cs:10:22:10:22 | access to local variable s | Assert.cs:10:22:10:22 | access to local variable s | +| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:22:10:22 | access to local variable s | +| Assert.cs:10:27:10:30 | null | Assert.cs:10:27:10:30 | null | +| Assert.cs:11:9:11:35 | call to method WriteLine | Assert.cs:11:27:11:27 | access to local variable s | +| Assert.cs:11:9:11:36 | ...; | Assert.cs:11:9:11:36 | ...; | +| Assert.cs:11:27:11:27 | access to local variable s | Assert.cs:11:27:11:27 | access to local variable s | +| Assert.cs:11:27:11:34 | access to property Length | Assert.cs:11:27:11:27 | access to local variable s | +| Assert.cs:15:5:19:5 | {...} | Assert.cs:15:5:19:5 | {...} | +| Assert.cs:16:9:16:33 | ... ...; | Assert.cs:16:9:16:33 | ... ...; | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:16:20:16:32 | ... ? ... : ... | +| Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:16:20:16:20 | access to parameter b | +| Assert.cs:16:20:16:32 | ... ? ... : ... | Assert.cs:16:20:16:32 | ... ? ... : ... | +| Assert.cs:16:24:16:27 | null | Assert.cs:16:24:16:27 | null | +| Assert.cs:16:31:16:32 | "" | Assert.cs:16:31:16:32 | "" | +| Assert.cs:17:9:17:24 | call to method IsNull | Assert.cs:17:23:17:23 | access to local variable s | +| Assert.cs:17:9:17:25 | ...; | Assert.cs:17:9:17:25 | ...; | +| Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:17:23:17:23 | access to local variable s | +| Assert.cs:18:9:18:35 | call to method WriteLine | Assert.cs:18:27:18:27 | access to local variable s | +| Assert.cs:18:9:18:36 | ...; | Assert.cs:18:9:18:36 | ...; | +| Assert.cs:18:27:18:27 | access to local variable s | Assert.cs:18:27:18:27 | access to local variable s | +| Assert.cs:18:27:18:34 | access to property Length | Assert.cs:18:27:18:27 | access to local variable s | +| Assert.cs:22:5:26:5 | {...} | Assert.cs:22:5:26:5 | {...} | +| Assert.cs:23:9:23:33 | ... ...; | Assert.cs:23:9:23:33 | ... ...; | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:23:20:23:32 | ... ? ... : ... | +| Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:23:20:23:20 | access to parameter b | +| Assert.cs:23:20:23:32 | ... ? ... : ... | Assert.cs:23:20:23:32 | ... ? ... : ... | +| Assert.cs:23:24:23:27 | null | Assert.cs:23:24:23:27 | null | +| Assert.cs:23:31:23:32 | "" | Assert.cs:23:31:23:32 | "" | +| Assert.cs:24:9:24:27 | call to method IsNotNull | Assert.cs:24:26:24:26 | access to local variable s | +| Assert.cs:24:9:24:28 | ...; | Assert.cs:24:9:24:28 | ...; | +| Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:24:26:24:26 | access to local variable s | +| Assert.cs:25:9:25:35 | call to method WriteLine | Assert.cs:25:27:25:27 | access to local variable s | +| Assert.cs:25:9:25:36 | ...; | Assert.cs:25:9:25:36 | ...; | +| Assert.cs:25:27:25:27 | access to local variable s | Assert.cs:25:27:25:27 | access to local variable s | +| Assert.cs:25:27:25:34 | access to property Length | Assert.cs:25:27:25:27 | access to local variable s | +| Assert.cs:29:5:33:5 | {...} | Assert.cs:29:5:33:5 | {...} | +| Assert.cs:30:9:30:33 | ... ...; | Assert.cs:30:9:30:33 | ... ...; | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:30:20:30:32 | ... ? ... : ... | +| Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:30:20:30:20 | access to parameter b | +| Assert.cs:30:20:30:32 | ... ? ... : ... | Assert.cs:30:20:30:32 | ... ? ... : ... | +| Assert.cs:30:24:30:27 | null | Assert.cs:30:24:30:27 | null | +| Assert.cs:30:31:30:32 | "" | Assert.cs:30:31:30:32 | "" | +| Assert.cs:31:9:31:32 | call to method IsTrue | Assert.cs:31:23:31:23 | access to local variable s | +| Assert.cs:31:9:31:33 | ...; | Assert.cs:31:9:31:33 | ...; | +| Assert.cs:31:23:31:23 | access to local variable s | Assert.cs:31:23:31:23 | access to local variable s | +| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:23:31:23 | access to local variable s | +| Assert.cs:31:28:31:31 | null | Assert.cs:31:28:31:31 | null | +| Assert.cs:32:9:32:35 | call to method WriteLine | Assert.cs:32:27:32:27 | access to local variable s | +| Assert.cs:32:9:32:36 | ...; | Assert.cs:32:9:32:36 | ...; | +| Assert.cs:32:27:32:27 | access to local variable s | Assert.cs:32:27:32:27 | access to local variable s | +| Assert.cs:32:27:32:34 | access to property Length | Assert.cs:32:27:32:27 | access to local variable s | +| Assert.cs:36:5:40:5 | {...} | Assert.cs:36:5:40:5 | {...} | +| Assert.cs:37:9:37:33 | ... ...; | Assert.cs:37:9:37:33 | ... ...; | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:37:20:37:32 | ... ? ... : ... | +| Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:37:20:37:20 | access to parameter b | +| Assert.cs:37:20:37:32 | ... ? ... : ... | Assert.cs:37:20:37:32 | ... ? ... : ... | +| Assert.cs:37:24:37:27 | null | Assert.cs:37:24:37:27 | null | +| Assert.cs:37:31:37:32 | "" | Assert.cs:37:31:37:32 | "" | +| Assert.cs:38:9:38:32 | call to method IsTrue | Assert.cs:38:23:38:23 | access to local variable s | +| Assert.cs:38:9:38:33 | ...; | Assert.cs:38:9:38:33 | ...; | +| Assert.cs:38:23:38:23 | access to local variable s | Assert.cs:38:23:38:23 | access to local variable s | +| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:23:38:23 | access to local variable s | +| Assert.cs:38:28:38:31 | null | Assert.cs:38:28:38:31 | null | +| Assert.cs:39:9:39:35 | call to method WriteLine | Assert.cs:39:27:39:27 | access to local variable s | +| Assert.cs:39:9:39:36 | ...; | Assert.cs:39:9:39:36 | ...; | +| Assert.cs:39:27:39:27 | access to local variable s | Assert.cs:39:27:39:27 | access to local variable s | +| Assert.cs:39:27:39:34 | access to property Length | Assert.cs:39:27:39:27 | access to local variable s | +| Assert.cs:43:5:47:5 | {...} | Assert.cs:43:5:47:5 | {...} | +| Assert.cs:44:9:44:33 | ... ...; | Assert.cs:44:9:44:33 | ... ...; | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:44:20:44:32 | ... ? ... : ... | +| Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:44:20:44:20 | access to parameter b | +| Assert.cs:44:20:44:32 | ... ? ... : ... | Assert.cs:44:20:44:32 | ... ? ... : ... | +| Assert.cs:44:24:44:27 | null | Assert.cs:44:24:44:27 | null | +| Assert.cs:44:31:44:32 | "" | Assert.cs:44:31:44:32 | "" | +| Assert.cs:45:9:45:33 | call to method IsFalse | Assert.cs:45:24:45:24 | access to local variable s | +| Assert.cs:45:9:45:34 | ...; | Assert.cs:45:9:45:34 | ...; | +| Assert.cs:45:24:45:24 | access to local variable s | Assert.cs:45:24:45:24 | access to local variable s | +| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:24:45:24 | access to local variable s | +| Assert.cs:45:29:45:32 | null | Assert.cs:45:29:45:32 | null | +| Assert.cs:46:9:46:35 | call to method WriteLine | Assert.cs:46:27:46:27 | access to local variable s | +| Assert.cs:46:9:46:36 | ...; | Assert.cs:46:9:46:36 | ...; | +| Assert.cs:46:27:46:27 | access to local variable s | Assert.cs:46:27:46:27 | access to local variable s | +| Assert.cs:46:27:46:34 | access to property Length | Assert.cs:46:27:46:27 | access to local variable s | +| Assert.cs:50:5:54:5 | {...} | Assert.cs:50:5:54:5 | {...} | +| Assert.cs:51:9:51:33 | ... ...; | Assert.cs:51:9:51:33 | ... ...; | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:51:20:51:32 | ... ? ... : ... | +| Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:51:20:51:20 | access to parameter b | +| Assert.cs:51:20:51:32 | ... ? ... : ... | Assert.cs:51:20:51:32 | ... ? ... : ... | +| Assert.cs:51:24:51:27 | null | Assert.cs:51:24:51:27 | null | +| Assert.cs:51:31:51:32 | "" | Assert.cs:51:31:51:32 | "" | +| Assert.cs:52:9:52:33 | call to method IsFalse | Assert.cs:52:24:52:24 | access to local variable s | +| Assert.cs:52:9:52:34 | ...; | Assert.cs:52:9:52:34 | ...; | +| Assert.cs:52:24:52:24 | access to local variable s | Assert.cs:52:24:52:24 | access to local variable s | +| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:24:52:24 | access to local variable s | +| Assert.cs:52:29:52:32 | null | Assert.cs:52:29:52:32 | null | +| Assert.cs:53:9:53:35 | call to method WriteLine | Assert.cs:53:27:53:27 | access to local variable s | +| Assert.cs:53:9:53:36 | ...; | Assert.cs:53:9:53:36 | ...; | +| Assert.cs:53:27:53:27 | access to local variable s | Assert.cs:53:27:53:27 | access to local variable s | +| Assert.cs:53:27:53:34 | access to property Length | Assert.cs:53:27:53:27 | access to local variable s | +| Assert.cs:57:5:61:5 | {...} | Assert.cs:57:5:61:5 | {...} | +| Assert.cs:58:9:58:33 | ... ...; | Assert.cs:58:9:58:33 | ... ...; | +| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:58:20:58:32 | ... ? ... : ... | +| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | +| Assert.cs:58:20:58:32 | ... ? ... : ... | Assert.cs:58:20:58:32 | ... ? ... : ... | +| Assert.cs:58:24:58:27 | null | Assert.cs:58:24:58:27 | null | +| Assert.cs:58:31:58:32 | "" | Assert.cs:58:31:58:32 | "" | +| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:59:23:59:36 | ... && ... | +| Assert.cs:59:9:59:38 | ...; | Assert.cs:59:9:59:38 | ...; | +| Assert.cs:59:23:59:23 | access to local variable s | Assert.cs:59:23:59:23 | access to local variable s | +| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:23:59:23 | access to local variable s | +| Assert.cs:59:23:59:36 | ... && ... | Assert.cs:59:23:59:36 | ... && ... | +| Assert.cs:59:28:59:31 | null | Assert.cs:59:28:59:31 | null | +| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:59:36:59:36 | access to parameter b | +| Assert.cs:60:9:60:35 | call to method WriteLine | Assert.cs:60:27:60:27 | access to local variable s | +| Assert.cs:60:9:60:36 | ...; | Assert.cs:60:9:60:36 | ...; | +| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:60:27:60:27 | access to local variable s | +| Assert.cs:60:27:60:34 | access to property Length | Assert.cs:60:27:60:27 | access to local variable s | +| Assert.cs:64:5:68:5 | {...} | Assert.cs:64:5:68:5 | {...} | +| Assert.cs:65:9:65:33 | ... ...; | Assert.cs:65:9:65:33 | ... ...; | +| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:65:20:65:32 | ... ? ... : ... | +| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | +| Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:65:20:65:32 | ... ? ... : ... | +| Assert.cs:65:24:65:27 | null | Assert.cs:65:24:65:27 | null | +| Assert.cs:65:31:65:32 | "" | Assert.cs:65:31:65:32 | "" | +| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:66:24:66:37 | ... \|\| ... | +| Assert.cs:66:9:66:39 | ...; | Assert.cs:66:9:66:39 | ...; | +| Assert.cs:66:24:66:24 | access to local variable s | Assert.cs:66:24:66:24 | access to local variable s | +| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:24:66:24 | access to local variable s | +| Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:66:24:66:37 | ... \|\| ... | +| Assert.cs:66:29:66:32 | null | Assert.cs:66:29:66:32 | null | +| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:66:37:66:37 | access to parameter b | +| Assert.cs:67:9:67:35 | call to method WriteLine | Assert.cs:67:27:67:27 | access to local variable s | +| Assert.cs:67:9:67:36 | ...; | Assert.cs:67:9:67:36 | ...; | +| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:67:27:67:27 | access to local variable s | +| Assert.cs:67:27:67:34 | access to property Length | Assert.cs:67:27:67:27 | access to local variable s | +| Assert.cs:71:5:75:5 | {...} | Assert.cs:71:5:75:5 | {...} | +| Assert.cs:72:9:72:33 | ... ...; | Assert.cs:72:9:72:33 | ... ...; | +| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:72:20:72:32 | ... ? ... : ... | +| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | +| Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:72:20:72:32 | ... ? ... : ... | +| Assert.cs:72:24:72:27 | null | Assert.cs:72:24:72:27 | null | +| Assert.cs:72:31:72:32 | "" | Assert.cs:72:31:72:32 | "" | +| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:73:23:73:36 | ... && ... | +| Assert.cs:73:9:73:38 | ...; | Assert.cs:73:9:73:38 | ...; | +| Assert.cs:73:23:73:23 | access to local variable s | Assert.cs:73:23:73:23 | access to local variable s | +| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:23:73:23 | access to local variable s | +| Assert.cs:73:23:73:36 | ... && ... | Assert.cs:73:23:73:36 | ... && ... | +| Assert.cs:73:28:73:31 | null | Assert.cs:73:28:73:31 | null | +| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:73:36:73:36 | access to parameter b | +| Assert.cs:74:9:74:35 | call to method WriteLine | Assert.cs:74:27:74:27 | access to local variable s | +| Assert.cs:74:9:74:36 | ...; | Assert.cs:74:9:74:36 | ...; | +| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:74:27:74:27 | access to local variable s | +| Assert.cs:74:27:74:34 | access to property Length | Assert.cs:74:27:74:27 | access to local variable s | +| Assert.cs:78:5:82:5 | {...} | Assert.cs:78:5:82:5 | {...} | +| Assert.cs:79:9:79:33 | ... ...; | Assert.cs:79:9:79:33 | ... ...; | +| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:79:20:79:32 | ... ? ... : ... | +| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | +| Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:79:20:79:32 | ... ? ... : ... | +| Assert.cs:79:24:79:27 | null | Assert.cs:79:24:79:27 | null | +| Assert.cs:79:31:79:32 | "" | Assert.cs:79:31:79:32 | "" | +| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:80:24:80:37 | ... \|\| ... | +| Assert.cs:80:9:80:39 | ...; | Assert.cs:80:9:80:39 | ...; | +| Assert.cs:80:24:80:24 | access to local variable s | Assert.cs:80:24:80:24 | access to local variable s | +| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:24:80:24 | access to local variable s | +| Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:24:80:37 | ... \|\| ... | +| Assert.cs:80:29:80:32 | null | Assert.cs:80:29:80:32 | null | +| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:80:37:80:37 | access to parameter b | +| Assert.cs:81:9:81:35 | call to method WriteLine | Assert.cs:81:27:81:27 | access to local variable s | +| Assert.cs:81:9:81:36 | ...; | Assert.cs:81:9:81:36 | ...; | +| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:81:27:81:27 | access to local variable s | +| Assert.cs:81:27:81:34 | access to property Length | Assert.cs:81:27:81:27 | access to local variable s | +| Assert.cs:85:5:129:5 | {...} | Assert.cs:85:5:129:5 | {...} | +| Assert.cs:86:9:86:33 | ... ...; | Assert.cs:86:9:86:33 | ... ...; | +| Assert.cs:86:16:86:32 | String s = ... | Assert.cs:86:20:86:32 | ... ? ... : ... | +| Assert.cs:86:20:86:20 | access to parameter b | Assert.cs:86:20:86:20 | access to parameter b | +| Assert.cs:86:20:86:32 | ... ? ... : ... | Assert.cs:86:20:86:32 | ... ? ... : ... | +| Assert.cs:86:24:86:27 | null | Assert.cs:86:24:86:27 | null | +| Assert.cs:86:31:86:32 | "" | Assert.cs:86:31:86:32 | "" | +| Assert.cs:87:9:87:31 | call to method Assert | Assert.cs:87:22:87:22 | access to local variable s | +| Assert.cs:87:9:87:32 | ...; | Assert.cs:87:9:87:32 | ...; | +| Assert.cs:87:22:87:22 | access to local variable s | Assert.cs:87:22:87:22 | access to local variable s | +| Assert.cs:87:22:87:30 | ... != ... | Assert.cs:87:22:87:22 | access to local variable s | +| Assert.cs:87:27:87:30 | null | Assert.cs:87:27:87:30 | null | +| Assert.cs:88:9:88:35 | call to method WriteLine | Assert.cs:88:27:88:27 | access to local variable s | +| Assert.cs:88:9:88:36 | ...; | Assert.cs:88:9:88:36 | ...; | +| Assert.cs:88:27:88:27 | access to local variable s | Assert.cs:88:27:88:27 | access to local variable s | +| Assert.cs:88:27:88:34 | access to property Length | Assert.cs:88:27:88:27 | access to local variable s | +| Assert.cs:90:9:90:25 | ... = ... | Assert.cs:90:13:90:25 | ... ? ... : ... | +| Assert.cs:90:9:90:26 | ...; | Assert.cs:90:9:90:26 | ...; | +| Assert.cs:90:13:90:13 | access to parameter b | Assert.cs:90:13:90:13 | access to parameter b | +| Assert.cs:90:13:90:25 | ... ? ... : ... | Assert.cs:90:13:90:25 | ... ? ... : ... | +| Assert.cs:90:17:90:20 | null | Assert.cs:90:17:90:20 | null | +| Assert.cs:90:24:90:25 | "" | Assert.cs:90:24:90:25 | "" | +| Assert.cs:91:9:91:24 | call to method IsNull | Assert.cs:91:23:91:23 | access to local variable s | +| Assert.cs:91:9:91:25 | ...; | Assert.cs:91:9:91:25 | ...; | +| Assert.cs:91:23:91:23 | access to local variable s | Assert.cs:91:23:91:23 | access to local variable s | +| Assert.cs:92:9:92:35 | call to method WriteLine | Assert.cs:92:27:92:27 | access to local variable s | +| Assert.cs:92:9:92:36 | ...; | Assert.cs:92:9:92:36 | ...; | +| Assert.cs:92:27:92:27 | access to local variable s | Assert.cs:92:27:92:27 | access to local variable s | +| Assert.cs:92:27:92:34 | access to property Length | Assert.cs:92:27:92:27 | access to local variable s | +| Assert.cs:94:9:94:25 | ... = ... | Assert.cs:94:13:94:25 | ... ? ... : ... | +| Assert.cs:94:9:94:26 | ...; | Assert.cs:94:9:94:26 | ...; | +| Assert.cs:94:13:94:13 | access to parameter b | Assert.cs:94:13:94:13 | access to parameter b | +| Assert.cs:94:13:94:25 | ... ? ... : ... | Assert.cs:94:13:94:25 | ... ? ... : ... | +| Assert.cs:94:17:94:20 | null | Assert.cs:94:17:94:20 | null | +| Assert.cs:94:24:94:25 | "" | Assert.cs:94:24:94:25 | "" | +| Assert.cs:95:9:95:27 | call to method IsNotNull | Assert.cs:95:26:95:26 | access to local variable s | +| Assert.cs:95:9:95:28 | ...; | Assert.cs:95:9:95:28 | ...; | +| Assert.cs:95:26:95:26 | access to local variable s | Assert.cs:95:26:95:26 | access to local variable s | +| Assert.cs:96:9:96:35 | call to method WriteLine | Assert.cs:96:27:96:27 | access to local variable s | +| Assert.cs:96:9:96:36 | ...; | Assert.cs:96:9:96:36 | ...; | +| Assert.cs:96:27:96:27 | access to local variable s | Assert.cs:96:27:96:27 | access to local variable s | +| Assert.cs:96:27:96:34 | access to property Length | Assert.cs:96:27:96:27 | access to local variable s | +| Assert.cs:98:9:98:25 | ... = ... | Assert.cs:98:13:98:25 | ... ? ... : ... | +| Assert.cs:98:9:98:26 | ...; | Assert.cs:98:9:98:26 | ...; | +| Assert.cs:98:13:98:13 | access to parameter b | Assert.cs:98:13:98:13 | access to parameter b | +| Assert.cs:98:13:98:25 | ... ? ... : ... | Assert.cs:98:13:98:25 | ... ? ... : ... | +| Assert.cs:98:17:98:20 | null | Assert.cs:98:17:98:20 | null | +| Assert.cs:98:24:98:25 | "" | Assert.cs:98:24:98:25 | "" | +| Assert.cs:99:9:99:32 | call to method IsTrue | Assert.cs:99:23:99:23 | access to local variable s | +| Assert.cs:99:9:99:33 | ...; | Assert.cs:99:9:99:33 | ...; | +| Assert.cs:99:23:99:23 | access to local variable s | Assert.cs:99:23:99:23 | access to local variable s | +| Assert.cs:99:23:99:31 | ... == ... | Assert.cs:99:23:99:23 | access to local variable s | +| Assert.cs:99:28:99:31 | null | Assert.cs:99:28:99:31 | null | +| Assert.cs:100:9:100:35 | call to method WriteLine | Assert.cs:100:27:100:27 | access to local variable s | +| Assert.cs:100:9:100:36 | ...; | Assert.cs:100:9:100:36 | ...; | +| Assert.cs:100:27:100:27 | access to local variable s | Assert.cs:100:27:100:27 | access to local variable s | +| Assert.cs:100:27:100:34 | access to property Length | Assert.cs:100:27:100:27 | access to local variable s | +| Assert.cs:102:9:102:25 | ... = ... | Assert.cs:102:13:102:25 | ... ? ... : ... | +| Assert.cs:102:9:102:26 | ...; | Assert.cs:102:9:102:26 | ...; | +| Assert.cs:102:13:102:13 | access to parameter b | Assert.cs:102:13:102:13 | access to parameter b | +| Assert.cs:102:13:102:25 | ... ? ... : ... | Assert.cs:102:13:102:25 | ... ? ... : ... | +| Assert.cs:102:17:102:20 | null | Assert.cs:102:17:102:20 | null | +| Assert.cs:102:24:102:25 | "" | Assert.cs:102:24:102:25 | "" | +| Assert.cs:103:9:103:32 | call to method IsTrue | Assert.cs:103:23:103:23 | access to local variable s | +| Assert.cs:103:9:103:33 | ...; | Assert.cs:103:9:103:33 | ...; | +| Assert.cs:103:23:103:23 | access to local variable s | Assert.cs:103:23:103:23 | access to local variable s | +| Assert.cs:103:23:103:31 | ... != ... | Assert.cs:103:23:103:23 | access to local variable s | +| Assert.cs:103:28:103:31 | null | Assert.cs:103:28:103:31 | null | +| Assert.cs:104:9:104:35 | call to method WriteLine | Assert.cs:104:27:104:27 | access to local variable s | +| Assert.cs:104:9:104:36 | ...; | Assert.cs:104:9:104:36 | ...; | +| Assert.cs:104:27:104:27 | access to local variable s | Assert.cs:104:27:104:27 | access to local variable s | +| Assert.cs:104:27:104:34 | access to property Length | Assert.cs:104:27:104:27 | access to local variable s | +| Assert.cs:106:9:106:25 | ... = ... | Assert.cs:106:13:106:25 | ... ? ... : ... | +| Assert.cs:106:9:106:26 | ...; | Assert.cs:106:9:106:26 | ...; | +| Assert.cs:106:13:106:13 | access to parameter b | Assert.cs:106:13:106:13 | access to parameter b | +| Assert.cs:106:13:106:25 | ... ? ... : ... | Assert.cs:106:13:106:25 | ... ? ... : ... | +| Assert.cs:106:17:106:20 | null | Assert.cs:106:17:106:20 | null | +| Assert.cs:106:24:106:25 | "" | Assert.cs:106:24:106:25 | "" | +| Assert.cs:107:9:107:33 | call to method IsFalse | Assert.cs:107:24:107:24 | access to local variable s | +| Assert.cs:107:9:107:34 | ...; | Assert.cs:107:9:107:34 | ...; | +| Assert.cs:107:24:107:24 | access to local variable s | Assert.cs:107:24:107:24 | access to local variable s | +| Assert.cs:107:24:107:32 | ... != ... | Assert.cs:107:24:107:24 | access to local variable s | +| Assert.cs:107:29:107:32 | null | Assert.cs:107:29:107:32 | null | +| Assert.cs:108:9:108:35 | call to method WriteLine | Assert.cs:108:27:108:27 | access to local variable s | +| Assert.cs:108:9:108:36 | ...; | Assert.cs:108:9:108:36 | ...; | +| Assert.cs:108:27:108:27 | access to local variable s | Assert.cs:108:27:108:27 | access to local variable s | +| Assert.cs:108:27:108:34 | access to property Length | Assert.cs:108:27:108:27 | access to local variable s | +| Assert.cs:110:9:110:25 | ... = ... | Assert.cs:110:13:110:25 | ... ? ... : ... | +| Assert.cs:110:9:110:26 | ...; | Assert.cs:110:9:110:26 | ...; | +| Assert.cs:110:13:110:13 | access to parameter b | Assert.cs:110:13:110:13 | access to parameter b | +| Assert.cs:110:13:110:25 | ... ? ... : ... | Assert.cs:110:13:110:25 | ... ? ... : ... | +| Assert.cs:110:17:110:20 | null | Assert.cs:110:17:110:20 | null | +| Assert.cs:110:24:110:25 | "" | Assert.cs:110:24:110:25 | "" | +| Assert.cs:111:9:111:33 | call to method IsFalse | Assert.cs:111:24:111:24 | access to local variable s | +| Assert.cs:111:9:111:34 | ...; | Assert.cs:111:9:111:34 | ...; | +| Assert.cs:111:24:111:24 | access to local variable s | Assert.cs:111:24:111:24 | access to local variable s | +| Assert.cs:111:24:111:32 | ... == ... | Assert.cs:111:24:111:24 | access to local variable s | +| Assert.cs:111:29:111:32 | null | Assert.cs:111:29:111:32 | null | +| Assert.cs:112:9:112:35 | call to method WriteLine | Assert.cs:112:27:112:27 | access to local variable s | +| Assert.cs:112:9:112:36 | ...; | Assert.cs:112:9:112:36 | ...; | +| Assert.cs:112:27:112:27 | access to local variable s | Assert.cs:112:27:112:27 | access to local variable s | +| Assert.cs:112:27:112:34 | access to property Length | Assert.cs:112:27:112:27 | access to local variable s | +| Assert.cs:114:9:114:25 | ... = ... | Assert.cs:114:13:114:25 | ... ? ... : ... | +| Assert.cs:114:9:114:26 | ...; | Assert.cs:114:9:114:26 | ...; | +| Assert.cs:114:13:114:13 | access to parameter b | Assert.cs:114:13:114:13 | access to parameter b | +| Assert.cs:114:13:114:25 | ... ? ... : ... | Assert.cs:114:13:114:25 | ... ? ... : ... | +| Assert.cs:114:17:114:20 | null | Assert.cs:114:17:114:20 | null | +| Assert.cs:114:24:114:25 | "" | Assert.cs:114:24:114:25 | "" | +| Assert.cs:115:9:115:37 | call to method IsTrue | Assert.cs:115:23:115:36 | ... && ... | +| Assert.cs:115:9:115:38 | ...; | Assert.cs:115:9:115:38 | ...; | +| Assert.cs:115:23:115:23 | access to local variable s | Assert.cs:115:23:115:23 | access to local variable s | +| Assert.cs:115:23:115:31 | ... != ... | Assert.cs:115:23:115:23 | access to local variable s | +| Assert.cs:115:23:115:36 | ... && ... | Assert.cs:115:23:115:36 | ... && ... | +| Assert.cs:115:28:115:31 | null | Assert.cs:115:28:115:31 | null | +| Assert.cs:115:36:115:36 | access to parameter b | Assert.cs:115:36:115:36 | access to parameter b | +| Assert.cs:116:9:116:35 | call to method WriteLine | Assert.cs:116:27:116:27 | access to local variable s | +| Assert.cs:116:9:116:36 | ...; | Assert.cs:116:9:116:36 | ...; | +| Assert.cs:116:27:116:27 | access to local variable s | Assert.cs:116:27:116:27 | access to local variable s | +| Assert.cs:116:27:116:34 | access to property Length | Assert.cs:116:27:116:27 | access to local variable s | +| Assert.cs:118:9:118:25 | ... = ... | Assert.cs:118:13:118:25 | ... ? ... : ... | +| Assert.cs:118:9:118:26 | ...; | Assert.cs:118:9:118:26 | ...; | +| Assert.cs:118:13:118:13 | access to parameter b | Assert.cs:118:13:118:13 | access to parameter b | +| Assert.cs:118:13:118:25 | ... ? ... : ... | Assert.cs:118:13:118:25 | ... ? ... : ... | +| Assert.cs:118:17:118:20 | null | Assert.cs:118:17:118:20 | null | +| Assert.cs:118:24:118:25 | "" | Assert.cs:118:24:118:25 | "" | +| Assert.cs:119:9:119:39 | call to method IsFalse | Assert.cs:119:24:119:38 | ... \|\| ... | +| Assert.cs:119:9:119:40 | ...; | Assert.cs:119:9:119:40 | ...; | +| Assert.cs:119:24:119:24 | access to local variable s | Assert.cs:119:24:119:24 | access to local variable s | +| Assert.cs:119:24:119:32 | ... == ... | Assert.cs:119:24:119:24 | access to local variable s | +| Assert.cs:119:24:119:38 | ... \|\| ... | Assert.cs:119:24:119:38 | ... \|\| ... | +| Assert.cs:119:29:119:32 | null | Assert.cs:119:29:119:32 | null | +| Assert.cs:119:37:119:38 | !... | Assert.cs:119:37:119:38 | !... | +| Assert.cs:119:38:119:38 | access to parameter b | Assert.cs:119:38:119:38 | access to parameter b | +| Assert.cs:120:9:120:35 | call to method WriteLine | Assert.cs:120:27:120:27 | access to local variable s | +| Assert.cs:120:9:120:36 | ...; | Assert.cs:120:9:120:36 | ...; | +| Assert.cs:120:27:120:27 | access to local variable s | Assert.cs:120:27:120:27 | access to local variable s | +| Assert.cs:120:27:120:34 | access to property Length | Assert.cs:120:27:120:27 | access to local variable s | +| Assert.cs:122:9:122:25 | ... = ... | Assert.cs:122:13:122:25 | ... ? ... : ... | +| Assert.cs:122:9:122:26 | ...; | Assert.cs:122:9:122:26 | ...; | +| Assert.cs:122:13:122:13 | access to parameter b | Assert.cs:122:13:122:13 | access to parameter b | +| Assert.cs:122:13:122:25 | ... ? ... : ... | Assert.cs:122:13:122:25 | ... ? ... : ... | +| Assert.cs:122:17:122:20 | null | Assert.cs:122:17:122:20 | null | +| Assert.cs:122:24:122:25 | "" | Assert.cs:122:24:122:25 | "" | +| Assert.cs:123:9:123:37 | call to method IsTrue | Assert.cs:123:23:123:36 | ... && ... | +| Assert.cs:123:9:123:38 | ...; | Assert.cs:123:9:123:38 | ...; | +| Assert.cs:123:23:123:23 | access to local variable s | Assert.cs:123:23:123:23 | access to local variable s | +| Assert.cs:123:23:123:31 | ... == ... | Assert.cs:123:23:123:23 | access to local variable s | +| Assert.cs:123:23:123:36 | ... && ... | Assert.cs:123:23:123:36 | ... && ... | +| Assert.cs:123:28:123:31 | null | Assert.cs:123:28:123:31 | null | +| Assert.cs:123:36:123:36 | access to parameter b | Assert.cs:123:36:123:36 | access to parameter b | +| Assert.cs:124:9:124:35 | call to method WriteLine | Assert.cs:124:27:124:27 | access to local variable s | +| Assert.cs:124:9:124:36 | ...; | Assert.cs:124:9:124:36 | ...; | +| Assert.cs:124:27:124:27 | access to local variable s | Assert.cs:124:27:124:27 | access to local variable s | +| Assert.cs:124:27:124:34 | access to property Length | Assert.cs:124:27:124:27 | access to local variable s | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:126:13:126:25 | ... ? ... : ... | +| Assert.cs:126:9:126:26 | ...; | Assert.cs:126:9:126:26 | ...; | +| Assert.cs:126:13:126:13 | access to parameter b | Assert.cs:126:13:126:13 | access to parameter b | +| Assert.cs:126:13:126:25 | ... ? ... : ... | Assert.cs:126:13:126:25 | ... ? ... : ... | +| Assert.cs:126:17:126:20 | null | Assert.cs:126:17:126:20 | null | +| Assert.cs:126:24:126:25 | "" | Assert.cs:126:24:126:25 | "" | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:127:24:127:38 | ... \|\| ... | +| Assert.cs:127:9:127:40 | ...; | Assert.cs:127:9:127:40 | ...; | +| Assert.cs:127:24:127:24 | access to local variable s | Assert.cs:127:24:127:24 | access to local variable s | +| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:24:127:24 | access to local variable s | +| Assert.cs:127:24:127:38 | ... \|\| ... | Assert.cs:127:24:127:38 | ... \|\| ... | +| Assert.cs:127:29:127:32 | null | Assert.cs:127:29:127:32 | null | +| Assert.cs:127:37:127:38 | !... | Assert.cs:127:37:127:38 | !... | +| Assert.cs:127:38:127:38 | access to parameter b | Assert.cs:127:38:127:38 | access to parameter b | +| Assert.cs:128:9:128:35 | call to method WriteLine | Assert.cs:128:27:128:27 | access to local variable s | +| Assert.cs:128:9:128:36 | ...; | Assert.cs:128:9:128:36 | ...; | +| Assert.cs:128:27:128:27 | access to local variable s | Assert.cs:128:27:128:27 | access to local variable s | +| Assert.cs:128:27:128:34 | access to property Length | Assert.cs:128:27:128:27 | access to local variable s | | Assignments.cs:4:5:15:5 | {...} | Assignments.cs:4:5:15:5 | {...} | | Assignments.cs:5:9:5:18 | ... ...; | Assignments.cs:5:9:5:18 | ... ...; | | Assignments.cs:5:13:5:17 | Int32 x = ... | Assignments.cs:5:17:5:17 | 0 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index 428ddfeca24..0b700ae4848 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -307,6 +307,418 @@ | ArrayCreation.cs:9:43:9:50 | { ..., ... } | ArrayCreation.cs:9:43:9:50 | { ..., ... } | normal | | ArrayCreation.cs:9:45:9:45 | 2 | ArrayCreation.cs:9:45:9:45 | 2 | normal | | ArrayCreation.cs:9:48:9:48 | 3 | ArrayCreation.cs:9:48:9:48 | 3 | normal | +| Assert.cs:8:5:12:5 | {...} | Assert.cs:11:9:11:35 | call to method WriteLine | normal | +| Assert.cs:9:9:9:33 | ... ...; | Assert.cs:9:16:9:32 | String s = ... | normal | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:9:16:9:32 | String s = ... | normal | +| Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:9:20:9:20 | access to parameter b | false | +| Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:9:20:9:20 | access to parameter b | true | +| Assert.cs:9:20:9:32 | ... ? ... : ... | Assert.cs:9:24:9:27 | null | normal | +| Assert.cs:9:20:9:32 | ... ? ... : ... | Assert.cs:9:31:9:32 | "" | normal | +| Assert.cs:9:24:9:27 | null | Assert.cs:9:24:9:27 | null | normal | +| Assert.cs:9:31:9:32 | "" | Assert.cs:9:31:9:32 | "" | normal | +| Assert.cs:10:9:10:31 | call to method Assert | Assert.cs:10:9:10:31 | call to method Assert | normal | +| Assert.cs:10:9:10:32 | ...; | Assert.cs:10:9:10:31 | call to method Assert | normal | +| Assert.cs:10:22:10:22 | access to local variable s | Assert.cs:10:22:10:22 | access to local variable s | normal | +| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:22:10:30 | ... != ... | normal | +| Assert.cs:10:27:10:30 | null | Assert.cs:10:27:10:30 | null | normal | +| Assert.cs:11:9:11:35 | call to method WriteLine | Assert.cs:11:9:11:35 | call to method WriteLine | normal | +| Assert.cs:11:9:11:36 | ...; | Assert.cs:11:9:11:35 | call to method WriteLine | normal | +| Assert.cs:11:27:11:27 | access to local variable s | Assert.cs:11:27:11:27 | access to local variable s | normal | +| Assert.cs:11:27:11:34 | access to property Length | Assert.cs:11:27:11:34 | access to property Length | normal | +| Assert.cs:15:5:19:5 | {...} | Assert.cs:18:9:18:35 | call to method WriteLine | normal | +| Assert.cs:16:9:16:33 | ... ...; | Assert.cs:16:16:16:32 | String s = ... | normal | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:16:16:16:32 | String s = ... | normal | +| Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:16:20:16:20 | access to parameter b | false | +| Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:16:20:16:20 | access to parameter b | true | +| Assert.cs:16:20:16:32 | ... ? ... : ... | Assert.cs:16:24:16:27 | null | normal | +| Assert.cs:16:20:16:32 | ... ? ... : ... | Assert.cs:16:31:16:32 | "" | normal | +| Assert.cs:16:24:16:27 | null | Assert.cs:16:24:16:27 | null | normal | +| Assert.cs:16:31:16:32 | "" | Assert.cs:16:31:16:32 | "" | normal | +| Assert.cs:17:9:17:24 | call to method IsNull | Assert.cs:17:9:17:24 | call to method IsNull | normal | +| Assert.cs:17:9:17:25 | ...; | Assert.cs:17:9:17:24 | call to method IsNull | normal | +| Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:17:23:17:23 | access to local variable s | normal | +| Assert.cs:18:9:18:35 | call to method WriteLine | Assert.cs:18:9:18:35 | call to method WriteLine | normal | +| Assert.cs:18:9:18:36 | ...; | Assert.cs:18:9:18:35 | call to method WriteLine | normal | +| Assert.cs:18:27:18:27 | access to local variable s | Assert.cs:18:27:18:27 | access to local variable s | normal | +| Assert.cs:18:27:18:34 | access to property Length | Assert.cs:18:27:18:34 | access to property Length | normal | +| Assert.cs:22:5:26:5 | {...} | Assert.cs:25:9:25:35 | call to method WriteLine | normal | +| Assert.cs:23:9:23:33 | ... ...; | Assert.cs:23:16:23:32 | String s = ... | normal | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:23:16:23:32 | String s = ... | normal | +| Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:23:20:23:20 | access to parameter b | false | +| Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:23:20:23:20 | access to parameter b | true | +| Assert.cs:23:20:23:32 | ... ? ... : ... | Assert.cs:23:24:23:27 | null | normal | +| Assert.cs:23:20:23:32 | ... ? ... : ... | Assert.cs:23:31:23:32 | "" | normal | +| Assert.cs:23:24:23:27 | null | Assert.cs:23:24:23:27 | null | normal | +| Assert.cs:23:31:23:32 | "" | Assert.cs:23:31:23:32 | "" | normal | +| Assert.cs:24:9:24:27 | call to method IsNotNull | Assert.cs:24:9:24:27 | call to method IsNotNull | normal | +| Assert.cs:24:9:24:28 | ...; | Assert.cs:24:9:24:27 | call to method IsNotNull | normal | +| Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:24:26:24:26 | access to local variable s | normal | +| Assert.cs:25:9:25:35 | call to method WriteLine | Assert.cs:25:9:25:35 | call to method WriteLine | normal | +| Assert.cs:25:9:25:36 | ...; | Assert.cs:25:9:25:35 | call to method WriteLine | normal | +| Assert.cs:25:27:25:27 | access to local variable s | Assert.cs:25:27:25:27 | access to local variable s | normal | +| Assert.cs:25:27:25:34 | access to property Length | Assert.cs:25:27:25:34 | access to property Length | normal | +| Assert.cs:29:5:33:5 | {...} | Assert.cs:32:9:32:35 | call to method WriteLine | normal | +| Assert.cs:30:9:30:33 | ... ...; | Assert.cs:30:16:30:32 | String s = ... | normal | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:30:16:30:32 | String s = ... | normal | +| Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:30:20:30:20 | access to parameter b | false | +| Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:30:20:30:20 | access to parameter b | true | +| Assert.cs:30:20:30:32 | ... ? ... : ... | Assert.cs:30:24:30:27 | null | normal | +| Assert.cs:30:20:30:32 | ... ? ... : ... | Assert.cs:30:31:30:32 | "" | normal | +| Assert.cs:30:24:30:27 | null | Assert.cs:30:24:30:27 | null | normal | +| Assert.cs:30:31:30:32 | "" | Assert.cs:30:31:30:32 | "" | normal | +| Assert.cs:31:9:31:32 | call to method IsTrue | Assert.cs:31:9:31:32 | call to method IsTrue | normal | +| Assert.cs:31:9:31:33 | ...; | Assert.cs:31:9:31:32 | call to method IsTrue | normal | +| Assert.cs:31:23:31:23 | access to local variable s | Assert.cs:31:23:31:23 | access to local variable s | normal | +| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:23:31:31 | ... == ... | normal | +| Assert.cs:31:28:31:31 | null | Assert.cs:31:28:31:31 | null | normal | +| Assert.cs:32:9:32:35 | call to method WriteLine | Assert.cs:32:9:32:35 | call to method WriteLine | normal | +| Assert.cs:32:9:32:36 | ...; | Assert.cs:32:9:32:35 | call to method WriteLine | normal | +| Assert.cs:32:27:32:27 | access to local variable s | Assert.cs:32:27:32:27 | access to local variable s | normal | +| Assert.cs:32:27:32:34 | access to property Length | Assert.cs:32:27:32:34 | access to property Length | normal | +| Assert.cs:36:5:40:5 | {...} | Assert.cs:39:9:39:35 | call to method WriteLine | normal | +| Assert.cs:37:9:37:33 | ... ...; | Assert.cs:37:16:37:32 | String s = ... | normal | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:37:16:37:32 | String s = ... | normal | +| Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:37:20:37:20 | access to parameter b | false | +| Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:37:20:37:20 | access to parameter b | true | +| Assert.cs:37:20:37:32 | ... ? ... : ... | Assert.cs:37:24:37:27 | null | normal | +| Assert.cs:37:20:37:32 | ... ? ... : ... | Assert.cs:37:31:37:32 | "" | normal | +| Assert.cs:37:24:37:27 | null | Assert.cs:37:24:37:27 | null | normal | +| Assert.cs:37:31:37:32 | "" | Assert.cs:37:31:37:32 | "" | normal | +| Assert.cs:38:9:38:32 | call to method IsTrue | Assert.cs:38:9:38:32 | call to method IsTrue | normal | +| Assert.cs:38:9:38:33 | ...; | Assert.cs:38:9:38:32 | call to method IsTrue | normal | +| Assert.cs:38:23:38:23 | access to local variable s | Assert.cs:38:23:38:23 | access to local variable s | normal | +| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:23:38:31 | ... != ... | normal | +| Assert.cs:38:28:38:31 | null | Assert.cs:38:28:38:31 | null | normal | +| Assert.cs:39:9:39:35 | call to method WriteLine | Assert.cs:39:9:39:35 | call to method WriteLine | normal | +| Assert.cs:39:9:39:36 | ...; | Assert.cs:39:9:39:35 | call to method WriteLine | normal | +| Assert.cs:39:27:39:27 | access to local variable s | Assert.cs:39:27:39:27 | access to local variable s | normal | +| Assert.cs:39:27:39:34 | access to property Length | Assert.cs:39:27:39:34 | access to property Length | normal | +| Assert.cs:43:5:47:5 | {...} | Assert.cs:46:9:46:35 | call to method WriteLine | normal | +| Assert.cs:44:9:44:33 | ... ...; | Assert.cs:44:16:44:32 | String s = ... | normal | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:44:16:44:32 | String s = ... | normal | +| Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:44:20:44:20 | access to parameter b | false | +| Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:44:20:44:20 | access to parameter b | true | +| Assert.cs:44:20:44:32 | ... ? ... : ... | Assert.cs:44:24:44:27 | null | normal | +| Assert.cs:44:20:44:32 | ... ? ... : ... | Assert.cs:44:31:44:32 | "" | normal | +| Assert.cs:44:24:44:27 | null | Assert.cs:44:24:44:27 | null | normal | +| Assert.cs:44:31:44:32 | "" | Assert.cs:44:31:44:32 | "" | normal | +| Assert.cs:45:9:45:33 | call to method IsFalse | Assert.cs:45:9:45:33 | call to method IsFalse | normal | +| Assert.cs:45:9:45:34 | ...; | Assert.cs:45:9:45:33 | call to method IsFalse | normal | +| Assert.cs:45:24:45:24 | access to local variable s | Assert.cs:45:24:45:24 | access to local variable s | normal | +| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:24:45:32 | ... != ... | normal | +| Assert.cs:45:29:45:32 | null | Assert.cs:45:29:45:32 | null | normal | +| Assert.cs:46:9:46:35 | call to method WriteLine | Assert.cs:46:9:46:35 | call to method WriteLine | normal | +| Assert.cs:46:9:46:36 | ...; | Assert.cs:46:9:46:35 | call to method WriteLine | normal | +| Assert.cs:46:27:46:27 | access to local variable s | Assert.cs:46:27:46:27 | access to local variable s | normal | +| Assert.cs:46:27:46:34 | access to property Length | Assert.cs:46:27:46:34 | access to property Length | normal | +| Assert.cs:50:5:54:5 | {...} | Assert.cs:53:9:53:35 | call to method WriteLine | normal | +| Assert.cs:51:9:51:33 | ... ...; | Assert.cs:51:16:51:32 | String s = ... | normal | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:51:16:51:32 | String s = ... | normal | +| Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:51:20:51:20 | access to parameter b | false | +| Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:51:20:51:20 | access to parameter b | true | +| Assert.cs:51:20:51:32 | ... ? ... : ... | Assert.cs:51:24:51:27 | null | normal | +| Assert.cs:51:20:51:32 | ... ? ... : ... | Assert.cs:51:31:51:32 | "" | normal | +| Assert.cs:51:24:51:27 | null | Assert.cs:51:24:51:27 | null | normal | +| Assert.cs:51:31:51:32 | "" | Assert.cs:51:31:51:32 | "" | normal | +| Assert.cs:52:9:52:33 | call to method IsFalse | Assert.cs:52:9:52:33 | call to method IsFalse | normal | +| Assert.cs:52:9:52:34 | ...; | Assert.cs:52:9:52:33 | call to method IsFalse | normal | +| Assert.cs:52:24:52:24 | access to local variable s | Assert.cs:52:24:52:24 | access to local variable s | normal | +| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:24:52:32 | ... == ... | normal | +| Assert.cs:52:29:52:32 | null | Assert.cs:52:29:52:32 | null | normal | +| Assert.cs:53:9:53:35 | call to method WriteLine | Assert.cs:53:9:53:35 | call to method WriteLine | normal | +| Assert.cs:53:9:53:36 | ...; | Assert.cs:53:9:53:35 | call to method WriteLine | normal | +| Assert.cs:53:27:53:27 | access to local variable s | Assert.cs:53:27:53:27 | access to local variable s | normal | +| Assert.cs:53:27:53:34 | access to property Length | Assert.cs:53:27:53:34 | access to property Length | normal | +| Assert.cs:57:5:61:5 | {...} | Assert.cs:60:9:60:35 | call to method WriteLine | normal | +| Assert.cs:58:9:58:33 | ... ...; | Assert.cs:58:16:58:32 | String s = ... | normal | +| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:58:16:58:32 | String s = ... | normal | +| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | false | +| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | true | +| Assert.cs:58:20:58:32 | ... ? ... : ... | Assert.cs:58:24:58:27 | null | normal | +| Assert.cs:58:20:58:32 | ... ? ... : ... | Assert.cs:58:31:58:32 | "" | normal | +| Assert.cs:58:24:58:27 | null | Assert.cs:58:24:58:27 | null | normal | +| Assert.cs:58:31:58:32 | "" | Assert.cs:58:31:58:32 | "" | normal | +| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:59:9:59:37 | call to method IsTrue | normal | +| Assert.cs:59:9:59:38 | ...; | Assert.cs:59:9:59:37 | call to method IsTrue | normal | +| Assert.cs:59:23:59:23 | access to local variable s | Assert.cs:59:23:59:23 | access to local variable s | normal | +| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:23:59:31 | ... != ... | false | +| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:23:59:31 | ... != ... | true | +| Assert.cs:59:23:59:36 | ... && ... | Assert.cs:59:23:59:31 | ... != ... | false | +| Assert.cs:59:23:59:36 | ... && ... | Assert.cs:59:36:59:36 | access to parameter b | normal | +| Assert.cs:59:28:59:31 | null | Assert.cs:59:28:59:31 | null | normal | +| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:59:36:59:36 | access to parameter b | normal | +| Assert.cs:60:9:60:35 | call to method WriteLine | Assert.cs:60:9:60:35 | call to method WriteLine | normal | +| Assert.cs:60:9:60:36 | ...; | Assert.cs:60:9:60:35 | call to method WriteLine | normal | +| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:60:27:60:27 | access to local variable s | normal | +| Assert.cs:60:27:60:34 | access to property Length | Assert.cs:60:27:60:34 | access to property Length | normal | +| Assert.cs:64:5:68:5 | {...} | Assert.cs:67:9:67:35 | call to method WriteLine | normal | +| Assert.cs:65:9:65:33 | ... ...; | Assert.cs:65:16:65:32 | String s = ... | normal | +| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:65:16:65:32 | String s = ... | normal | +| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | false | +| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | true | +| Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:65:24:65:27 | null | normal | +| Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:65:31:65:32 | "" | normal | +| Assert.cs:65:24:65:27 | null | Assert.cs:65:24:65:27 | null | normal | +| Assert.cs:65:31:65:32 | "" | Assert.cs:65:31:65:32 | "" | normal | +| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:66:9:66:38 | call to method IsFalse | normal | +| Assert.cs:66:9:66:39 | ...; | Assert.cs:66:9:66:38 | call to method IsFalse | normal | +| Assert.cs:66:24:66:24 | access to local variable s | Assert.cs:66:24:66:24 | access to local variable s | normal | +| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:24:66:32 | ... == ... | false | +| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:24:66:32 | ... == ... | true | +| Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:66:24:66:32 | ... == ... | true | +| Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:66:37:66:37 | access to parameter b | normal | +| Assert.cs:66:29:66:32 | null | Assert.cs:66:29:66:32 | null | normal | +| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:66:37:66:37 | access to parameter b | normal | +| Assert.cs:67:9:67:35 | call to method WriteLine | Assert.cs:67:9:67:35 | call to method WriteLine | normal | +| Assert.cs:67:9:67:36 | ...; | Assert.cs:67:9:67:35 | call to method WriteLine | normal | +| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:67:27:67:27 | access to local variable s | normal | +| Assert.cs:67:27:67:34 | access to property Length | Assert.cs:67:27:67:34 | access to property Length | normal | +| Assert.cs:71:5:75:5 | {...} | Assert.cs:74:9:74:35 | call to method WriteLine | normal | +| Assert.cs:72:9:72:33 | ... ...; | Assert.cs:72:16:72:32 | String s = ... | normal | +| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:72:16:72:32 | String s = ... | normal | +| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | false | +| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | true | +| Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:72:24:72:27 | null | normal | +| Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:72:31:72:32 | "" | normal | +| Assert.cs:72:24:72:27 | null | Assert.cs:72:24:72:27 | null | normal | +| Assert.cs:72:31:72:32 | "" | Assert.cs:72:31:72:32 | "" | normal | +| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:73:9:73:37 | call to method IsTrue | normal | +| Assert.cs:73:9:73:38 | ...; | Assert.cs:73:9:73:37 | call to method IsTrue | normal | +| Assert.cs:73:23:73:23 | access to local variable s | Assert.cs:73:23:73:23 | access to local variable s | normal | +| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:23:73:31 | ... == ... | false | +| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:23:73:31 | ... == ... | true | +| Assert.cs:73:23:73:36 | ... && ... | Assert.cs:73:23:73:31 | ... == ... | false | +| Assert.cs:73:23:73:36 | ... && ... | Assert.cs:73:36:73:36 | access to parameter b | normal | +| Assert.cs:73:28:73:31 | null | Assert.cs:73:28:73:31 | null | normal | +| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:73:36:73:36 | access to parameter b | normal | +| Assert.cs:74:9:74:35 | call to method WriteLine | Assert.cs:74:9:74:35 | call to method WriteLine | normal | +| Assert.cs:74:9:74:36 | ...; | Assert.cs:74:9:74:35 | call to method WriteLine | normal | +| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:74:27:74:27 | access to local variable s | normal | +| Assert.cs:74:27:74:34 | access to property Length | Assert.cs:74:27:74:34 | access to property Length | normal | +| Assert.cs:78:5:82:5 | {...} | Assert.cs:81:9:81:35 | call to method WriteLine | normal | +| Assert.cs:79:9:79:33 | ... ...; | Assert.cs:79:16:79:32 | String s = ... | normal | +| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:79:16:79:32 | String s = ... | normal | +| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | false | +| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | true | +| Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:79:24:79:27 | null | normal | +| Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:79:31:79:32 | "" | normal | +| Assert.cs:79:24:79:27 | null | Assert.cs:79:24:79:27 | null | normal | +| Assert.cs:79:31:79:32 | "" | Assert.cs:79:31:79:32 | "" | normal | +| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:80:9:80:38 | call to method IsFalse | normal | +| Assert.cs:80:9:80:39 | ...; | Assert.cs:80:9:80:38 | call to method IsFalse | normal | +| Assert.cs:80:24:80:24 | access to local variable s | Assert.cs:80:24:80:24 | access to local variable s | normal | +| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:24:80:32 | ... != ... | false | +| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:24:80:32 | ... != ... | true | +| Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:24:80:32 | ... != ... | true | +| Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:37:80:37 | access to parameter b | normal | +| Assert.cs:80:29:80:32 | null | Assert.cs:80:29:80:32 | null | normal | +| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:80:37:80:37 | access to parameter b | normal | +| Assert.cs:81:9:81:35 | call to method WriteLine | Assert.cs:81:9:81:35 | call to method WriteLine | normal | +| Assert.cs:81:9:81:36 | ...; | Assert.cs:81:9:81:35 | call to method WriteLine | normal | +| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:81:27:81:27 | access to local variable s | normal | +| Assert.cs:81:27:81:34 | access to property Length | Assert.cs:81:27:81:34 | access to property Length | normal | +| Assert.cs:85:5:129:5 | {...} | Assert.cs:128:9:128:35 | call to method WriteLine | normal | +| Assert.cs:86:9:86:33 | ... ...; | Assert.cs:86:16:86:32 | String s = ... | normal | +| Assert.cs:86:16:86:32 | String s = ... | Assert.cs:86:16:86:32 | String s = ... | normal | +| Assert.cs:86:20:86:20 | access to parameter b | Assert.cs:86:20:86:20 | access to parameter b | false | +| Assert.cs:86:20:86:20 | access to parameter b | Assert.cs:86:20:86:20 | access to parameter b | true | +| Assert.cs:86:20:86:32 | ... ? ... : ... | Assert.cs:86:24:86:27 | null | normal | +| Assert.cs:86:20:86:32 | ... ? ... : ... | Assert.cs:86:31:86:32 | "" | normal | +| Assert.cs:86:24:86:27 | null | Assert.cs:86:24:86:27 | null | normal | +| Assert.cs:86:31:86:32 | "" | Assert.cs:86:31:86:32 | "" | normal | +| Assert.cs:87:9:87:31 | call to method Assert | Assert.cs:87:9:87:31 | call to method Assert | normal | +| Assert.cs:87:9:87:32 | ...; | Assert.cs:87:9:87:31 | call to method Assert | normal | +| Assert.cs:87:22:87:22 | access to local variable s | Assert.cs:87:22:87:22 | access to local variable s | normal | +| Assert.cs:87:22:87:30 | ... != ... | Assert.cs:87:22:87:30 | ... != ... | normal | +| Assert.cs:87:27:87:30 | null | Assert.cs:87:27:87:30 | null | normal | +| Assert.cs:88:9:88:35 | call to method WriteLine | Assert.cs:88:9:88:35 | call to method WriteLine | normal | +| Assert.cs:88:9:88:36 | ...; | Assert.cs:88:9:88:35 | call to method WriteLine | normal | +| Assert.cs:88:27:88:27 | access to local variable s | Assert.cs:88:27:88:27 | access to local variable s | normal | +| Assert.cs:88:27:88:34 | access to property Length | Assert.cs:88:27:88:34 | access to property Length | normal | +| Assert.cs:90:9:90:25 | ... = ... | Assert.cs:90:9:90:25 | ... = ... | normal | +| Assert.cs:90:9:90:26 | ...; | Assert.cs:90:9:90:25 | ... = ... | normal | +| Assert.cs:90:13:90:13 | access to parameter b | Assert.cs:90:13:90:13 | access to parameter b | false | +| Assert.cs:90:13:90:13 | access to parameter b | Assert.cs:90:13:90:13 | access to parameter b | true | +| Assert.cs:90:13:90:25 | ... ? ... : ... | Assert.cs:90:17:90:20 | null | normal | +| Assert.cs:90:13:90:25 | ... ? ... : ... | Assert.cs:90:24:90:25 | "" | normal | +| Assert.cs:90:17:90:20 | null | Assert.cs:90:17:90:20 | null | normal | +| Assert.cs:90:24:90:25 | "" | Assert.cs:90:24:90:25 | "" | normal | +| Assert.cs:91:9:91:24 | call to method IsNull | Assert.cs:91:9:91:24 | call to method IsNull | normal | +| Assert.cs:91:9:91:25 | ...; | Assert.cs:91:9:91:24 | call to method IsNull | normal | +| Assert.cs:91:23:91:23 | access to local variable s | Assert.cs:91:23:91:23 | access to local variable s | normal | +| Assert.cs:92:9:92:35 | call to method WriteLine | Assert.cs:92:9:92:35 | call to method WriteLine | normal | +| Assert.cs:92:9:92:36 | ...; | Assert.cs:92:9:92:35 | call to method WriteLine | normal | +| Assert.cs:92:27:92:27 | access to local variable s | Assert.cs:92:27:92:27 | access to local variable s | normal | +| Assert.cs:92:27:92:34 | access to property Length | Assert.cs:92:27:92:34 | access to property Length | normal | +| Assert.cs:94:9:94:25 | ... = ... | Assert.cs:94:9:94:25 | ... = ... | normal | +| Assert.cs:94:9:94:26 | ...; | Assert.cs:94:9:94:25 | ... = ... | normal | +| Assert.cs:94:13:94:13 | access to parameter b | Assert.cs:94:13:94:13 | access to parameter b | false | +| Assert.cs:94:13:94:13 | access to parameter b | Assert.cs:94:13:94:13 | access to parameter b | true | +| Assert.cs:94:13:94:25 | ... ? ... : ... | Assert.cs:94:17:94:20 | null | normal | +| Assert.cs:94:13:94:25 | ... ? ... : ... | Assert.cs:94:24:94:25 | "" | normal | +| Assert.cs:94:17:94:20 | null | Assert.cs:94:17:94:20 | null | normal | +| Assert.cs:94:24:94:25 | "" | Assert.cs:94:24:94:25 | "" | normal | +| Assert.cs:95:9:95:27 | call to method IsNotNull | Assert.cs:95:9:95:27 | call to method IsNotNull | normal | +| Assert.cs:95:9:95:28 | ...; | Assert.cs:95:9:95:27 | call to method IsNotNull | normal | +| Assert.cs:95:26:95:26 | access to local variable s | Assert.cs:95:26:95:26 | access to local variable s | normal | +| Assert.cs:96:9:96:35 | call to method WriteLine | Assert.cs:96:9:96:35 | call to method WriteLine | normal | +| Assert.cs:96:9:96:36 | ...; | Assert.cs:96:9:96:35 | call to method WriteLine | normal | +| Assert.cs:96:27:96:27 | access to local variable s | Assert.cs:96:27:96:27 | access to local variable s | normal | +| Assert.cs:96:27:96:34 | access to property Length | Assert.cs:96:27:96:34 | access to property Length | normal | +| Assert.cs:98:9:98:25 | ... = ... | Assert.cs:98:9:98:25 | ... = ... | normal | +| Assert.cs:98:9:98:26 | ...; | Assert.cs:98:9:98:25 | ... = ... | normal | +| Assert.cs:98:13:98:13 | access to parameter b | Assert.cs:98:13:98:13 | access to parameter b | false | +| Assert.cs:98:13:98:13 | access to parameter b | Assert.cs:98:13:98:13 | access to parameter b | true | +| Assert.cs:98:13:98:25 | ... ? ... : ... | Assert.cs:98:17:98:20 | null | normal | +| Assert.cs:98:13:98:25 | ... ? ... : ... | Assert.cs:98:24:98:25 | "" | normal | +| Assert.cs:98:17:98:20 | null | Assert.cs:98:17:98:20 | null | normal | +| Assert.cs:98:24:98:25 | "" | Assert.cs:98:24:98:25 | "" | normal | +| Assert.cs:99:9:99:32 | call to method IsTrue | Assert.cs:99:9:99:32 | call to method IsTrue | normal | +| Assert.cs:99:9:99:33 | ...; | Assert.cs:99:9:99:32 | call to method IsTrue | normal | +| Assert.cs:99:23:99:23 | access to local variable s | Assert.cs:99:23:99:23 | access to local variable s | normal | +| Assert.cs:99:23:99:31 | ... == ... | Assert.cs:99:23:99:31 | ... == ... | normal | +| Assert.cs:99:28:99:31 | null | Assert.cs:99:28:99:31 | null | normal | +| Assert.cs:100:9:100:35 | call to method WriteLine | Assert.cs:100:9:100:35 | call to method WriteLine | normal | +| Assert.cs:100:9:100:36 | ...; | Assert.cs:100:9:100:35 | call to method WriteLine | normal | +| Assert.cs:100:27:100:27 | access to local variable s | Assert.cs:100:27:100:27 | access to local variable s | normal | +| Assert.cs:100:27:100:34 | access to property Length | Assert.cs:100:27:100:34 | access to property Length | normal | +| Assert.cs:102:9:102:25 | ... = ... | Assert.cs:102:9:102:25 | ... = ... | normal | +| Assert.cs:102:9:102:26 | ...; | Assert.cs:102:9:102:25 | ... = ... | normal | +| Assert.cs:102:13:102:13 | access to parameter b | Assert.cs:102:13:102:13 | access to parameter b | false | +| Assert.cs:102:13:102:13 | access to parameter b | Assert.cs:102:13:102:13 | access to parameter b | true | +| Assert.cs:102:13:102:25 | ... ? ... : ... | Assert.cs:102:17:102:20 | null | normal | +| Assert.cs:102:13:102:25 | ... ? ... : ... | Assert.cs:102:24:102:25 | "" | normal | +| Assert.cs:102:17:102:20 | null | Assert.cs:102:17:102:20 | null | normal | +| Assert.cs:102:24:102:25 | "" | Assert.cs:102:24:102:25 | "" | normal | +| Assert.cs:103:9:103:32 | call to method IsTrue | Assert.cs:103:9:103:32 | call to method IsTrue | normal | +| Assert.cs:103:9:103:33 | ...; | Assert.cs:103:9:103:32 | call to method IsTrue | normal | +| Assert.cs:103:23:103:23 | access to local variable s | Assert.cs:103:23:103:23 | access to local variable s | normal | +| Assert.cs:103:23:103:31 | ... != ... | Assert.cs:103:23:103:31 | ... != ... | normal | +| Assert.cs:103:28:103:31 | null | Assert.cs:103:28:103:31 | null | normal | +| Assert.cs:104:9:104:35 | call to method WriteLine | Assert.cs:104:9:104:35 | call to method WriteLine | normal | +| Assert.cs:104:9:104:36 | ...; | Assert.cs:104:9:104:35 | call to method WriteLine | normal | +| Assert.cs:104:27:104:27 | access to local variable s | Assert.cs:104:27:104:27 | access to local variable s | normal | +| Assert.cs:104:27:104:34 | access to property Length | Assert.cs:104:27:104:34 | access to property Length | normal | +| Assert.cs:106:9:106:25 | ... = ... | Assert.cs:106:9:106:25 | ... = ... | normal | +| Assert.cs:106:9:106:26 | ...; | Assert.cs:106:9:106:25 | ... = ... | normal | +| Assert.cs:106:13:106:13 | access to parameter b | Assert.cs:106:13:106:13 | access to parameter b | false | +| Assert.cs:106:13:106:13 | access to parameter b | Assert.cs:106:13:106:13 | access to parameter b | true | +| Assert.cs:106:13:106:25 | ... ? ... : ... | Assert.cs:106:17:106:20 | null | normal | +| Assert.cs:106:13:106:25 | ... ? ... : ... | Assert.cs:106:24:106:25 | "" | normal | +| Assert.cs:106:17:106:20 | null | Assert.cs:106:17:106:20 | null | normal | +| Assert.cs:106:24:106:25 | "" | Assert.cs:106:24:106:25 | "" | normal | +| Assert.cs:107:9:107:33 | call to method IsFalse | Assert.cs:107:9:107:33 | call to method IsFalse | normal | +| Assert.cs:107:9:107:34 | ...; | Assert.cs:107:9:107:33 | call to method IsFalse | normal | +| Assert.cs:107:24:107:24 | access to local variable s | Assert.cs:107:24:107:24 | access to local variable s | normal | +| Assert.cs:107:24:107:32 | ... != ... | Assert.cs:107:24:107:32 | ... != ... | normal | +| Assert.cs:107:29:107:32 | null | Assert.cs:107:29:107:32 | null | normal | +| Assert.cs:108:9:108:35 | call to method WriteLine | Assert.cs:108:9:108:35 | call to method WriteLine | normal | +| Assert.cs:108:9:108:36 | ...; | Assert.cs:108:9:108:35 | call to method WriteLine | normal | +| Assert.cs:108:27:108:27 | access to local variable s | Assert.cs:108:27:108:27 | access to local variable s | normal | +| Assert.cs:108:27:108:34 | access to property Length | Assert.cs:108:27:108:34 | access to property Length | normal | +| Assert.cs:110:9:110:25 | ... = ... | Assert.cs:110:9:110:25 | ... = ... | normal | +| Assert.cs:110:9:110:26 | ...; | Assert.cs:110:9:110:25 | ... = ... | normal | +| Assert.cs:110:13:110:13 | access to parameter b | Assert.cs:110:13:110:13 | access to parameter b | false | +| Assert.cs:110:13:110:13 | access to parameter b | Assert.cs:110:13:110:13 | access to parameter b | true | +| Assert.cs:110:13:110:25 | ... ? ... : ... | Assert.cs:110:17:110:20 | null | normal | +| Assert.cs:110:13:110:25 | ... ? ... : ... | Assert.cs:110:24:110:25 | "" | normal | +| Assert.cs:110:17:110:20 | null | Assert.cs:110:17:110:20 | null | normal | +| Assert.cs:110:24:110:25 | "" | Assert.cs:110:24:110:25 | "" | normal | +| Assert.cs:111:9:111:33 | call to method IsFalse | Assert.cs:111:9:111:33 | call to method IsFalse | normal | +| Assert.cs:111:9:111:34 | ...; | Assert.cs:111:9:111:33 | call to method IsFalse | normal | +| Assert.cs:111:24:111:24 | access to local variable s | Assert.cs:111:24:111:24 | access to local variable s | normal | +| Assert.cs:111:24:111:32 | ... == ... | Assert.cs:111:24:111:32 | ... == ... | normal | +| Assert.cs:111:29:111:32 | null | Assert.cs:111:29:111:32 | null | normal | +| Assert.cs:112:9:112:35 | call to method WriteLine | Assert.cs:112:9:112:35 | call to method WriteLine | normal | +| Assert.cs:112:9:112:36 | ...; | Assert.cs:112:9:112:35 | call to method WriteLine | normal | +| Assert.cs:112:27:112:27 | access to local variable s | Assert.cs:112:27:112:27 | access to local variable s | normal | +| Assert.cs:112:27:112:34 | access to property Length | Assert.cs:112:27:112:34 | access to property Length | normal | +| Assert.cs:114:9:114:25 | ... = ... | Assert.cs:114:9:114:25 | ... = ... | normal | +| Assert.cs:114:9:114:26 | ...; | Assert.cs:114:9:114:25 | ... = ... | normal | +| Assert.cs:114:13:114:13 | access to parameter b | Assert.cs:114:13:114:13 | access to parameter b | false | +| Assert.cs:114:13:114:13 | access to parameter b | Assert.cs:114:13:114:13 | access to parameter b | true | +| Assert.cs:114:13:114:25 | ... ? ... : ... | Assert.cs:114:17:114:20 | null | normal | +| Assert.cs:114:13:114:25 | ... ? ... : ... | Assert.cs:114:24:114:25 | "" | normal | +| Assert.cs:114:17:114:20 | null | Assert.cs:114:17:114:20 | null | normal | +| Assert.cs:114:24:114:25 | "" | Assert.cs:114:24:114:25 | "" | normal | +| Assert.cs:115:9:115:37 | call to method IsTrue | Assert.cs:115:9:115:37 | call to method IsTrue | normal | +| Assert.cs:115:9:115:38 | ...; | Assert.cs:115:9:115:37 | call to method IsTrue | normal | +| Assert.cs:115:23:115:23 | access to local variable s | Assert.cs:115:23:115:23 | access to local variable s | normal | +| Assert.cs:115:23:115:31 | ... != ... | Assert.cs:115:23:115:31 | ... != ... | false | +| Assert.cs:115:23:115:31 | ... != ... | Assert.cs:115:23:115:31 | ... != ... | true | +| Assert.cs:115:23:115:36 | ... && ... | Assert.cs:115:23:115:31 | ... != ... | false | +| Assert.cs:115:23:115:36 | ... && ... | Assert.cs:115:36:115:36 | access to parameter b | normal | +| Assert.cs:115:28:115:31 | null | Assert.cs:115:28:115:31 | null | normal | +| Assert.cs:115:36:115:36 | access to parameter b | Assert.cs:115:36:115:36 | access to parameter b | normal | +| Assert.cs:116:9:116:35 | call to method WriteLine | Assert.cs:116:9:116:35 | call to method WriteLine | normal | +| Assert.cs:116:9:116:36 | ...; | Assert.cs:116:9:116:35 | call to method WriteLine | normal | +| Assert.cs:116:27:116:27 | access to local variable s | Assert.cs:116:27:116:27 | access to local variable s | normal | +| Assert.cs:116:27:116:34 | access to property Length | Assert.cs:116:27:116:34 | access to property Length | normal | +| Assert.cs:118:9:118:25 | ... = ... | Assert.cs:118:9:118:25 | ... = ... | normal | +| Assert.cs:118:9:118:26 | ...; | Assert.cs:118:9:118:25 | ... = ... | normal | +| Assert.cs:118:13:118:13 | access to parameter b | Assert.cs:118:13:118:13 | access to parameter b | false | +| Assert.cs:118:13:118:13 | access to parameter b | Assert.cs:118:13:118:13 | access to parameter b | true | +| Assert.cs:118:13:118:25 | ... ? ... : ... | Assert.cs:118:17:118:20 | null | normal | +| Assert.cs:118:13:118:25 | ... ? ... : ... | Assert.cs:118:24:118:25 | "" | normal | +| Assert.cs:118:17:118:20 | null | Assert.cs:118:17:118:20 | null | normal | +| Assert.cs:118:24:118:25 | "" | Assert.cs:118:24:118:25 | "" | normal | +| Assert.cs:119:9:119:39 | call to method IsFalse | Assert.cs:119:9:119:39 | call to method IsFalse | normal | +| Assert.cs:119:9:119:40 | ...; | Assert.cs:119:9:119:39 | call to method IsFalse | normal | +| Assert.cs:119:24:119:24 | access to local variable s | Assert.cs:119:24:119:24 | access to local variable s | normal | +| Assert.cs:119:24:119:32 | ... == ... | Assert.cs:119:24:119:32 | ... == ... | false | +| Assert.cs:119:24:119:32 | ... == ... | Assert.cs:119:24:119:32 | ... == ... | true | +| Assert.cs:119:24:119:38 | ... \|\| ... | Assert.cs:119:24:119:32 | ... == ... | true | +| Assert.cs:119:24:119:38 | ... \|\| ... | Assert.cs:119:38:119:38 | access to parameter b | normal | +| Assert.cs:119:29:119:32 | null | Assert.cs:119:29:119:32 | null | normal | +| Assert.cs:119:37:119:38 | !... | Assert.cs:119:38:119:38 | access to parameter b | normal | +| Assert.cs:119:38:119:38 | access to parameter b | Assert.cs:119:38:119:38 | access to parameter b | normal | +| Assert.cs:120:9:120:35 | call to method WriteLine | Assert.cs:120:9:120:35 | call to method WriteLine | normal | +| Assert.cs:120:9:120:36 | ...; | Assert.cs:120:9:120:35 | call to method WriteLine | normal | +| Assert.cs:120:27:120:27 | access to local variable s | Assert.cs:120:27:120:27 | access to local variable s | normal | +| Assert.cs:120:27:120:34 | access to property Length | Assert.cs:120:27:120:34 | access to property Length | normal | +| Assert.cs:122:9:122:25 | ... = ... | Assert.cs:122:9:122:25 | ... = ... | normal | +| Assert.cs:122:9:122:26 | ...; | Assert.cs:122:9:122:25 | ... = ... | normal | +| Assert.cs:122:13:122:13 | access to parameter b | Assert.cs:122:13:122:13 | access to parameter b | false | +| Assert.cs:122:13:122:13 | access to parameter b | Assert.cs:122:13:122:13 | access to parameter b | true | +| Assert.cs:122:13:122:25 | ... ? ... : ... | Assert.cs:122:17:122:20 | null | normal | +| Assert.cs:122:13:122:25 | ... ? ... : ... | Assert.cs:122:24:122:25 | "" | normal | +| Assert.cs:122:17:122:20 | null | Assert.cs:122:17:122:20 | null | normal | +| Assert.cs:122:24:122:25 | "" | Assert.cs:122:24:122:25 | "" | normal | +| Assert.cs:123:9:123:37 | call to method IsTrue | Assert.cs:123:9:123:37 | call to method IsTrue | normal | +| Assert.cs:123:9:123:38 | ...; | Assert.cs:123:9:123:37 | call to method IsTrue | normal | +| Assert.cs:123:23:123:23 | access to local variable s | Assert.cs:123:23:123:23 | access to local variable s | normal | +| Assert.cs:123:23:123:31 | ... == ... | Assert.cs:123:23:123:31 | ... == ... | false | +| Assert.cs:123:23:123:31 | ... == ... | Assert.cs:123:23:123:31 | ... == ... | true | +| Assert.cs:123:23:123:36 | ... && ... | Assert.cs:123:23:123:31 | ... == ... | false | +| Assert.cs:123:23:123:36 | ... && ... | Assert.cs:123:36:123:36 | access to parameter b | normal | +| Assert.cs:123:28:123:31 | null | Assert.cs:123:28:123:31 | null | normal | +| Assert.cs:123:36:123:36 | access to parameter b | Assert.cs:123:36:123:36 | access to parameter b | normal | +| Assert.cs:124:9:124:35 | call to method WriteLine | Assert.cs:124:9:124:35 | call to method WriteLine | normal | +| Assert.cs:124:9:124:36 | ...; | Assert.cs:124:9:124:35 | call to method WriteLine | normal | +| Assert.cs:124:27:124:27 | access to local variable s | Assert.cs:124:27:124:27 | access to local variable s | normal | +| Assert.cs:124:27:124:34 | access to property Length | Assert.cs:124:27:124:34 | access to property Length | normal | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:126:9:126:25 | ... = ... | normal | +| Assert.cs:126:9:126:26 | ...; | Assert.cs:126:9:126:25 | ... = ... | normal | +| Assert.cs:126:13:126:13 | access to parameter b | Assert.cs:126:13:126:13 | access to parameter b | false | +| Assert.cs:126:13:126:13 | access to parameter b | Assert.cs:126:13:126:13 | access to parameter b | true | +| Assert.cs:126:13:126:25 | ... ? ... : ... | Assert.cs:126:17:126:20 | null | normal | +| Assert.cs:126:13:126:25 | ... ? ... : ... | Assert.cs:126:24:126:25 | "" | normal | +| Assert.cs:126:17:126:20 | null | Assert.cs:126:17:126:20 | null | normal | +| Assert.cs:126:24:126:25 | "" | Assert.cs:126:24:126:25 | "" | normal | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:127:9:127:39 | call to method IsFalse | normal | +| Assert.cs:127:9:127:40 | ...; | Assert.cs:127:9:127:39 | call to method IsFalse | normal | +| Assert.cs:127:24:127:24 | access to local variable s | Assert.cs:127:24:127:24 | access to local variable s | normal | +| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:24:127:32 | ... != ... | false | +| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:24:127:32 | ... != ... | true | +| Assert.cs:127:24:127:38 | ... \|\| ... | Assert.cs:127:24:127:32 | ... != ... | true | +| Assert.cs:127:24:127:38 | ... \|\| ... | Assert.cs:127:38:127:38 | access to parameter b | normal | +| Assert.cs:127:29:127:32 | null | Assert.cs:127:29:127:32 | null | normal | +| Assert.cs:127:37:127:38 | !... | Assert.cs:127:38:127:38 | access to parameter b | normal | +| Assert.cs:127:38:127:38 | access to parameter b | Assert.cs:127:38:127:38 | access to parameter b | normal | +| Assert.cs:128:9:128:35 | call to method WriteLine | Assert.cs:128:9:128:35 | call to method WriteLine | normal | +| Assert.cs:128:9:128:36 | ...; | Assert.cs:128:9:128:35 | call to method WriteLine | normal | +| Assert.cs:128:27:128:27 | access to local variable s | Assert.cs:128:27:128:27 | access to local variable s | normal | +| Assert.cs:128:27:128:34 | access to property Length | Assert.cs:128:27:128:34 | access to property Length | normal | | Assignments.cs:4:5:15:5 | {...} | Assignments.cs:14:9:14:35 | ... += ... | normal | | Assignments.cs:5:9:5:18 | ... ...; | Assignments.cs:5:13:5:17 | Int32 x = ... | normal | | Assignments.cs:5:13:5:17 | Int32 x = ... | Assignments.cs:5:13:5:17 | Int32 x = ... | normal | diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 7feee30c18b..9348a4103ed 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -307,6 +307,526 @@ | ArrayCreation.cs:9:43:9:50 | { ..., ... } | ArrayCreation.cs:9:31:9:52 | { ..., ... } | semmle.label | successor | | ArrayCreation.cs:9:45:9:45 | 2 | ArrayCreation.cs:9:48:9:48 | 3 | semmle.label | successor | | ArrayCreation.cs:9:48:9:48 | 3 | ArrayCreation.cs:9:43:9:50 | { ..., ... } | semmle.label | successor | +| Assert.cs:7:10:7:11 | enter M1 | Assert.cs:8:5:12:5 | {...} | semmle.label | successor | +| Assert.cs:8:5:12:5 | {...} | Assert.cs:9:9:9:33 | ... ...; | semmle.label | successor | +| Assert.cs:9:9:9:33 | ... ...; | Assert.cs:9:20:9:32 | ... ? ... : ... | semmle.label | successor | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:10:9:10:32 | ...; | semmle.label | successor | +| Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:9:24:9:27 | null | semmle.label | true | +| Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:9:31:9:32 | "" | semmle.label | false | +| Assert.cs:9:20:9:32 | ... ? ... : ... | Assert.cs:9:20:9:20 | access to parameter b | semmle.label | successor | +| Assert.cs:9:24:9:27 | null | Assert.cs:9:16:9:32 | String s = ... | semmle.label | successor | +| Assert.cs:9:31:9:32 | "" | Assert.cs:9:16:9:32 | String s = ... | semmle.label | successor | +| Assert.cs:10:9:10:31 | call to method Assert | Assert.cs:11:9:11:36 | ...; | semmle.label | successor | +| Assert.cs:10:9:10:32 | ...; | Assert.cs:10:22:10:22 | access to local variable s | semmle.label | successor | +| Assert.cs:10:22:10:22 | access to local variable s | Assert.cs:10:27:10:30 | null | semmle.label | successor | +| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:9:10:31 | call to method Assert | semmle.label | successor | +| Assert.cs:10:27:10:30 | null | Assert.cs:10:22:10:30 | ... != ... | semmle.label | successor | +| Assert.cs:11:9:11:35 | call to method WriteLine | Assert.cs:7:10:7:11 | exit M1 | semmle.label | successor | +| Assert.cs:11:9:11:36 | ...; | Assert.cs:11:27:11:27 | access to local variable s | semmle.label | successor | +| Assert.cs:11:27:11:27 | access to local variable s | Assert.cs:11:27:11:34 | access to property Length | semmle.label | successor | +| Assert.cs:11:27:11:34 | access to property Length | Assert.cs:11:9:11:35 | call to method WriteLine | semmle.label | successor | +| Assert.cs:14:10:14:11 | enter M2 | Assert.cs:15:5:19:5 | {...} | semmle.label | successor | +| Assert.cs:15:5:19:5 | {...} | Assert.cs:16:9:16:33 | ... ...; | semmle.label | successor | +| Assert.cs:16:9:16:33 | ... ...; | Assert.cs:16:20:16:32 | ... ? ... : ... | semmle.label | successor | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:17:9:17:25 | ...; | semmle.label | successor | +| Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:16:24:16:27 | null | semmle.label | true | +| Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:16:31:16:32 | "" | semmle.label | false | +| Assert.cs:16:20:16:32 | ... ? ... : ... | Assert.cs:16:20:16:20 | access to parameter b | semmle.label | successor | +| Assert.cs:16:24:16:27 | null | Assert.cs:16:16:16:32 | String s = ... | semmle.label | successor | +| Assert.cs:16:31:16:32 | "" | Assert.cs:16:16:16:32 | String s = ... | semmle.label | successor | +| Assert.cs:17:9:17:24 | call to method IsNull | Assert.cs:18:9:18:36 | ...; | semmle.label | successor | +| Assert.cs:17:9:17:25 | ...; | Assert.cs:17:23:17:23 | access to local variable s | semmle.label | successor | +| Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:17:9:17:24 | call to method IsNull | semmle.label | successor | +| Assert.cs:18:9:18:35 | call to method WriteLine | Assert.cs:14:10:14:11 | exit M2 | semmle.label | successor | +| Assert.cs:18:9:18:36 | ...; | Assert.cs:18:27:18:27 | access to local variable s | semmle.label | successor | +| Assert.cs:18:27:18:27 | access to local variable s | Assert.cs:18:27:18:34 | access to property Length | semmle.label | successor | +| Assert.cs:18:27:18:34 | access to property Length | Assert.cs:18:9:18:35 | call to method WriteLine | semmle.label | successor | +| Assert.cs:21:10:21:11 | enter M3 | Assert.cs:22:5:26:5 | {...} | semmle.label | successor | +| Assert.cs:22:5:26:5 | {...} | Assert.cs:23:9:23:33 | ... ...; | semmle.label | successor | +| Assert.cs:23:9:23:33 | ... ...; | Assert.cs:23:20:23:32 | ... ? ... : ... | semmle.label | successor | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:24:9:24:28 | ...; | semmle.label | successor | +| Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:23:24:23:27 | null | semmle.label | true | +| Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:23:31:23:32 | "" | semmle.label | false | +| Assert.cs:23:20:23:32 | ... ? ... : ... | Assert.cs:23:20:23:20 | access to parameter b | semmle.label | successor | +| Assert.cs:23:24:23:27 | null | Assert.cs:23:16:23:32 | String s = ... | semmle.label | successor | +| Assert.cs:23:31:23:32 | "" | Assert.cs:23:16:23:32 | String s = ... | semmle.label | successor | +| Assert.cs:24:9:24:27 | call to method IsNotNull | Assert.cs:25:9:25:36 | ...; | semmle.label | successor | +| Assert.cs:24:9:24:28 | ...; | Assert.cs:24:26:24:26 | access to local variable s | semmle.label | successor | +| Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:24:9:24:27 | call to method IsNotNull | semmle.label | successor | +| Assert.cs:25:9:25:35 | call to method WriteLine | Assert.cs:21:10:21:11 | exit M3 | semmle.label | successor | +| Assert.cs:25:9:25:36 | ...; | Assert.cs:25:27:25:27 | access to local variable s | semmle.label | successor | +| Assert.cs:25:27:25:27 | access to local variable s | Assert.cs:25:27:25:34 | access to property Length | semmle.label | successor | +| Assert.cs:25:27:25:34 | access to property Length | Assert.cs:25:9:25:35 | call to method WriteLine | semmle.label | successor | +| Assert.cs:28:10:28:11 | enter M4 | Assert.cs:29:5:33:5 | {...} | semmle.label | successor | +| Assert.cs:29:5:33:5 | {...} | Assert.cs:30:9:30:33 | ... ...; | semmle.label | successor | +| Assert.cs:30:9:30:33 | ... ...; | Assert.cs:30:20:30:32 | ... ? ... : ... | semmle.label | successor | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:31:9:31:33 | ...; | semmle.label | successor | +| Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:30:24:30:27 | null | semmle.label | true | +| Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:30:31:30:32 | "" | semmle.label | false | +| Assert.cs:30:20:30:32 | ... ? ... : ... | Assert.cs:30:20:30:20 | access to parameter b | semmle.label | successor | +| Assert.cs:30:24:30:27 | null | Assert.cs:30:16:30:32 | String s = ... | semmle.label | successor | +| Assert.cs:30:31:30:32 | "" | Assert.cs:30:16:30:32 | String s = ... | semmle.label | successor | +| Assert.cs:31:9:31:32 | call to method IsTrue | Assert.cs:32:9:32:36 | ...; | semmle.label | successor | +| Assert.cs:31:9:31:33 | ...; | Assert.cs:31:23:31:23 | access to local variable s | semmle.label | successor | +| Assert.cs:31:23:31:23 | access to local variable s | Assert.cs:31:28:31:31 | null | semmle.label | successor | +| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:9:31:32 | call to method IsTrue | semmle.label | successor | +| Assert.cs:31:28:31:31 | null | Assert.cs:31:23:31:31 | ... == ... | semmle.label | successor | +| Assert.cs:32:9:32:35 | call to method WriteLine | Assert.cs:28:10:28:11 | exit M4 | semmle.label | successor | +| Assert.cs:32:9:32:36 | ...; | Assert.cs:32:27:32:27 | access to local variable s | semmle.label | successor | +| Assert.cs:32:27:32:27 | access to local variable s | Assert.cs:32:27:32:34 | access to property Length | semmle.label | successor | +| Assert.cs:32:27:32:34 | access to property Length | Assert.cs:32:9:32:35 | call to method WriteLine | semmle.label | successor | +| Assert.cs:35:10:35:11 | enter M5 | Assert.cs:36:5:40:5 | {...} | semmle.label | successor | +| Assert.cs:36:5:40:5 | {...} | Assert.cs:37:9:37:33 | ... ...; | semmle.label | successor | +| Assert.cs:37:9:37:33 | ... ...; | Assert.cs:37:20:37:32 | ... ? ... : ... | semmle.label | successor | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:38:9:38:33 | ...; | semmle.label | successor | +| Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:37:24:37:27 | null | semmle.label | true | +| Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:37:31:37:32 | "" | semmle.label | false | +| Assert.cs:37:20:37:32 | ... ? ... : ... | Assert.cs:37:20:37:20 | access to parameter b | semmle.label | successor | +| Assert.cs:37:24:37:27 | null | Assert.cs:37:16:37:32 | String s = ... | semmle.label | successor | +| Assert.cs:37:31:37:32 | "" | Assert.cs:37:16:37:32 | String s = ... | semmle.label | successor | +| Assert.cs:38:9:38:32 | call to method IsTrue | Assert.cs:39:9:39:36 | ...; | semmle.label | successor | +| Assert.cs:38:9:38:33 | ...; | Assert.cs:38:23:38:23 | access to local variable s | semmle.label | successor | +| Assert.cs:38:23:38:23 | access to local variable s | Assert.cs:38:28:38:31 | null | semmle.label | successor | +| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:9:38:32 | call to method IsTrue | semmle.label | successor | +| Assert.cs:38:28:38:31 | null | Assert.cs:38:23:38:31 | ... != ... | semmle.label | successor | +| Assert.cs:39:9:39:35 | call to method WriteLine | Assert.cs:35:10:35:11 | exit M5 | semmle.label | successor | +| Assert.cs:39:9:39:36 | ...; | Assert.cs:39:27:39:27 | access to local variable s | semmle.label | successor | +| Assert.cs:39:27:39:27 | access to local variable s | Assert.cs:39:27:39:34 | access to property Length | semmle.label | successor | +| Assert.cs:39:27:39:34 | access to property Length | Assert.cs:39:9:39:35 | call to method WriteLine | semmle.label | successor | +| Assert.cs:42:10:42:11 | enter M6 | Assert.cs:43:5:47:5 | {...} | semmle.label | successor | +| Assert.cs:43:5:47:5 | {...} | Assert.cs:44:9:44:33 | ... ...; | semmle.label | successor | +| Assert.cs:44:9:44:33 | ... ...; | Assert.cs:44:20:44:32 | ... ? ... : ... | semmle.label | successor | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:45:9:45:34 | ...; | semmle.label | successor | +| Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:44:24:44:27 | null | semmle.label | true | +| Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:44:31:44:32 | "" | semmle.label | false | +| Assert.cs:44:20:44:32 | ... ? ... : ... | Assert.cs:44:20:44:20 | access to parameter b | semmle.label | successor | +| Assert.cs:44:24:44:27 | null | Assert.cs:44:16:44:32 | String s = ... | semmle.label | successor | +| Assert.cs:44:31:44:32 | "" | Assert.cs:44:16:44:32 | String s = ... | semmle.label | successor | +| Assert.cs:45:9:45:33 | call to method IsFalse | Assert.cs:46:9:46:36 | ...; | semmle.label | successor | +| Assert.cs:45:9:45:34 | ...; | Assert.cs:45:24:45:24 | access to local variable s | semmle.label | successor | +| Assert.cs:45:24:45:24 | access to local variable s | Assert.cs:45:29:45:32 | null | semmle.label | successor | +| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:9:45:33 | call to method IsFalse | semmle.label | successor | +| Assert.cs:45:29:45:32 | null | Assert.cs:45:24:45:32 | ... != ... | semmle.label | successor | +| Assert.cs:46:9:46:35 | call to method WriteLine | Assert.cs:42:10:42:11 | exit M6 | semmle.label | successor | +| Assert.cs:46:9:46:36 | ...; | Assert.cs:46:27:46:27 | access to local variable s | semmle.label | successor | +| Assert.cs:46:27:46:27 | access to local variable s | Assert.cs:46:27:46:34 | access to property Length | semmle.label | successor | +| Assert.cs:46:27:46:34 | access to property Length | Assert.cs:46:9:46:35 | call to method WriteLine | semmle.label | successor | +| Assert.cs:49:10:49:11 | enter M7 | Assert.cs:50:5:54:5 | {...} | semmle.label | successor | +| Assert.cs:50:5:54:5 | {...} | Assert.cs:51:9:51:33 | ... ...; | semmle.label | successor | +| Assert.cs:51:9:51:33 | ... ...; | Assert.cs:51:20:51:32 | ... ? ... : ... | semmle.label | successor | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:52:9:52:34 | ...; | semmle.label | successor | +| Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:51:24:51:27 | null | semmle.label | true | +| Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:51:31:51:32 | "" | semmle.label | false | +| Assert.cs:51:20:51:32 | ... ? ... : ... | Assert.cs:51:20:51:20 | access to parameter b | semmle.label | successor | +| Assert.cs:51:24:51:27 | null | Assert.cs:51:16:51:32 | String s = ... | semmle.label | successor | +| Assert.cs:51:31:51:32 | "" | Assert.cs:51:16:51:32 | String s = ... | semmle.label | successor | +| Assert.cs:52:9:52:33 | call to method IsFalse | Assert.cs:53:9:53:36 | ...; | semmle.label | successor | +| Assert.cs:52:9:52:34 | ...; | Assert.cs:52:24:52:24 | access to local variable s | semmle.label | successor | +| Assert.cs:52:24:52:24 | access to local variable s | Assert.cs:52:29:52:32 | null | semmle.label | successor | +| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:9:52:33 | call to method IsFalse | semmle.label | successor | +| Assert.cs:52:29:52:32 | null | Assert.cs:52:24:52:32 | ... == ... | semmle.label | successor | +| Assert.cs:53:9:53:35 | call to method WriteLine | Assert.cs:49:10:49:11 | exit M7 | semmle.label | successor | +| Assert.cs:53:9:53:36 | ...; | Assert.cs:53:27:53:27 | access to local variable s | semmle.label | successor | +| Assert.cs:53:27:53:27 | access to local variable s | Assert.cs:53:27:53:34 | access to property Length | semmle.label | successor | +| Assert.cs:53:27:53:34 | access to property Length | Assert.cs:53:9:53:35 | call to method WriteLine | semmle.label | successor | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:57:5:61:5 | {...} | semmle.label | successor | +| Assert.cs:57:5:61:5 | {...} | Assert.cs:58:9:58:33 | ... ...; | semmle.label | successor | +| Assert.cs:58:9:58:33 | ... ...; | Assert.cs:58:20:58:32 | ... ? ... : ... | semmle.label | successor | +| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:59:9:59:38 | ...; | semmle.label | successor | +| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:24:58:27 | null | semmle.label | true | +| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:31:58:32 | "" | semmle.label | false | +| Assert.cs:58:20:58:32 | ... ? ... : ... | Assert.cs:58:20:58:20 | access to parameter b | semmle.label | successor | +| Assert.cs:58:24:58:27 | null | Assert.cs:58:16:58:32 | String s = ... | semmle.label | successor | +| Assert.cs:58:31:58:32 | "" | Assert.cs:58:16:58:32 | String s = ... | semmle.label | successor | +| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:60:9:60:36 | ...; | semmle.label | successor | +| Assert.cs:59:9:59:38 | ...; | Assert.cs:59:23:59:36 | ... && ... | semmle.label | successor | +| Assert.cs:59:23:59:23 | access to local variable s | Assert.cs:59:28:59:31 | null | semmle.label | successor | +| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:9:59:37 | call to method IsTrue | semmle.label | false | +| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:36:59:36 | access to parameter b | semmle.label | true | +| Assert.cs:59:23:59:36 | ... && ... | Assert.cs:59:23:59:23 | access to local variable s | semmle.label | successor | +| Assert.cs:59:28:59:31 | null | Assert.cs:59:23:59:31 | ... != ... | semmle.label | successor | +| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:59:9:59:37 | call to method IsTrue | semmle.label | successor | +| Assert.cs:60:9:60:35 | call to method WriteLine | Assert.cs:56:10:56:11 | exit M8 | semmle.label | successor | +| Assert.cs:60:9:60:36 | ...; | Assert.cs:60:27:60:27 | access to local variable s | semmle.label | successor | +| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:60:27:60:34 | access to property Length | semmle.label | successor | +| Assert.cs:60:27:60:34 | access to property Length | Assert.cs:60:9:60:35 | call to method WriteLine | semmle.label | successor | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:64:5:68:5 | {...} | semmle.label | successor | +| Assert.cs:64:5:68:5 | {...} | Assert.cs:65:9:65:33 | ... ...; | semmle.label | successor | +| Assert.cs:65:9:65:33 | ... ...; | Assert.cs:65:20:65:32 | ... ? ... : ... | semmle.label | successor | +| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:66:9:66:39 | ...; | semmle.label | successor | +| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:24:65:27 | null | semmle.label | true | +| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:31:65:32 | "" | semmle.label | false | +| Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:65:20:65:20 | access to parameter b | semmle.label | successor | +| Assert.cs:65:24:65:27 | null | Assert.cs:65:16:65:32 | String s = ... | semmle.label | successor | +| Assert.cs:65:31:65:32 | "" | Assert.cs:65:16:65:32 | String s = ... | semmle.label | successor | +| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:67:9:67:36 | ...; | semmle.label | successor | +| Assert.cs:66:9:66:39 | ...; | Assert.cs:66:24:66:37 | ... \|\| ... | semmle.label | successor | +| Assert.cs:66:24:66:24 | access to local variable s | Assert.cs:66:29:66:32 | null | semmle.label | successor | +| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:9:66:38 | call to method IsFalse | semmle.label | true | +| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:37:66:37 | access to parameter b | semmle.label | false | +| Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:66:24:66:24 | access to local variable s | semmle.label | successor | +| Assert.cs:66:29:66:32 | null | Assert.cs:66:24:66:32 | ... == ... | semmle.label | successor | +| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:66:9:66:38 | call to method IsFalse | semmle.label | successor | +| Assert.cs:67:9:67:35 | call to method WriteLine | Assert.cs:63:10:63:11 | exit M9 | semmle.label | successor | +| Assert.cs:67:9:67:36 | ...; | Assert.cs:67:27:67:27 | access to local variable s | semmle.label | successor | +| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:67:27:67:34 | access to property Length | semmle.label | successor | +| Assert.cs:67:27:67:34 | access to property Length | Assert.cs:67:9:67:35 | call to method WriteLine | semmle.label | successor | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:71:5:75:5 | {...} | semmle.label | successor | +| Assert.cs:71:5:75:5 | {...} | Assert.cs:72:9:72:33 | ... ...; | semmle.label | successor | +| Assert.cs:72:9:72:33 | ... ...; | Assert.cs:72:20:72:32 | ... ? ... : ... | semmle.label | successor | +| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:73:9:73:38 | ...; | semmle.label | successor | +| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:24:72:27 | null | semmle.label | true | +| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:31:72:32 | "" | semmle.label | false | +| Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:72:20:72:20 | access to parameter b | semmle.label | successor | +| Assert.cs:72:24:72:27 | null | Assert.cs:72:16:72:32 | String s = ... | semmle.label | successor | +| Assert.cs:72:31:72:32 | "" | Assert.cs:72:16:72:32 | String s = ... | semmle.label | successor | +| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:74:9:74:36 | ...; | semmle.label | successor | +| Assert.cs:73:9:73:38 | ...; | Assert.cs:73:23:73:36 | ... && ... | semmle.label | successor | +| Assert.cs:73:23:73:23 | access to local variable s | Assert.cs:73:28:73:31 | null | semmle.label | successor | +| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:9:73:37 | call to method IsTrue | semmle.label | false | +| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:36:73:36 | access to parameter b | semmle.label | true | +| Assert.cs:73:23:73:36 | ... && ... | Assert.cs:73:23:73:23 | access to local variable s | semmle.label | successor | +| Assert.cs:73:28:73:31 | null | Assert.cs:73:23:73:31 | ... == ... | semmle.label | successor | +| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:73:9:73:37 | call to method IsTrue | semmle.label | successor | +| Assert.cs:74:9:74:35 | call to method WriteLine | Assert.cs:70:10:70:12 | exit M10 | semmle.label | successor | +| Assert.cs:74:9:74:36 | ...; | Assert.cs:74:27:74:27 | access to local variable s | semmle.label | successor | +| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:74:27:74:34 | access to property Length | semmle.label | successor | +| Assert.cs:74:27:74:34 | access to property Length | Assert.cs:74:9:74:35 | call to method WriteLine | semmle.label | successor | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:78:5:82:5 | {...} | semmle.label | successor | +| Assert.cs:78:5:82:5 | {...} | Assert.cs:79:9:79:33 | ... ...; | semmle.label | successor | +| Assert.cs:79:9:79:33 | ... ...; | Assert.cs:79:20:79:32 | ... ? ... : ... | semmle.label | successor | +| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:80:9:80:39 | ...; | semmle.label | successor | +| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:24:79:27 | null | semmle.label | true | +| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:31:79:32 | "" | semmle.label | false | +| Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:79:20:79:20 | access to parameter b | semmle.label | successor | +| Assert.cs:79:24:79:27 | null | Assert.cs:79:16:79:32 | String s = ... | semmle.label | successor | +| Assert.cs:79:31:79:32 | "" | Assert.cs:79:16:79:32 | String s = ... | semmle.label | successor | +| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:81:9:81:36 | ...; | semmle.label | successor | +| Assert.cs:80:9:80:39 | ...; | Assert.cs:80:24:80:37 | ... \|\| ... | semmle.label | successor | +| Assert.cs:80:24:80:24 | access to local variable s | Assert.cs:80:29:80:32 | null | semmle.label | successor | +| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:9:80:38 | call to method IsFalse | semmle.label | true | +| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:37:80:37 | access to parameter b | semmle.label | false | +| Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:24:80:24 | access to local variable s | semmle.label | successor | +| Assert.cs:80:29:80:32 | null | Assert.cs:80:24:80:32 | ... != ... | semmle.label | successor | +| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:80:9:80:38 | call to method IsFalse | semmle.label | successor | +| Assert.cs:81:9:81:35 | call to method WriteLine | Assert.cs:77:10:77:12 | exit M11 | semmle.label | successor | +| Assert.cs:81:9:81:36 | ...; | Assert.cs:81:27:81:27 | access to local variable s | semmle.label | successor | +| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:81:27:81:34 | access to property Length | semmle.label | successor | +| Assert.cs:81:27:81:34 | access to property Length | Assert.cs:81:9:81:35 | call to method WriteLine | semmle.label | successor | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:85:5:129:5 | {...} | semmle.label | successor | +| Assert.cs:85:5:129:5 | {...} | Assert.cs:86:9:86:33 | ... ...; | semmle.label | successor | +| Assert.cs:86:9:86:33 | ... ...; | Assert.cs:86:20:86:32 | ... ? ... : ... | semmle.label | successor | +| Assert.cs:86:16:86:32 | [b (line 84): false] String s = ... | Assert.cs:87:9:87:32 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:86:16:86:32 | [b (line 84): true] String s = ... | Assert.cs:87:9:87:32 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:86:20:86:20 | access to parameter b | Assert.cs:86:24:86:27 | [b (line 84): true] null | semmle.label | true | +| Assert.cs:86:20:86:20 | access to parameter b | Assert.cs:86:31:86:32 | [b (line 84): false] "" | semmle.label | false | +| Assert.cs:86:20:86:32 | ... ? ... : ... | Assert.cs:86:20:86:20 | access to parameter b | semmle.label | successor | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:86:16:86:32 | [b (line 84): true] String s = ... | semmle.label | successor | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:86:16:86:32 | [b (line 84): false] String s = ... | semmle.label | successor | +| Assert.cs:87:9:87:31 | [b (line 84): false] call to method Assert | Assert.cs:88:9:88:36 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:87:9:87:31 | [b (line 84): true] call to method Assert | Assert.cs:88:9:88:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:87:9:87:32 | [b (line 84): false] ...; | Assert.cs:87:22:87:22 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:87:9:87:32 | [b (line 84): true] ...; | Assert.cs:87:22:87:22 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:87:22:87:22 | [b (line 84): false] access to local variable s | Assert.cs:87:27:87:30 | [b (line 84): false] null | semmle.label | successor | +| Assert.cs:87:22:87:22 | [b (line 84): true] access to local variable s | Assert.cs:87:27:87:30 | [b (line 84): true] null | semmle.label | successor | +| Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | Assert.cs:87:9:87:31 | [b (line 84): false] call to method Assert | semmle.label | successor | +| Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | Assert.cs:87:9:87:31 | [b (line 84): true] call to method Assert | semmle.label | successor | +| Assert.cs:87:27:87:30 | [b (line 84): false] null | Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | semmle.label | successor | +| Assert.cs:87:27:87:30 | [b (line 84): true] null | Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | semmle.label | successor | +| Assert.cs:88:9:88:35 | [b (line 84): false] call to method WriteLine | Assert.cs:90:9:90:26 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:88:9:88:35 | [b (line 84): true] call to method WriteLine | Assert.cs:90:9:90:26 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:88:9:88:36 | [b (line 84): false] ...; | Assert.cs:88:27:88:27 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:88:9:88:36 | [b (line 84): true] ...; | Assert.cs:88:27:88:27 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:88:27:88:27 | [b (line 84): false] access to local variable s | Assert.cs:88:27:88:34 | [b (line 84): false] access to property Length | semmle.label | successor | +| Assert.cs:88:27:88:27 | [b (line 84): true] access to local variable s | Assert.cs:88:27:88:34 | [b (line 84): true] access to property Length | semmle.label | successor | +| Assert.cs:88:27:88:34 | [b (line 84): false] access to property Length | Assert.cs:88:9:88:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | +| Assert.cs:88:27:88:34 | [b (line 84): true] access to property Length | Assert.cs:88:9:88:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | +| Assert.cs:90:9:90:25 | [b (line 84): false] ... = ... | Assert.cs:91:9:91:25 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:90:9:90:25 | [b (line 84): true] ... = ... | Assert.cs:91:9:91:25 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:90:9:90:26 | [b (line 84): false] ...; | Assert.cs:90:13:90:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | +| Assert.cs:90:9:90:26 | [b (line 84): true] ...; | Assert.cs:90:13:90:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | +| Assert.cs:90:13:90:13 | [b (line 84): false] access to parameter b | Assert.cs:90:24:90:25 | [b (line 84): false] "" | semmle.label | false | +| Assert.cs:90:13:90:13 | [b (line 84): true] access to parameter b | Assert.cs:90:17:90:20 | [b (line 84): true] null | semmle.label | true | +| Assert.cs:90:13:90:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:90:13:90:13 | [b (line 84): false] access to parameter b | semmle.label | successor | +| Assert.cs:90:13:90:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:90:13:90:13 | [b (line 84): true] access to parameter b | semmle.label | successor | +| Assert.cs:90:17:90:20 | [b (line 84): true] null | Assert.cs:90:9:90:25 | [b (line 84): true] ... = ... | semmle.label | successor | +| Assert.cs:90:24:90:25 | [b (line 84): false] "" | Assert.cs:90:9:90:25 | [b (line 84): false] ... = ... | semmle.label | successor | +| Assert.cs:91:9:91:24 | [b (line 84): false] call to method IsNull | Assert.cs:92:9:92:36 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:91:9:91:24 | [b (line 84): true] call to method IsNull | Assert.cs:92:9:92:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:91:9:91:25 | [b (line 84): false] ...; | Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:91:9:91:25 | [b (line 84): true] ...; | Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | Assert.cs:91:9:91:24 | [b (line 84): false] call to method IsNull | semmle.label | successor | +| Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | Assert.cs:91:9:91:24 | [b (line 84): true] call to method IsNull | semmle.label | successor | +| Assert.cs:92:9:92:35 | [b (line 84): false] call to method WriteLine | Assert.cs:94:9:94:26 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:92:9:92:35 | [b (line 84): true] call to method WriteLine | Assert.cs:94:9:94:26 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:92:9:92:36 | [b (line 84): false] ...; | Assert.cs:92:27:92:27 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:92:9:92:36 | [b (line 84): true] ...; | Assert.cs:92:27:92:27 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:92:27:92:27 | [b (line 84): false] access to local variable s | Assert.cs:92:27:92:34 | [b (line 84): false] access to property Length | semmle.label | successor | +| Assert.cs:92:27:92:27 | [b (line 84): true] access to local variable s | Assert.cs:92:27:92:34 | [b (line 84): true] access to property Length | semmle.label | successor | +| Assert.cs:92:27:92:34 | [b (line 84): false] access to property Length | Assert.cs:92:9:92:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | +| Assert.cs:92:27:92:34 | [b (line 84): true] access to property Length | Assert.cs:92:9:92:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | +| Assert.cs:94:9:94:25 | [b (line 84): false] ... = ... | Assert.cs:95:9:95:28 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:94:9:94:25 | [b (line 84): true] ... = ... | Assert.cs:95:9:95:28 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:94:9:94:26 | [b (line 84): false] ...; | Assert.cs:94:13:94:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | +| Assert.cs:94:9:94:26 | [b (line 84): true] ...; | Assert.cs:94:13:94:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | +| Assert.cs:94:13:94:13 | [b (line 84): false] access to parameter b | Assert.cs:94:24:94:25 | [b (line 84): false] "" | semmle.label | false | +| Assert.cs:94:13:94:13 | [b (line 84): true] access to parameter b | Assert.cs:94:17:94:20 | [b (line 84): true] null | semmle.label | true | +| Assert.cs:94:13:94:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:94:13:94:13 | [b (line 84): false] access to parameter b | semmle.label | successor | +| Assert.cs:94:13:94:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:94:13:94:13 | [b (line 84): true] access to parameter b | semmle.label | successor | +| Assert.cs:94:17:94:20 | [b (line 84): true] null | Assert.cs:94:9:94:25 | [b (line 84): true] ... = ... | semmle.label | successor | +| Assert.cs:94:24:94:25 | [b (line 84): false] "" | Assert.cs:94:9:94:25 | [b (line 84): false] ... = ... | semmle.label | successor | +| Assert.cs:95:9:95:27 | [b (line 84): false] call to method IsNotNull | Assert.cs:96:9:96:36 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:95:9:95:27 | [b (line 84): true] call to method IsNotNull | Assert.cs:96:9:96:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:95:9:95:28 | [b (line 84): false] ...; | Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:95:9:95:28 | [b (line 84): true] ...; | Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | Assert.cs:95:9:95:27 | [b (line 84): false] call to method IsNotNull | semmle.label | successor | +| Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | Assert.cs:95:9:95:27 | [b (line 84): true] call to method IsNotNull | semmle.label | successor | +| Assert.cs:96:9:96:35 | [b (line 84): false] call to method WriteLine | Assert.cs:98:9:98:26 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:96:9:96:35 | [b (line 84): true] call to method WriteLine | Assert.cs:98:9:98:26 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:96:9:96:36 | [b (line 84): false] ...; | Assert.cs:96:27:96:27 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:96:9:96:36 | [b (line 84): true] ...; | Assert.cs:96:27:96:27 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:96:27:96:27 | [b (line 84): false] access to local variable s | Assert.cs:96:27:96:34 | [b (line 84): false] access to property Length | semmle.label | successor | +| Assert.cs:96:27:96:27 | [b (line 84): true] access to local variable s | Assert.cs:96:27:96:34 | [b (line 84): true] access to property Length | semmle.label | successor | +| Assert.cs:96:27:96:34 | [b (line 84): false] access to property Length | Assert.cs:96:9:96:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | +| Assert.cs:96:27:96:34 | [b (line 84): true] access to property Length | Assert.cs:96:9:96:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | +| Assert.cs:98:9:98:25 | [b (line 84): false] ... = ... | Assert.cs:99:9:99:33 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:98:9:98:25 | [b (line 84): true] ... = ... | Assert.cs:99:9:99:33 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:98:9:98:26 | [b (line 84): false] ...; | Assert.cs:98:13:98:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | +| Assert.cs:98:9:98:26 | [b (line 84): true] ...; | Assert.cs:98:13:98:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | +| Assert.cs:98:13:98:13 | [b (line 84): false] access to parameter b | Assert.cs:98:24:98:25 | [b (line 84): false] "" | semmle.label | false | +| Assert.cs:98:13:98:13 | [b (line 84): true] access to parameter b | Assert.cs:98:17:98:20 | [b (line 84): true] null | semmle.label | true | +| Assert.cs:98:13:98:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:98:13:98:13 | [b (line 84): false] access to parameter b | semmle.label | successor | +| Assert.cs:98:13:98:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:98:13:98:13 | [b (line 84): true] access to parameter b | semmle.label | successor | +| Assert.cs:98:17:98:20 | [b (line 84): true] null | Assert.cs:98:9:98:25 | [b (line 84): true] ... = ... | semmle.label | successor | +| Assert.cs:98:24:98:25 | [b (line 84): false] "" | Assert.cs:98:9:98:25 | [b (line 84): false] ... = ... | semmle.label | successor | +| Assert.cs:99:9:99:32 | [b (line 84): false] call to method IsTrue | Assert.cs:100:9:100:36 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:99:9:99:32 | [b (line 84): true] call to method IsTrue | Assert.cs:100:9:100:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:99:9:99:33 | [b (line 84): false] ...; | Assert.cs:99:23:99:23 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:99:9:99:33 | [b (line 84): true] ...; | Assert.cs:99:23:99:23 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:99:23:99:23 | [b (line 84): false] access to local variable s | Assert.cs:99:28:99:31 | [b (line 84): false] null | semmle.label | successor | +| Assert.cs:99:23:99:23 | [b (line 84): true] access to local variable s | Assert.cs:99:28:99:31 | [b (line 84): true] null | semmle.label | successor | +| Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | Assert.cs:99:9:99:32 | [b (line 84): false] call to method IsTrue | semmle.label | successor | +| Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | Assert.cs:99:9:99:32 | [b (line 84): true] call to method IsTrue | semmle.label | successor | +| Assert.cs:99:28:99:31 | [b (line 84): false] null | Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | semmle.label | successor | +| Assert.cs:99:28:99:31 | [b (line 84): true] null | Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | semmle.label | successor | +| Assert.cs:100:9:100:35 | [b (line 84): false] call to method WriteLine | Assert.cs:102:9:102:26 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:100:9:100:35 | [b (line 84): true] call to method WriteLine | Assert.cs:102:9:102:26 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:100:9:100:36 | [b (line 84): false] ...; | Assert.cs:100:27:100:27 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:100:9:100:36 | [b (line 84): true] ...; | Assert.cs:100:27:100:27 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:100:27:100:27 | [b (line 84): false] access to local variable s | Assert.cs:100:27:100:34 | [b (line 84): false] access to property Length | semmle.label | successor | +| Assert.cs:100:27:100:27 | [b (line 84): true] access to local variable s | Assert.cs:100:27:100:34 | [b (line 84): true] access to property Length | semmle.label | successor | +| Assert.cs:100:27:100:34 | [b (line 84): false] access to property Length | Assert.cs:100:9:100:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | +| Assert.cs:100:27:100:34 | [b (line 84): true] access to property Length | Assert.cs:100:9:100:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | +| Assert.cs:102:9:102:25 | [b (line 84): false] ... = ... | Assert.cs:103:9:103:33 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:102:9:102:25 | [b (line 84): true] ... = ... | Assert.cs:103:9:103:33 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:102:9:102:26 | [b (line 84): false] ...; | Assert.cs:102:13:102:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | +| Assert.cs:102:9:102:26 | [b (line 84): true] ...; | Assert.cs:102:13:102:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | +| Assert.cs:102:13:102:13 | [b (line 84): false] access to parameter b | Assert.cs:102:24:102:25 | [b (line 84): false] "" | semmle.label | false | +| Assert.cs:102:13:102:13 | [b (line 84): true] access to parameter b | Assert.cs:102:17:102:20 | [b (line 84): true] null | semmle.label | true | +| Assert.cs:102:13:102:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:102:13:102:13 | [b (line 84): false] access to parameter b | semmle.label | successor | +| Assert.cs:102:13:102:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:102:13:102:13 | [b (line 84): true] access to parameter b | semmle.label | successor | +| Assert.cs:102:17:102:20 | [b (line 84): true] null | Assert.cs:102:9:102:25 | [b (line 84): true] ... = ... | semmle.label | successor | +| Assert.cs:102:24:102:25 | [b (line 84): false] "" | Assert.cs:102:9:102:25 | [b (line 84): false] ... = ... | semmle.label | successor | +| Assert.cs:103:9:103:32 | [b (line 84): false] call to method IsTrue | Assert.cs:104:9:104:36 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:103:9:103:32 | [b (line 84): true] call to method IsTrue | Assert.cs:104:9:104:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:103:9:103:33 | [b (line 84): false] ...; | Assert.cs:103:23:103:23 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:103:9:103:33 | [b (line 84): true] ...; | Assert.cs:103:23:103:23 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:103:23:103:23 | [b (line 84): false] access to local variable s | Assert.cs:103:28:103:31 | [b (line 84): false] null | semmle.label | successor | +| Assert.cs:103:23:103:23 | [b (line 84): true] access to local variable s | Assert.cs:103:28:103:31 | [b (line 84): true] null | semmle.label | successor | +| Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | Assert.cs:103:9:103:32 | [b (line 84): false] call to method IsTrue | semmle.label | successor | +| Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | Assert.cs:103:9:103:32 | [b (line 84): true] call to method IsTrue | semmle.label | successor | +| Assert.cs:103:28:103:31 | [b (line 84): false] null | Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | semmle.label | successor | +| Assert.cs:103:28:103:31 | [b (line 84): true] null | Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | semmle.label | successor | +| Assert.cs:104:9:104:35 | [b (line 84): false] call to method WriteLine | Assert.cs:106:9:106:26 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:104:9:104:35 | [b (line 84): true] call to method WriteLine | Assert.cs:106:9:106:26 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:104:9:104:36 | [b (line 84): false] ...; | Assert.cs:104:27:104:27 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:104:9:104:36 | [b (line 84): true] ...; | Assert.cs:104:27:104:27 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:104:27:104:27 | [b (line 84): false] access to local variable s | Assert.cs:104:27:104:34 | [b (line 84): false] access to property Length | semmle.label | successor | +| Assert.cs:104:27:104:27 | [b (line 84): true] access to local variable s | Assert.cs:104:27:104:34 | [b (line 84): true] access to property Length | semmle.label | successor | +| Assert.cs:104:27:104:34 | [b (line 84): false] access to property Length | Assert.cs:104:9:104:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | +| Assert.cs:104:27:104:34 | [b (line 84): true] access to property Length | Assert.cs:104:9:104:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | +| Assert.cs:106:9:106:25 | [b (line 84): false] ... = ... | Assert.cs:107:9:107:34 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:106:9:106:25 | [b (line 84): true] ... = ... | Assert.cs:107:9:107:34 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:106:9:106:26 | [b (line 84): false] ...; | Assert.cs:106:13:106:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | +| Assert.cs:106:9:106:26 | [b (line 84): true] ...; | Assert.cs:106:13:106:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | +| Assert.cs:106:13:106:13 | [b (line 84): false] access to parameter b | Assert.cs:106:24:106:25 | [b (line 84): false] "" | semmle.label | false | +| Assert.cs:106:13:106:13 | [b (line 84): true] access to parameter b | Assert.cs:106:17:106:20 | [b (line 84): true] null | semmle.label | true | +| Assert.cs:106:13:106:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:106:13:106:13 | [b (line 84): false] access to parameter b | semmle.label | successor | +| Assert.cs:106:13:106:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:106:13:106:13 | [b (line 84): true] access to parameter b | semmle.label | successor | +| Assert.cs:106:17:106:20 | [b (line 84): true] null | Assert.cs:106:9:106:25 | [b (line 84): true] ... = ... | semmle.label | successor | +| Assert.cs:106:24:106:25 | [b (line 84): false] "" | Assert.cs:106:9:106:25 | [b (line 84): false] ... = ... | semmle.label | successor | +| Assert.cs:107:9:107:33 | [b (line 84): false] call to method IsFalse | Assert.cs:108:9:108:36 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:107:9:107:33 | [b (line 84): true] call to method IsFalse | Assert.cs:108:9:108:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:107:9:107:34 | [b (line 84): false] ...; | Assert.cs:107:24:107:24 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:107:9:107:34 | [b (line 84): true] ...; | Assert.cs:107:24:107:24 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:107:24:107:24 | [b (line 84): false] access to local variable s | Assert.cs:107:29:107:32 | [b (line 84): false] null | semmle.label | successor | +| Assert.cs:107:24:107:24 | [b (line 84): true] access to local variable s | Assert.cs:107:29:107:32 | [b (line 84): true] null | semmle.label | successor | +| Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | Assert.cs:107:9:107:33 | [b (line 84): false] call to method IsFalse | semmle.label | successor | +| Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | Assert.cs:107:9:107:33 | [b (line 84): true] call to method IsFalse | semmle.label | successor | +| Assert.cs:107:29:107:32 | [b (line 84): false] null | Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | semmle.label | successor | +| Assert.cs:107:29:107:32 | [b (line 84): true] null | Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | semmle.label | successor | +| Assert.cs:108:9:108:35 | [b (line 84): false] call to method WriteLine | Assert.cs:110:9:110:26 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:108:9:108:35 | [b (line 84): true] call to method WriteLine | Assert.cs:110:9:110:26 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:108:9:108:36 | [b (line 84): false] ...; | Assert.cs:108:27:108:27 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:108:9:108:36 | [b (line 84): true] ...; | Assert.cs:108:27:108:27 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:108:27:108:27 | [b (line 84): false] access to local variable s | Assert.cs:108:27:108:34 | [b (line 84): false] access to property Length | semmle.label | successor | +| Assert.cs:108:27:108:27 | [b (line 84): true] access to local variable s | Assert.cs:108:27:108:34 | [b (line 84): true] access to property Length | semmle.label | successor | +| Assert.cs:108:27:108:34 | [b (line 84): false] access to property Length | Assert.cs:108:9:108:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | +| Assert.cs:108:27:108:34 | [b (line 84): true] access to property Length | Assert.cs:108:9:108:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | +| Assert.cs:110:9:110:25 | [b (line 84): false] ... = ... | Assert.cs:111:9:111:34 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:110:9:110:25 | [b (line 84): true] ... = ... | Assert.cs:111:9:111:34 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:110:9:110:26 | [b (line 84): false] ...; | Assert.cs:110:13:110:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | +| Assert.cs:110:9:110:26 | [b (line 84): true] ...; | Assert.cs:110:13:110:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | +| Assert.cs:110:13:110:13 | [b (line 84): false] access to parameter b | Assert.cs:110:24:110:25 | [b (line 84): false] "" | semmle.label | false | +| Assert.cs:110:13:110:13 | [b (line 84): true] access to parameter b | Assert.cs:110:17:110:20 | [b (line 84): true] null | semmle.label | true | +| Assert.cs:110:13:110:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:110:13:110:13 | [b (line 84): false] access to parameter b | semmle.label | successor | +| Assert.cs:110:13:110:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:110:13:110:13 | [b (line 84): true] access to parameter b | semmle.label | successor | +| Assert.cs:110:17:110:20 | [b (line 84): true] null | Assert.cs:110:9:110:25 | [b (line 84): true] ... = ... | semmle.label | successor | +| Assert.cs:110:24:110:25 | [b (line 84): false] "" | Assert.cs:110:9:110:25 | [b (line 84): false] ... = ... | semmle.label | successor | +| Assert.cs:111:9:111:33 | [b (line 84): false] call to method IsFalse | Assert.cs:112:9:112:36 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:111:9:111:33 | [b (line 84): true] call to method IsFalse | Assert.cs:112:9:112:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:111:9:111:34 | [b (line 84): false] ...; | Assert.cs:111:24:111:24 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:111:9:111:34 | [b (line 84): true] ...; | Assert.cs:111:24:111:24 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:111:24:111:24 | [b (line 84): false] access to local variable s | Assert.cs:111:29:111:32 | [b (line 84): false] null | semmle.label | successor | +| Assert.cs:111:24:111:24 | [b (line 84): true] access to local variable s | Assert.cs:111:29:111:32 | [b (line 84): true] null | semmle.label | successor | +| Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | Assert.cs:111:9:111:33 | [b (line 84): false] call to method IsFalse | semmle.label | successor | +| Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | Assert.cs:111:9:111:33 | [b (line 84): true] call to method IsFalse | semmle.label | successor | +| Assert.cs:111:29:111:32 | [b (line 84): false] null | Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | semmle.label | successor | +| Assert.cs:111:29:111:32 | [b (line 84): true] null | Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | semmle.label | successor | +| Assert.cs:112:9:112:35 | [b (line 84): false] call to method WriteLine | Assert.cs:114:9:114:26 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:112:9:112:35 | [b (line 84): true] call to method WriteLine | Assert.cs:114:9:114:26 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:112:9:112:36 | [b (line 84): false] ...; | Assert.cs:112:27:112:27 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:112:9:112:36 | [b (line 84): true] ...; | Assert.cs:112:27:112:27 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:112:27:112:27 | [b (line 84): false] access to local variable s | Assert.cs:112:27:112:34 | [b (line 84): false] access to property Length | semmle.label | successor | +| Assert.cs:112:27:112:27 | [b (line 84): true] access to local variable s | Assert.cs:112:27:112:34 | [b (line 84): true] access to property Length | semmle.label | successor | +| Assert.cs:112:27:112:34 | [b (line 84): false] access to property Length | Assert.cs:112:9:112:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | +| Assert.cs:112:27:112:34 | [b (line 84): true] access to property Length | Assert.cs:112:9:112:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | +| Assert.cs:114:9:114:25 | [b (line 84): false] ... = ... | Assert.cs:115:9:115:38 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:114:9:114:25 | [b (line 84): true] ... = ... | Assert.cs:115:9:115:38 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:114:9:114:26 | [b (line 84): false] ...; | Assert.cs:114:13:114:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | +| Assert.cs:114:9:114:26 | [b (line 84): true] ...; | Assert.cs:114:13:114:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | +| Assert.cs:114:13:114:13 | [b (line 84): false] access to parameter b | Assert.cs:114:24:114:25 | [b (line 84): false] "" | semmle.label | false | +| Assert.cs:114:13:114:13 | [b (line 84): true] access to parameter b | Assert.cs:114:17:114:20 | [b (line 84): true] null | semmle.label | true | +| Assert.cs:114:13:114:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:114:13:114:13 | [b (line 84): false] access to parameter b | semmle.label | successor | +| Assert.cs:114:13:114:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:114:13:114:13 | [b (line 84): true] access to parameter b | semmle.label | successor | +| Assert.cs:114:17:114:20 | [b (line 84): true] null | Assert.cs:114:9:114:25 | [b (line 84): true] ... = ... | semmle.label | successor | +| Assert.cs:114:24:114:25 | [b (line 84): false] "" | Assert.cs:114:9:114:25 | [b (line 84): false] ... = ... | semmle.label | successor | +| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:116:9:116:36 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:116:9:116:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:115:9:115:38 | [b (line 84): false] ...; | Assert.cs:115:23:115:36 | [b (line 84): false] ... && ... | semmle.label | successor | +| Assert.cs:115:9:115:38 | [b (line 84): true] ...; | Assert.cs:115:23:115:36 | [b (line 84): true] ... && ... | semmle.label | successor | +| Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | Assert.cs:115:28:115:31 | [b (line 84): false] null | semmle.label | successor | +| Assert.cs:115:23:115:23 | [b (line 84): true] access to local variable s | Assert.cs:115:28:115:31 | [b (line 84): true] null | semmle.label | successor | +| Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | semmle.label | false | +| Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | semmle.label | true | +| Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | semmle.label | false | +| Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | semmle.label | true | +| Assert.cs:115:23:115:36 | [b (line 84): false] ... && ... | Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:115:23:115:36 | [b (line 84): true] ... && ... | Assert.cs:115:23:115:23 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:115:28:115:31 | [b (line 84): false] null | Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | semmle.label | successor | +| Assert.cs:115:28:115:31 | [b (line 84): true] null | Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | semmle.label | successor | +| Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | semmle.label | successor | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | semmle.label | successor | +| Assert.cs:116:9:116:35 | [b (line 84): false] call to method WriteLine | Assert.cs:118:9:118:26 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | Assert.cs:118:9:118:26 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:116:9:116:36 | [b (line 84): false] ...; | Assert.cs:116:27:116:27 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:116:9:116:36 | [b (line 84): true] ...; | Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:116:27:116:27 | [b (line 84): false] access to local variable s | Assert.cs:116:27:116:34 | [b (line 84): false] access to property Length | semmle.label | successor | +| Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | semmle.label | successor | +| Assert.cs:116:27:116:34 | [b (line 84): false] access to property Length | Assert.cs:116:9:116:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | +| Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | +| Assert.cs:118:9:118:25 | [b (line 84): false] ... = ... | Assert.cs:119:9:119:40 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | Assert.cs:119:9:119:40 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:118:9:118:26 | [b (line 84): false] ...; | Assert.cs:118:13:118:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | +| Assert.cs:118:9:118:26 | [b (line 84): true] ...; | Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | +| Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | Assert.cs:118:24:118:25 | [b (line 84): false] "" | semmle.label | false | +| Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | Assert.cs:118:17:118:20 | [b (line 84): true] null | semmle.label | true | +| Assert.cs:118:13:118:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | semmle.label | successor | +| Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | semmle.label | successor | +| Assert.cs:118:17:118:20 | [b (line 84): true] null | Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | semmle.label | successor | +| Assert.cs:118:24:118:25 | [b (line 84): false] "" | Assert.cs:118:9:118:25 | [b (line 84): false] ... = ... | semmle.label | successor | +| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:120:9:120:36 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:120:9:120:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:119:9:119:40 | [b (line 84): false] ...; | Assert.cs:119:24:119:38 | [b (line 84): false] ... \|\| ... | semmle.label | successor | +| Assert.cs:119:9:119:40 | [b (line 84): true] ...; | Assert.cs:119:24:119:38 | [b (line 84): true] ... \|\| ... | semmle.label | successor | +| Assert.cs:119:24:119:24 | [b (line 84): false] access to local variable s | Assert.cs:119:29:119:32 | [b (line 84): false] null | semmle.label | successor | +| Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | Assert.cs:119:29:119:32 | [b (line 84): true] null | semmle.label | successor | +| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | semmle.label | true | +| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | Assert.cs:119:37:119:38 | [b (line 84): false] !... | semmle.label | false | +| Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | semmle.label | true | +| Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:37:119:38 | [b (line 84): true] !... | semmle.label | false | +| Assert.cs:119:24:119:38 | [b (line 84): false] ... \|\| ... | Assert.cs:119:24:119:24 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:119:24:119:38 | [b (line 84): true] ... \|\| ... | Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:119:29:119:32 | [b (line 84): false] null | Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | semmle.label | successor | +| Assert.cs:119:29:119:32 | [b (line 84): true] null | Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | semmle.label | successor | +| Assert.cs:119:37:119:38 | [b (line 84): false] !... | Assert.cs:119:38:119:38 | [b (line 84): false] access to parameter b | semmle.label | successor | +| Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | semmle.label | successor | +| Assert.cs:119:38:119:38 | [b (line 84): false] access to parameter b | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | semmle.label | successor | +| Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | semmle.label | successor | +| Assert.cs:120:9:120:35 | [b (line 84): false] call to method WriteLine | Assert.cs:122:9:122:26 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | Assert.cs:122:9:122:26 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:120:9:120:36 | [b (line 84): false] ...; | Assert.cs:120:27:120:27 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:120:9:120:36 | [b (line 84): true] ...; | Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:120:27:120:27 | [b (line 84): false] access to local variable s | Assert.cs:120:27:120:34 | [b (line 84): false] access to property Length | semmle.label | successor | +| Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | semmle.label | successor | +| Assert.cs:120:27:120:34 | [b (line 84): false] access to property Length | Assert.cs:120:9:120:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | +| Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | +| Assert.cs:122:9:122:25 | [b (line 84): false] ... = ... | Assert.cs:123:9:123:38 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | Assert.cs:123:9:123:38 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:122:9:122:26 | [b (line 84): false] ...; | Assert.cs:122:13:122:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | +| Assert.cs:122:9:122:26 | [b (line 84): true] ...; | Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | +| Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | Assert.cs:122:24:122:25 | [b (line 84): false] "" | semmle.label | false | +| Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | Assert.cs:122:17:122:20 | [b (line 84): true] null | semmle.label | true | +| Assert.cs:122:13:122:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | semmle.label | successor | +| Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | semmle.label | successor | +| Assert.cs:122:17:122:20 | [b (line 84): true] null | Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | semmle.label | successor | +| Assert.cs:122:24:122:25 | [b (line 84): false] "" | Assert.cs:122:9:122:25 | [b (line 84): false] ... = ... | semmle.label | successor | +| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:124:9:124:36 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:124:9:124:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:123:9:123:38 | [b (line 84): false] ...; | Assert.cs:123:23:123:36 | [b (line 84): false] ... && ... | semmle.label | successor | +| Assert.cs:123:9:123:38 | [b (line 84): true] ...; | Assert.cs:123:23:123:36 | [b (line 84): true] ... && ... | semmle.label | successor | +| Assert.cs:123:23:123:23 | [b (line 84): false] access to local variable s | Assert.cs:123:28:123:31 | [b (line 84): false] null | semmle.label | successor | +| Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | Assert.cs:123:28:123:31 | [b (line 84): true] null | semmle.label | successor | +| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | semmle.label | false | +| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | semmle.label | true | +| Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | semmle.label | false | +| Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | semmle.label | true | +| Assert.cs:123:23:123:36 | [b (line 84): false] ... && ... | Assert.cs:123:23:123:23 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:123:23:123:36 | [b (line 84): true] ... && ... | Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:123:28:123:31 | [b (line 84): false] null | Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | semmle.label | successor | +| Assert.cs:123:28:123:31 | [b (line 84): true] null | Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | semmle.label | successor | +| Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | semmle.label | successor | +| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | semmle.label | successor | +| Assert.cs:124:9:124:35 | [b (line 84): false] call to method WriteLine | Assert.cs:126:9:126:26 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | Assert.cs:126:9:126:26 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:124:9:124:36 | [b (line 84): false] ...; | Assert.cs:124:27:124:27 | [b (line 84): false] access to local variable s | semmle.label | successor | +| Assert.cs:124:9:124:36 | [b (line 84): true] ...; | Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:124:27:124:27 | [b (line 84): false] access to local variable s | Assert.cs:124:27:124:34 | [b (line 84): false] access to property Length | semmle.label | successor | +| Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | semmle.label | successor | +| Assert.cs:124:27:124:34 | [b (line 84): false] access to property Length | Assert.cs:124:9:124:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | +| Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | +| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:127:9:127:40 | ...; | semmle.label | successor | +| Assert.cs:126:9:126:26 | [b (line 84): false] ...; | Assert.cs:126:13:126:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | +| Assert.cs:126:9:126:26 | [b (line 84): true] ...; | Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | +| Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | Assert.cs:126:24:126:25 | "" | semmle.label | false | +| Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | Assert.cs:126:17:126:20 | null | semmle.label | true | +| Assert.cs:126:13:126:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | semmle.label | successor | +| Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | semmle.label | successor | +| Assert.cs:126:17:126:20 | null | Assert.cs:126:9:126:25 | ... = ... | semmle.label | successor | +| Assert.cs:126:24:126:25 | "" | Assert.cs:126:9:126:25 | ... = ... | semmle.label | successor | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:128:9:128:36 | ...; | semmle.label | successor | +| Assert.cs:127:9:127:40 | ...; | Assert.cs:127:24:127:38 | ... \|\| ... | semmle.label | successor | +| Assert.cs:127:24:127:24 | access to local variable s | Assert.cs:127:29:127:32 | null | semmle.label | successor | +| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:9:127:39 | call to method IsFalse | semmle.label | true | +| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:37:127:38 | !... | semmle.label | false | +| Assert.cs:127:24:127:38 | ... \|\| ... | Assert.cs:127:24:127:24 | access to local variable s | semmle.label | successor | +| Assert.cs:127:29:127:32 | null | Assert.cs:127:24:127:32 | ... != ... | semmle.label | successor | +| Assert.cs:127:37:127:38 | !... | Assert.cs:127:38:127:38 | access to parameter b | semmle.label | successor | +| Assert.cs:127:38:127:38 | access to parameter b | Assert.cs:127:9:127:39 | call to method IsFalse | semmle.label | successor | +| Assert.cs:128:9:128:35 | call to method WriteLine | Assert.cs:84:10:84:12 | exit M12 | semmle.label | successor | +| Assert.cs:128:9:128:36 | ...; | Assert.cs:128:27:128:27 | access to local variable s | semmle.label | successor | +| Assert.cs:128:27:128:27 | access to local variable s | Assert.cs:128:27:128:34 | access to property Length | semmle.label | successor | +| Assert.cs:128:27:128:34 | access to property Length | Assert.cs:128:9:128:35 | call to method WriteLine | semmle.label | successor | | Assignments.cs:3:10:3:10 | enter M | Assignments.cs:4:5:15:5 | {...} | semmle.label | successor | | Assignments.cs:4:5:15:5 | {...} | Assignments.cs:5:9:5:18 | ... ...; | semmle.label | successor | | Assignments.cs:5:9:5:18 | ... ...; | Assignments.cs:5:17:5:17 | 0 | semmle.label | successor | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected index 90685fc60a2..a25a60947bc 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected @@ -1,4 +1,290 @@ booleanNode +| Assert.cs:86:16:86:32 | [b (line 84): false] String s = ... | b (line 84): false | +| Assert.cs:86:16:86:32 | [b (line 84): true] String s = ... | b (line 84): true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | b (line 84): false | +| Assert.cs:87:9:87:31 | [b (line 84): false] call to method Assert | b (line 84): false | +| Assert.cs:87:9:87:31 | [b (line 84): true] call to method Assert | b (line 84): true | +| Assert.cs:87:9:87:32 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:87:9:87:32 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:87:22:87:22 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:87:22:87:22 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | b (line 84): false | +| Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | b (line 84): true | +| Assert.cs:87:27:87:30 | [b (line 84): false] null | b (line 84): false | +| Assert.cs:87:27:87:30 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:88:9:88:35 | [b (line 84): false] call to method WriteLine | b (line 84): false | +| Assert.cs:88:9:88:35 | [b (line 84): true] call to method WriteLine | b (line 84): true | +| Assert.cs:88:9:88:36 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:88:9:88:36 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:88:27:88:27 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:88:27:88:27 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:88:27:88:34 | [b (line 84): false] access to property Length | b (line 84): false | +| Assert.cs:88:27:88:34 | [b (line 84): true] access to property Length | b (line 84): true | +| Assert.cs:90:9:90:25 | [b (line 84): false] ... = ... | b (line 84): false | +| Assert.cs:90:9:90:25 | [b (line 84): true] ... = ... | b (line 84): true | +| Assert.cs:90:9:90:26 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:90:9:90:26 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:90:13:90:13 | [b (line 84): false] access to parameter b | b (line 84): false | +| Assert.cs:90:13:90:13 | [b (line 84): true] access to parameter b | b (line 84): true | +| Assert.cs:90:13:90:25 | [b (line 84): false] ... ? ... : ... | b (line 84): false | +| Assert.cs:90:13:90:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | +| Assert.cs:90:17:90:20 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:90:24:90:25 | [b (line 84): false] "" | b (line 84): false | +| Assert.cs:91:9:91:24 | [b (line 84): false] call to method IsNull | b (line 84): false | +| Assert.cs:91:9:91:24 | [b (line 84): true] call to method IsNull | b (line 84): true | +| Assert.cs:91:9:91:25 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:91:9:91:25 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:92:9:92:35 | [b (line 84): false] call to method WriteLine | b (line 84): false | +| Assert.cs:92:9:92:35 | [b (line 84): true] call to method WriteLine | b (line 84): true | +| Assert.cs:92:9:92:36 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:92:9:92:36 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:92:27:92:27 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:92:27:92:27 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:92:27:92:34 | [b (line 84): false] access to property Length | b (line 84): false | +| Assert.cs:92:27:92:34 | [b (line 84): true] access to property Length | b (line 84): true | +| Assert.cs:94:9:94:25 | [b (line 84): false] ... = ... | b (line 84): false | +| Assert.cs:94:9:94:25 | [b (line 84): true] ... = ... | b (line 84): true | +| Assert.cs:94:9:94:26 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:94:9:94:26 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:94:13:94:13 | [b (line 84): false] access to parameter b | b (line 84): false | +| Assert.cs:94:13:94:13 | [b (line 84): true] access to parameter b | b (line 84): true | +| Assert.cs:94:13:94:25 | [b (line 84): false] ... ? ... : ... | b (line 84): false | +| Assert.cs:94:13:94:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | +| Assert.cs:94:17:94:20 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:94:24:94:25 | [b (line 84): false] "" | b (line 84): false | +| Assert.cs:95:9:95:27 | [b (line 84): false] call to method IsNotNull | b (line 84): false | +| Assert.cs:95:9:95:27 | [b (line 84): true] call to method IsNotNull | b (line 84): true | +| Assert.cs:95:9:95:28 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:95:9:95:28 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:96:9:96:35 | [b (line 84): false] call to method WriteLine | b (line 84): false | +| Assert.cs:96:9:96:35 | [b (line 84): true] call to method WriteLine | b (line 84): true | +| Assert.cs:96:9:96:36 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:96:9:96:36 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:96:27:96:27 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:96:27:96:27 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:96:27:96:34 | [b (line 84): false] access to property Length | b (line 84): false | +| Assert.cs:96:27:96:34 | [b (line 84): true] access to property Length | b (line 84): true | +| Assert.cs:98:9:98:25 | [b (line 84): false] ... = ... | b (line 84): false | +| Assert.cs:98:9:98:25 | [b (line 84): true] ... = ... | b (line 84): true | +| Assert.cs:98:9:98:26 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:98:9:98:26 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:98:13:98:13 | [b (line 84): false] access to parameter b | b (line 84): false | +| Assert.cs:98:13:98:13 | [b (line 84): true] access to parameter b | b (line 84): true | +| Assert.cs:98:13:98:25 | [b (line 84): false] ... ? ... : ... | b (line 84): false | +| Assert.cs:98:13:98:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | +| Assert.cs:98:17:98:20 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:98:24:98:25 | [b (line 84): false] "" | b (line 84): false | +| Assert.cs:99:9:99:32 | [b (line 84): false] call to method IsTrue | b (line 84): false | +| Assert.cs:99:9:99:32 | [b (line 84): true] call to method IsTrue | b (line 84): true | +| Assert.cs:99:9:99:33 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:99:9:99:33 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:99:23:99:23 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:99:23:99:23 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | b (line 84): false | +| Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | b (line 84): true | +| Assert.cs:99:28:99:31 | [b (line 84): false] null | b (line 84): false | +| Assert.cs:99:28:99:31 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:100:9:100:35 | [b (line 84): false] call to method WriteLine | b (line 84): false | +| Assert.cs:100:9:100:35 | [b (line 84): true] call to method WriteLine | b (line 84): true | +| Assert.cs:100:9:100:36 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:100:9:100:36 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:100:27:100:27 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:100:27:100:27 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:100:27:100:34 | [b (line 84): false] access to property Length | b (line 84): false | +| Assert.cs:100:27:100:34 | [b (line 84): true] access to property Length | b (line 84): true | +| Assert.cs:102:9:102:25 | [b (line 84): false] ... = ... | b (line 84): false | +| Assert.cs:102:9:102:25 | [b (line 84): true] ... = ... | b (line 84): true | +| Assert.cs:102:9:102:26 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:102:9:102:26 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:102:13:102:13 | [b (line 84): false] access to parameter b | b (line 84): false | +| Assert.cs:102:13:102:13 | [b (line 84): true] access to parameter b | b (line 84): true | +| Assert.cs:102:13:102:25 | [b (line 84): false] ... ? ... : ... | b (line 84): false | +| Assert.cs:102:13:102:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | +| Assert.cs:102:17:102:20 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:102:24:102:25 | [b (line 84): false] "" | b (line 84): false | +| Assert.cs:103:9:103:32 | [b (line 84): false] call to method IsTrue | b (line 84): false | +| Assert.cs:103:9:103:32 | [b (line 84): true] call to method IsTrue | b (line 84): true | +| Assert.cs:103:9:103:33 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:103:9:103:33 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:103:23:103:23 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:103:23:103:23 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | b (line 84): false | +| Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | b (line 84): true | +| Assert.cs:103:28:103:31 | [b (line 84): false] null | b (line 84): false | +| Assert.cs:103:28:103:31 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:104:9:104:35 | [b (line 84): false] call to method WriteLine | b (line 84): false | +| Assert.cs:104:9:104:35 | [b (line 84): true] call to method WriteLine | b (line 84): true | +| Assert.cs:104:9:104:36 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:104:9:104:36 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:104:27:104:27 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:104:27:104:27 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:104:27:104:34 | [b (line 84): false] access to property Length | b (line 84): false | +| Assert.cs:104:27:104:34 | [b (line 84): true] access to property Length | b (line 84): true | +| Assert.cs:106:9:106:25 | [b (line 84): false] ... = ... | b (line 84): false | +| Assert.cs:106:9:106:25 | [b (line 84): true] ... = ... | b (line 84): true | +| Assert.cs:106:9:106:26 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:106:9:106:26 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:106:13:106:13 | [b (line 84): false] access to parameter b | b (line 84): false | +| Assert.cs:106:13:106:13 | [b (line 84): true] access to parameter b | b (line 84): true | +| Assert.cs:106:13:106:25 | [b (line 84): false] ... ? ... : ... | b (line 84): false | +| Assert.cs:106:13:106:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | +| Assert.cs:106:17:106:20 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:106:24:106:25 | [b (line 84): false] "" | b (line 84): false | +| Assert.cs:107:9:107:33 | [b (line 84): false] call to method IsFalse | b (line 84): false | +| Assert.cs:107:9:107:33 | [b (line 84): true] call to method IsFalse | b (line 84): true | +| Assert.cs:107:9:107:34 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:107:9:107:34 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:107:24:107:24 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:107:24:107:24 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | b (line 84): false | +| Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | b (line 84): true | +| Assert.cs:107:29:107:32 | [b (line 84): false] null | b (line 84): false | +| Assert.cs:107:29:107:32 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:108:9:108:35 | [b (line 84): false] call to method WriteLine | b (line 84): false | +| Assert.cs:108:9:108:35 | [b (line 84): true] call to method WriteLine | b (line 84): true | +| Assert.cs:108:9:108:36 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:108:9:108:36 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:108:27:108:27 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:108:27:108:27 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:108:27:108:34 | [b (line 84): false] access to property Length | b (line 84): false | +| Assert.cs:108:27:108:34 | [b (line 84): true] access to property Length | b (line 84): true | +| Assert.cs:110:9:110:25 | [b (line 84): false] ... = ... | b (line 84): false | +| Assert.cs:110:9:110:25 | [b (line 84): true] ... = ... | b (line 84): true | +| Assert.cs:110:9:110:26 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:110:9:110:26 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:110:13:110:13 | [b (line 84): false] access to parameter b | b (line 84): false | +| Assert.cs:110:13:110:13 | [b (line 84): true] access to parameter b | b (line 84): true | +| Assert.cs:110:13:110:25 | [b (line 84): false] ... ? ... : ... | b (line 84): false | +| Assert.cs:110:13:110:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | +| Assert.cs:110:17:110:20 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:110:24:110:25 | [b (line 84): false] "" | b (line 84): false | +| Assert.cs:111:9:111:33 | [b (line 84): false] call to method IsFalse | b (line 84): false | +| Assert.cs:111:9:111:33 | [b (line 84): true] call to method IsFalse | b (line 84): true | +| Assert.cs:111:9:111:34 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:111:9:111:34 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:111:24:111:24 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:111:24:111:24 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | b (line 84): false | +| Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | b (line 84): true | +| Assert.cs:111:29:111:32 | [b (line 84): false] null | b (line 84): false | +| Assert.cs:111:29:111:32 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:112:9:112:35 | [b (line 84): false] call to method WriteLine | b (line 84): false | +| Assert.cs:112:9:112:35 | [b (line 84): true] call to method WriteLine | b (line 84): true | +| Assert.cs:112:9:112:36 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:112:9:112:36 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:112:27:112:27 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:112:27:112:27 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:112:27:112:34 | [b (line 84): false] access to property Length | b (line 84): false | +| Assert.cs:112:27:112:34 | [b (line 84): true] access to property Length | b (line 84): true | +| Assert.cs:114:9:114:25 | [b (line 84): false] ... = ... | b (line 84): false | +| Assert.cs:114:9:114:25 | [b (line 84): true] ... = ... | b (line 84): true | +| Assert.cs:114:9:114:26 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:114:9:114:26 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:114:13:114:13 | [b (line 84): false] access to parameter b | b (line 84): false | +| Assert.cs:114:13:114:13 | [b (line 84): true] access to parameter b | b (line 84): true | +| Assert.cs:114:13:114:25 | [b (line 84): false] ... ? ... : ... | b (line 84): false | +| Assert.cs:114:13:114:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | +| Assert.cs:114:17:114:20 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:114:24:114:25 | [b (line 84): false] "" | b (line 84): false | +| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | b (line 84): false | +| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | b (line 84): true | +| Assert.cs:115:9:115:38 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:115:9:115:38 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:115:23:115:23 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | b (line 84): false | +| Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | b (line 84): true | +| Assert.cs:115:23:115:36 | [b (line 84): false] ... && ... | b (line 84): false | +| Assert.cs:115:23:115:36 | [b (line 84): true] ... && ... | b (line 84): true | +| Assert.cs:115:28:115:31 | [b (line 84): false] null | b (line 84): false | +| Assert.cs:115:28:115:31 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | b (line 84): false | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | b (line 84): true | +| Assert.cs:116:9:116:35 | [b (line 84): false] call to method WriteLine | b (line 84): false | +| Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | b (line 84): true | +| Assert.cs:116:9:116:36 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:116:9:116:36 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:116:27:116:27 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:116:27:116:34 | [b (line 84): false] access to property Length | b (line 84): false | +| Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | b (line 84): true | +| Assert.cs:118:9:118:25 | [b (line 84): false] ... = ... | b (line 84): false | +| Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | b (line 84): true | +| Assert.cs:118:9:118:26 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:118:9:118:26 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | b (line 84): false | +| Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | b (line 84): true | +| Assert.cs:118:13:118:25 | [b (line 84): false] ... ? ... : ... | b (line 84): false | +| Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | +| Assert.cs:118:17:118:20 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:118:24:118:25 | [b (line 84): false] "" | b (line 84): false | +| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | b (line 84): false | +| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | b (line 84): true | +| Assert.cs:119:9:119:40 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:119:9:119:40 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:119:24:119:24 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | b (line 84): false | +| Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | b (line 84): true | +| Assert.cs:119:24:119:38 | [b (line 84): false] ... \|\| ... | b (line 84): false | +| Assert.cs:119:24:119:38 | [b (line 84): true] ... \|\| ... | b (line 84): true | +| Assert.cs:119:29:119:32 | [b (line 84): false] null | b (line 84): false | +| Assert.cs:119:29:119:32 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:119:37:119:38 | [b (line 84): false] !... | b (line 84): false | +| Assert.cs:119:37:119:38 | [b (line 84): true] !... | b (line 84): true | +| Assert.cs:119:38:119:38 | [b (line 84): false] access to parameter b | b (line 84): false | +| Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | b (line 84): true | +| Assert.cs:120:9:120:35 | [b (line 84): false] call to method WriteLine | b (line 84): false | +| Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | b (line 84): true | +| Assert.cs:120:9:120:36 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:120:9:120:36 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:120:27:120:27 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:120:27:120:34 | [b (line 84): false] access to property Length | b (line 84): false | +| Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | b (line 84): true | +| Assert.cs:122:9:122:25 | [b (line 84): false] ... = ... | b (line 84): false | +| Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | b (line 84): true | +| Assert.cs:122:9:122:26 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:122:9:122:26 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | b (line 84): false | +| Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | b (line 84): true | +| Assert.cs:122:13:122:25 | [b (line 84): false] ... ? ... : ... | b (line 84): false | +| Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | +| Assert.cs:122:17:122:20 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:122:24:122:25 | [b (line 84): false] "" | b (line 84): false | +| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | b (line 84): false | +| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | b (line 84): true | +| Assert.cs:123:9:123:38 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:123:9:123:38 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:123:23:123:23 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | b (line 84): false | +| Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | b (line 84): true | +| Assert.cs:123:23:123:36 | [b (line 84): false] ... && ... | b (line 84): false | +| Assert.cs:123:23:123:36 | [b (line 84): true] ... && ... | b (line 84): true | +| Assert.cs:123:28:123:31 | [b (line 84): false] null | b (line 84): false | +| Assert.cs:123:28:123:31 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | b (line 84): false | +| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | b (line 84): true | +| Assert.cs:124:9:124:35 | [b (line 84): false] call to method WriteLine | b (line 84): false | +| Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | b (line 84): true | +| Assert.cs:124:9:124:36 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:124:9:124:36 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:124:27:124:27 | [b (line 84): false] access to local variable s | b (line 84): false | +| Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:124:27:124:34 | [b (line 84): false] access to property Length | b (line 84): false | +| Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | b (line 84): true | +| Assert.cs:126:9:126:26 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:126:9:126:26 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | b (line 84): false | +| Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | b (line 84): true | +| Assert.cs:126:13:126:25 | [b (line 84): false] ... ? ... : ... | b (line 84): false | +| Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | | Conditions.cs:6:13:6:13 | [inc (line 3): true] access to parameter x | inc (line 3): true | | Conditions.cs:6:13:6:15 | [inc (line 3): true] ...++ | inc (line 3): true | | Conditions.cs:6:13:6:16 | [inc (line 3): true] ...; | inc (line 3): true | @@ -644,6 +930,18 @@ entryPoint | ArrayCreation.cs:5:12:5:13 | M2 | ArrayCreation.cs:5:28:5:28 | 0 | | ArrayCreation.cs:7:11:7:12 | M3 | ArrayCreation.cs:7:19:7:36 | array creation of type Int32[] | | ArrayCreation.cs:9:12:9:13 | M4 | ArrayCreation.cs:9:20:9:52 | array creation of type Int32[,] | +| Assert.cs:7:10:7:11 | M1 | Assert.cs:8:5:12:5 | {...} | +| Assert.cs:14:10:14:11 | M2 | Assert.cs:15:5:19:5 | {...} | +| Assert.cs:21:10:21:11 | M3 | Assert.cs:22:5:26:5 | {...} | +| Assert.cs:28:10:28:11 | M4 | Assert.cs:29:5:33:5 | {...} | +| Assert.cs:35:10:35:11 | M5 | Assert.cs:36:5:40:5 | {...} | +| Assert.cs:42:10:42:11 | M6 | Assert.cs:43:5:47:5 | {...} | +| Assert.cs:49:10:49:11 | M7 | Assert.cs:50:5:54:5 | {...} | +| Assert.cs:56:10:56:11 | M8 | Assert.cs:57:5:61:5 | {...} | +| Assert.cs:63:10:63:11 | M9 | Assert.cs:64:5:68:5 | {...} | +| Assert.cs:70:10:70:12 | M10 | Assert.cs:71:5:75:5 | {...} | +| Assert.cs:77:10:77:12 | M11 | Assert.cs:78:5:82:5 | {...} | +| Assert.cs:84:10:84:12 | M12 | Assert.cs:85:5:129:5 | {...} | | Assignments.cs:3:10:3:10 | M | Assignments.cs:4:5:15:5 | {...} | | Assignments.cs:14:18:14:35 | (...) => ... | Assignments.cs:14:33:14:35 | {...} | | Assignments.cs:17:40:17:40 | + | Assignments.cs:18:5:20:5 | {...} | diff --git a/csharp/ql/test/library-tests/controlflow/guards/AbstractValue.expected b/csharp/ql/test/library-tests/controlflow/guards/AbstractValue.expected index 092643191f8..cff9d3249ef 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/AbstractValue.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/AbstractValue.expected @@ -32,7 +32,7 @@ abstractValue | 0 | Guards.cs:322:18:322:18 | 0 | | 0 | Guards.cs:329:17:329:19 | access to constant A | | 0 | Guards.cs:334:20:334:20 | 0 | -| 0 | Splitting.cs:136:20:136:20 | 0 | +| 0 | Splitting.cs:137:20:137:20 | 0 | | 1 | Collections.cs:13:28:13:28 | 1 | | 1 | Collections.cs:15:28:15:28 | 1 | | 1 | Collections.cs:18:28:18:28 | 1 | @@ -365,6 +365,9 @@ abstractValue | non-null | Guards.cs:281:17:281:17 | access to local variable a | | non-null | Guards.cs:283:17:283:17 | access to parameter o | | non-null | Guards.cs:287:17:287:17 | access to parameter o | +| non-null | Guards.cs:341:31:341:32 | "" | +| non-null | Guards.cs:343:13:343:19 | access to type Console | +| non-null | Guards.cs:343:31:343:31 | access to local variable s | | non-null | Splitting.cs:13:17:13:17 | access to parameter o | | non-null | Splitting.cs:23:24:23:24 | access to parameter o | | non-null | Splitting.cs:33:24:33:25 | "" | @@ -384,12 +387,13 @@ abstractValue | non-null | Splitting.cs:117:9:117:9 | access to parameter o | | non-null | Splitting.cs:119:13:119:13 | access to parameter o | | non-null | Splitting.cs:120:16:120:16 | access to parameter o | -| non-null | Splitting.cs:132:17:132:17 | access to local variable o | -| non-null | Splitting.cs:132:17:132:29 | ... = ... | -| non-null | Splitting.cs:132:21:132:29 | call to method M11 | -| non-null | Splitting.cs:132:21:132:29 | this access | -| non-null | Splitting.cs:132:28:132:28 | access to local variable o | +| non-null | Splitting.cs:129:17:129:17 | access to local variable o | | non-null | Splitting.cs:133:17:133:17 | access to local variable o | +| non-null | Splitting.cs:133:17:133:29 | ... = ... | +| non-null | Splitting.cs:133:21:133:29 | call to method M11 | +| non-null | Splitting.cs:133:21:133:29 | this access | +| non-null | Splitting.cs:133:28:133:28 | access to local variable o | +| non-null | Splitting.cs:134:17:134:17 | access to local variable o | | null | Assert.cs:9:24:9:27 | null | | null | Assert.cs:10:27:10:30 | null | | null | Assert.cs:16:24:16:27 | null | @@ -438,6 +442,8 @@ abstractValue | null | Guards.cs:181:39:181:42 | null | | null | Guards.cs:185:43:185:46 | null | | null | Guards.cs:203:18:203:21 | null | +| null | Guards.cs:341:24:341:27 | null | +| null | Guards.cs:342:18:342:21 | null | | null | Splitting.cs:12:22:12:25 | null | | null | Splitting.cs:22:22:22:25 | null | | null | Splitting.cs:32:22:32:25 | null | @@ -450,7 +456,7 @@ abstractValue | null | Splitting.cs:105:27:105:30 | null | | null | Splitting.cs:116:27:116:30 | null | | null | Splitting.cs:125:21:125:24 | null | -| null | Splitting.cs:128:22:128:25 | null | +| null | Splitting.cs:129:22:129:25 | null | | true | Guards.cs:177:20:177:23 | true | | true | Guards.cs:181:46:181:49 | true | | true | Guards.cs:185:50:185:53 | true | diff --git a/csharp/ql/test/library-tests/controlflow/guards/BooleanGuardedExpr.expected b/csharp/ql/test/library-tests/controlflow/guards/BooleanGuardedExpr.expected index 2aa76cde6a0..717a6770500 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/BooleanGuardedExpr.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/BooleanGuardedExpr.expected @@ -75,6 +75,7 @@ | Guards.cs:208:17:208:17 | access to parameter o | Guards.cs:203:13:203:21 | ... != ... | Guards.cs:203:13:203:13 | access to parameter o | true | | Guards.cs:269:13:269:14 | access to parameter o1 | Guards.cs:268:13:268:41 | call to operator == | Guards.cs:268:13:268:14 | access to parameter o1 | true | | Guards.cs:271:13:271:14 | access to parameter o1 | Guards.cs:270:13:270:42 | call to operator == | Guards.cs:270:13:270:14 | access to parameter o1 | true | +| Guards.cs:342:27:342:27 | access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | false | | Splitting.cs:13:17:13:17 | access to parameter o | Splitting.cs:12:17:12:25 | ... != ... | Splitting.cs:12:17:12:17 | access to parameter o | true | | Splitting.cs:23:24:23:24 | access to parameter o | Splitting.cs:22:17:22:25 | ... != ... | Splitting.cs:22:17:22:17 | access to parameter o | true | | Splitting.cs:25:13:25:13 | access to parameter o | Splitting.cs:22:17:22:25 | ... != ... | Splitting.cs:22:17:22:17 | access to parameter o | false | @@ -93,4 +94,4 @@ | Splitting.cs:117:9:117:9 | access to parameter o | Splitting.cs:116:22:116:30 | ... != ... | Splitting.cs:116:22:116:22 | access to parameter o | true | | Splitting.cs:119:13:119:13 | access to parameter o | Splitting.cs:116:22:116:30 | ... != ... | Splitting.cs:116:22:116:22 | access to parameter o | true | | Splitting.cs:120:16:120:16 | access to parameter o | Splitting.cs:116:22:116:30 | ... != ... | Splitting.cs:116:22:116:22 | access to parameter o | true | -| Splitting.cs:132:25:132:25 | access to parameter b | Splitting.cs:130:21:130:21 | access to parameter b | Splitting.cs:130:21:130:21 | access to parameter b | false | +| Splitting.cs:133:25:133:25 | access to parameter b | Splitting.cs:131:21:131:21 | access to parameter b | Splitting.cs:131:21:131:21 | access to parameter b | false | diff --git a/csharp/ql/test/library-tests/controlflow/guards/GuardedControlFlowNode.expected b/csharp/ql/test/library-tests/controlflow/guards/GuardedControlFlowNode.expected index e8b4f96bb93..5d351185f66 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/GuardedControlFlowNode.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/GuardedControlFlowNode.expected @@ -192,6 +192,11 @@ | Guards.cs:287:17:287:17 | access to parameter o | Guards.cs:276:16:276:16 | access to parameter o | Guards.cs:276:16:276:16 | access to parameter o | non-match access to type Action | | Guards.cs:287:17:287:17 | access to parameter o | Guards.cs:276:16:276:16 | access to parameter o | Guards.cs:276:16:276:16 | access to parameter o | non-match null | | Guards.cs:287:17:287:17 | access to parameter o | Guards.cs:276:16:276:16 | access to parameter o | Guards.cs:276:16:276:16 | access to parameter o | non-null | +| Guards.cs:342:27:342:27 | [b (line 339): false] access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | false | +| Guards.cs:342:27:342:27 | [b (line 339): false] access to parameter b | Guards.cs:341:20:341:32 | ... ? ... : ... | Guards.cs:341:20:341:20 | access to parameter b | non-null | +| Guards.cs:342:27:342:27 | [b (line 339): true] access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | false | +| Guards.cs:342:27:342:27 | [b (line 339): true] access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | true | +| Guards.cs:342:27:342:27 | [b (line 339): true] access to parameter b | Guards.cs:341:20:341:32 | ... ? ... : ... | Guards.cs:341:20:341:20 | access to parameter b | non-null | | Splitting.cs:13:17:13:17 | [b (line 9): true] access to parameter o | Splitting.cs:12:17:12:17 | access to parameter o | Splitting.cs:12:17:12:17 | access to parameter o | non-null | | Splitting.cs:13:17:13:17 | [b (line 9): true] access to parameter o | Splitting.cs:12:17:12:25 | ... != ... | Splitting.cs:12:17:12:17 | access to parameter o | true | | Splitting.cs:14:13:14:13 | [b (line 9): false] access to parameter b | Splitting.cs:11:13:11:13 | access to parameter b | Splitting.cs:11:13:11:13 | access to parameter b | false | @@ -256,5 +261,5 @@ | Splitting.cs:119:13:119:13 | access to parameter o | Splitting.cs:116:22:116:30 | ... != ... | Splitting.cs:116:22:116:22 | access to parameter o | true | | Splitting.cs:120:16:120:16 | access to parameter o | Splitting.cs:116:22:116:22 | access to parameter o | Splitting.cs:116:22:116:22 | access to parameter o | non-null | | Splitting.cs:120:16:120:16 | access to parameter o | Splitting.cs:116:22:116:30 | ... != ... | Splitting.cs:116:22:116:22 | access to parameter o | true | -| Splitting.cs:130:21:130:21 | [b (line 123): false] access to parameter b | Splitting.cs:130:21:130:21 | access to parameter b | Splitting.cs:130:21:130:21 | access to parameter b | false | -| Splitting.cs:132:25:132:25 | [b (line 123): false] access to parameter b | Splitting.cs:130:21:130:21 | access to parameter b | Splitting.cs:130:21:130:21 | access to parameter b | false | +| Splitting.cs:131:21:131:21 | [b (line 123): false] access to parameter b | Splitting.cs:131:21:131:21 | access to parameter b | Splitting.cs:131:21:131:21 | access to parameter b | false | +| Splitting.cs:133:25:133:25 | [b (line 123): false] access to parameter b | Splitting.cs:131:21:131:21 | access to parameter b | Splitting.cs:131:21:131:21 | access to parameter b | false | diff --git a/csharp/ql/test/library-tests/controlflow/guards/GuardedExpr.expected b/csharp/ql/test/library-tests/controlflow/guards/GuardedExpr.expected index 50159853ea7..adbc50cece7 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/GuardedExpr.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/GuardedExpr.expected @@ -192,6 +192,8 @@ | Guards.cs:287:17:287:17 | access to parameter o | Guards.cs:276:16:276:16 | access to parameter o | Guards.cs:276:16:276:16 | access to parameter o | non-match access to type Action | | Guards.cs:287:17:287:17 | access to parameter o | Guards.cs:276:16:276:16 | access to parameter o | Guards.cs:276:16:276:16 | access to parameter o | non-match null | | Guards.cs:287:17:287:17 | access to parameter o | Guards.cs:276:16:276:16 | access to parameter o | Guards.cs:276:16:276:16 | access to parameter o | non-null | +| Guards.cs:342:27:342:27 | access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | false | +| Guards.cs:342:27:342:27 | access to parameter b | Guards.cs:341:20:341:32 | ... ? ... : ... | Guards.cs:341:20:341:20 | access to parameter b | non-null | | Splitting.cs:13:17:13:17 | access to parameter o | Splitting.cs:12:17:12:17 | access to parameter o | Splitting.cs:12:17:12:17 | access to parameter o | non-null | | Splitting.cs:13:17:13:17 | access to parameter o | Splitting.cs:12:17:12:25 | ... != ... | Splitting.cs:12:17:12:17 | access to parameter o | true | | Splitting.cs:23:24:23:24 | access to parameter o | Splitting.cs:22:17:22:17 | access to parameter o | Splitting.cs:22:17:22:17 | access to parameter o | non-null | @@ -228,4 +230,4 @@ | Splitting.cs:119:13:119:13 | access to parameter o | Splitting.cs:116:22:116:30 | ... != ... | Splitting.cs:116:22:116:22 | access to parameter o | true | | Splitting.cs:120:16:120:16 | access to parameter o | Splitting.cs:116:22:116:22 | access to parameter o | Splitting.cs:116:22:116:22 | access to parameter o | non-null | | Splitting.cs:120:16:120:16 | access to parameter o | Splitting.cs:116:22:116:30 | ... != ... | Splitting.cs:116:22:116:22 | access to parameter o | true | -| Splitting.cs:132:25:132:25 | access to parameter b | Splitting.cs:130:21:130:21 | access to parameter b | Splitting.cs:130:21:130:21 | access to parameter b | false | +| Splitting.cs:133:25:133:25 | access to parameter b | Splitting.cs:131:21:131:21 | access to parameter b | Splitting.cs:131:21:131:21 | access to parameter b | false | diff --git a/csharp/ql/test/library-tests/controlflow/guards/Guards.cs b/csharp/ql/test/library-tests/controlflow/guards/Guards.cs index 67a58f59aac..b8e687c43bb 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/Guards.cs +++ b/csharp/ql/test/library-tests/controlflow/guards/Guards.cs @@ -335,5 +335,12 @@ public class Guards _ => 1 }; } + + void M28(bool b) + { + string s = b ? null : ""; + if (s != null && !b) + Console.WriteLine(s.Length); // null guarded [MISSING] + } } diff --git a/csharp/ql/test/library-tests/controlflow/guards/Implications.expected b/csharp/ql/test/library-tests/controlflow/guards/Implications.expected index ec6c60ff9e8..8763eba9913 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/Implications.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/Implications.expected @@ -416,6 +416,24 @@ | Guards.cs:332:16:332:16 | access to local variable e | match access to constant B | Guards.cs:330:13:330:13 | access to parameter b | true | | Guards.cs:332:16:332:16 | access to local variable e | match access to constant B | Guards.cs:332:16:332:16 | access to local variable e | 1 | | Guards.cs:332:16:332:16 | access to local variable e | non-match access to constant B | Guards.cs:330:13:330:13 | access to parameter b | false | +| Guards.cs:341:20:341:32 | ... ? ... : ... | non-null | Guards.cs:341:20:341:20 | access to parameter b | false | +| Guards.cs:341:20:341:32 | ... ? ... : ... | non-null | Guards.cs:341:31:341:32 | "" | non-null | +| Guards.cs:341:20:341:32 | ... ? ... : ... | null | Guards.cs:341:20:341:20 | access to parameter b | true | +| Guards.cs:341:20:341:32 | ... ? ... : ... | null | Guards.cs:341:24:341:27 | null | null | +| Guards.cs:342:13:342:13 | access to local variable s | empty | Guards.cs:341:20:341:32 | ... ? ... : ... | empty | +| Guards.cs:342:13:342:13 | access to local variable s | non-empty | Guards.cs:341:20:341:32 | ... ? ... : ... | non-empty | +| Guards.cs:342:13:342:13 | access to local variable s | non-null | Guards.cs:341:20:341:32 | ... ? ... : ... | non-null | +| Guards.cs:342:13:342:13 | access to local variable s | null | Guards.cs:341:20:341:32 | ... ? ... : ... | null | +| Guards.cs:342:13:342:21 | ... != ... | false | Guards.cs:341:20:341:20 | access to parameter b | true | +| Guards.cs:342:13:342:21 | ... != ... | false | Guards.cs:342:13:342:13 | access to local variable s | null | +| Guards.cs:342:13:342:21 | ... != ... | true | Guards.cs:341:20:341:20 | access to parameter b | false | +| Guards.cs:342:13:342:21 | ... != ... | true | Guards.cs:342:13:342:13 | access to local variable s | non-null | +| Guards.cs:342:13:342:27 | ... && ... | true | Guards.cs:342:13:342:21 | ... != ... | true | +| Guards.cs:342:13:342:27 | ... && ... | true | Guards.cs:342:26:342:27 | !... | true | +| Guards.cs:342:26:342:27 | !... | false | Guards.cs:342:27:342:27 | access to parameter b | true | +| Guards.cs:342:26:342:27 | !... | true | Guards.cs:342:27:342:27 | access to parameter b | false | +| Guards.cs:343:31:343:31 | access to local variable s | non-null | Guards.cs:341:20:341:32 | ... ? ... : ... | non-null | +| Guards.cs:343:31:343:31 | access to local variable s | null | Guards.cs:341:20:341:32 | ... ? ... : ... | null | | Splitting.cs:12:17:12:25 | ... != ... | false | Splitting.cs:12:17:12:17 | access to parameter o | null | | Splitting.cs:12:17:12:25 | ... != ... | true | Splitting.cs:12:17:12:17 | access to parameter o | non-null | | Splitting.cs:22:17:22:25 | ... != ... | false | Splitting.cs:22:17:22:17 | access to parameter o | null | @@ -438,7 +456,8 @@ | Splitting.cs:105:22:105:30 | ... != ... | true | Splitting.cs:105:22:105:22 | access to parameter o | non-null | | Splitting.cs:116:22:116:30 | ... != ... | false | Splitting.cs:116:22:116:22 | access to parameter o | null | | Splitting.cs:116:22:116:30 | ... != ... | true | Splitting.cs:116:22:116:22 | access to parameter o | non-null | -| Splitting.cs:128:17:128:25 | ... != ... | false | Splitting.cs:128:17:128:17 | access to local variable o | null | -| Splitting.cs:128:17:128:25 | ... != ... | true | Splitting.cs:128:17:128:17 | access to local variable o | non-null | -| Splitting.cs:133:17:133:17 | access to local variable o | non-null | Splitting.cs:132:21:132:29 | call to method M11 | non-null | -| Splitting.cs:133:17:133:17 | access to local variable o | null | Splitting.cs:132:21:132:29 | call to method M11 | null | +| Splitting.cs:129:17:129:25 | ... != ... | false | Splitting.cs:129:17:129:17 | access to local variable o | null | +| Splitting.cs:129:17:129:25 | ... != ... | false | Splitting.cs:129:22:129:25 | null | non-null | +| Splitting.cs:129:17:129:25 | ... != ... | true | Splitting.cs:129:17:129:17 | access to local variable o | non-null | +| Splitting.cs:134:17:134:17 | access to local variable o | non-null | Splitting.cs:133:21:133:29 | call to method M11 | non-null | +| Splitting.cs:134:17:134:17 | access to local variable o | null | Splitting.cs:133:21:133:29 | call to method M11 | null | diff --git a/csharp/ql/test/library-tests/controlflow/guards/Splitting.cs b/csharp/ql/test/library-tests/controlflow/guards/Splitting.cs index 1efbaa8251f..76ccdd0f633 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/Splitting.cs +++ b/csharp/ql/test/library-tests/controlflow/guards/Splitting.cs @@ -125,6 +125,7 @@ public class Splitting object? o = null; do { + o.GetHashCode(); // not null guarded if (o != null) { if (b) diff --git a/csharp/ql/test/query-tests/Nullness/Assert.cs b/csharp/ql/test/query-tests/Nullness/Assert.cs index c483d1f36d3..a57ba59a861 100644 --- a/csharp/ql/test/query-tests/Nullness/Assert.cs +++ b/csharp/ql/test/query-tests/Nullness/Assert.cs @@ -39,7 +39,7 @@ class AssertTests Console.WriteLine(s.Length); // GOOD s = b ? null : ""; - Assert.IsFalse(s == null || b); + Assert.IsFalse(s == null || !b); Console.WriteLine(s.Length); // GOOD s = b ? null : ""; @@ -47,7 +47,7 @@ class AssertTests Console.WriteLine(s.Length); // BAD (always) s = b ? null : ""; - Assert.IsFalse(s != null || b); + Assert.IsFalse(s != null || !b); Console.WriteLine(s.Length); // BAD (always) } } diff --git a/csharp/ql/test/query-tests/Nullness/Implications.expected b/csharp/ql/test/query-tests/Nullness/Implications.expected index edb06970113..cd1c4113358 100644 --- a/csharp/ql/test/query-tests/Nullness/Implications.expected +++ b/csharp/ql/test/query-tests/Nullness/Implications.expected @@ -164,8 +164,10 @@ | Assert.cs:42:24:42:32 | ... == ... | false | Assert.cs:42:24:42:24 | access to local variable s | non-null | | Assert.cs:42:24:42:32 | ... == ... | true | Assert.cs:41:13:41:13 | access to parameter b | true | | Assert.cs:42:24:42:32 | ... == ... | true | Assert.cs:42:24:42:24 | access to local variable s | null | -| Assert.cs:42:24:42:37 | ... \|\| ... | false | Assert.cs:42:24:42:32 | ... == ... | false | -| Assert.cs:42:24:42:37 | ... \|\| ... | false | Assert.cs:42:37:42:37 | access to parameter b | false | +| Assert.cs:42:24:42:38 | ... \|\| ... | false | Assert.cs:42:24:42:32 | ... == ... | false | +| Assert.cs:42:24:42:38 | ... \|\| ... | false | Assert.cs:42:37:42:38 | !... | false | +| Assert.cs:42:37:42:38 | !... | false | Assert.cs:42:38:42:38 | access to parameter b | true | +| Assert.cs:42:37:42:38 | !... | true | Assert.cs:42:38:42:38 | access to parameter b | false | | Assert.cs:43:27:43:27 | access to local variable s | non-null | Assert.cs:41:13:41:25 | ... ? ... : ... | non-null | | Assert.cs:43:27:43:27 | access to local variable s | null | Assert.cs:41:13:41:25 | ... ? ... : ... | null | | Assert.cs:45:13:45:25 | ... ? ... : ... | non-null | Assert.cs:45:13:45:13 | access to parameter b | false | @@ -196,8 +198,10 @@ | Assert.cs:50:24:50:32 | ... != ... | false | Assert.cs:50:24:50:24 | access to local variable s | null | | Assert.cs:50:24:50:32 | ... != ... | true | Assert.cs:49:13:49:13 | access to parameter b | false | | Assert.cs:50:24:50:32 | ... != ... | true | Assert.cs:50:24:50:24 | access to local variable s | non-null | -| Assert.cs:50:24:50:37 | ... \|\| ... | false | Assert.cs:50:24:50:32 | ... != ... | false | -| Assert.cs:50:24:50:37 | ... \|\| ... | false | Assert.cs:50:37:50:37 | access to parameter b | false | +| Assert.cs:50:24:50:38 | ... \|\| ... | false | Assert.cs:50:24:50:32 | ... != ... | false | +| Assert.cs:50:24:50:38 | ... \|\| ... | false | Assert.cs:50:37:50:38 | !... | false | +| Assert.cs:50:37:50:38 | !... | false | Assert.cs:50:38:50:38 | access to parameter b | true | +| Assert.cs:50:37:50:38 | !... | true | Assert.cs:50:38:50:38 | access to parameter b | false | | Assert.cs:51:27:51:27 | access to local variable s | non-null | Assert.cs:49:13:49:25 | ... ? ... : ... | non-null | | Assert.cs:51:27:51:27 | access to local variable s | null | Assert.cs:49:13:49:25 | ... ? ... : ... | null | | B.cs:12:13:12:24 | access to local variable eqCallAlways | non-null | B.cs:7:26:7:29 | null | non-null | diff --git a/csharp/ql/test/query-tests/Nullness/NullMaybe.expected b/csharp/ql/test/query-tests/Nullness/NullMaybe.expected index d388d0fdacb..3db367e90ba 100644 --- a/csharp/ql/test/query-tests/Nullness/NullMaybe.expected +++ b/csharp/ql/test/query-tests/Nullness/NullMaybe.expected @@ -37,7 +37,7 @@ nodes | Assert.cs:47:27:47:27 | access to local variable s | | Assert.cs:47:27:47:27 | access to local variable s | | Assert.cs:49:9:49:25 | SSA def(s) | -| Assert.cs:50:37:50:37 | access to parameter b | +| Assert.cs:50:37:50:38 | !... | | Assert.cs:51:27:51:27 | access to local variable s | | B.cs:7:11:7:29 | SSA def(eqCallAlways) | | B.cs:10:11:10:30 | SSA def(neqCallAlways) | @@ -427,8 +427,8 @@ edges | Assert.cs:45:9:45:25 | [b (line 7): true] SSA def(s) | Assert.cs:46:36:46:36 | [b (line 7): true] access to parameter b | | Assert.cs:46:36:46:36 | [b (line 7): false] access to parameter b | Assert.cs:47:27:47:27 | access to local variable s | | Assert.cs:46:36:46:36 | [b (line 7): true] access to parameter b | Assert.cs:47:27:47:27 | access to local variable s | -| Assert.cs:49:9:49:25 | SSA def(s) | Assert.cs:50:37:50:37 | access to parameter b | -| Assert.cs:50:37:50:37 | access to parameter b | Assert.cs:51:27:51:27 | access to local variable s | +| Assert.cs:49:9:49:25 | SSA def(s) | Assert.cs:50:37:50:38 | !... | +| Assert.cs:50:37:50:38 | !... | Assert.cs:51:27:51:27 | access to local variable s | | B.cs:7:11:7:29 | SSA def(eqCallAlways) | B.cs:13:13:13:24 | access to local variable eqCallAlways | | B.cs:10:11:10:30 | SSA def(neqCallAlways) | B.cs:13:13:13:36 | ...; | | B.cs:10:11:10:30 | SSA def(neqCallAlways) | B.cs:15:9:16:26 | if (...) ... | From 072e1967c13ad70773aa986fbec3243a28ac1cd9 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 2 Oct 2020 15:51:29 +0200 Subject: [PATCH 183/411] C++: Accept more tests --- .../CWE/CWE-134/semmle/argv/argvLocal.expected | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected index 6182251cc76..20a501b9f09 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected @@ -65,26 +65,26 @@ edges | argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | (const char *)... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | Argument 0 indirection | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | Argument 0 indirection | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | printWrapper output argument | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | printWrapper output argument | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | (const char *)... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | (const char *)... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | Argument 0 indirection | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | Argument 0 indirection | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | printWrapper output argument | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | printWrapper output argument | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | (const char *)... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | (const char *)... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | @@ -93,19 +93,17 @@ edges | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | -| argvLocal.c:117:15:117:16 | Argument 0 indirection | argvLocal.c:117:15:117:16 | printWrapper output argument | | argvLocal.c:117:15:117:16 | array to pointer conversion | argvLocal.c:117:15:117:16 | printWrapper output argument | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | (const char *)... | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | i4 | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | Argument 0 indirection | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | i4 | +| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | printWrapper output argument | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | (const char *)... | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | ... ++ | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | -- ... | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | -- ... | -| argvLocal.c:122:15:122:16 | Argument 0 indirection | argvLocal.c:122:15:122:16 | printWrapper output argument | | argvLocal.c:122:15:122:16 | i4 | argvLocal.c:122:15:122:16 | printWrapper output argument | | argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | (const char *)... | | argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | ... ++ | @@ -115,14 +113,14 @@ edges | argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | (const char *)... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | Argument 0 indirection | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | Argument 0 indirection | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | printWrapper output argument | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | printWrapper output argument | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | (const char *)... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | (const char *)... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... | @@ -131,7 +129,6 @@ edges | argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | -| argvLocal.c:128:15:128:16 | Argument 0 indirection | argvLocal.c:128:15:128:16 | printWrapper output argument | | argvLocal.c:128:15:128:16 | array to pointer conversion | argvLocal.c:128:15:128:16 | printWrapper output argument | | argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:131:9:131:14 | (const char *)... | | argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:131:9:131:14 | ... + ... | From 28ab092e9f16ee41e17efc414212e4a635ff6803 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 Oct 2020 15:54:26 +0100 Subject: [PATCH 184/411] C++: Add 'tainted' markers to standalone_iterators.cpp test. --- .../dataflow/taint-tests/standalone_iterators.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/standalone_iterators.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/standalone_iterators.cpp index 24b585c3506..60c36412a91 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/standalone_iterators.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/standalone_iterators.cpp @@ -37,15 +37,15 @@ public: }; void test_typedefs(int_iterator_by_typedefs source1) { - sink(*source1); - sink(*(source1++)); - sink(*(++source1)); + sink(*source1); // tainted + sink(*(source1++)); // tainted + sink(*(++source1)); // tainted } void test_trait(int_iterator_by_trait source1) { - sink(*source1); - sink(*(source1++)); - sink(*(++source1)); + sink(*source1); // tainted + sink(*(source1++)); // tainted + sink(*(++source1)); // tainted } void test_non_iterator(non_iterator source1) { From fc45b6cd3cee747044469669fc3680bf2ec79f64 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Thu, 1 Oct 2020 19:43:14 +0200 Subject: [PATCH 185/411] Drop 'tech-inventory' and 'code duplication' queries from the standard query suites --- cpp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql | 1 + cpp/ql/src/codeql-suites/cpp-lgtm-full.qls | 3 --- cpp/ql/src/external/DuplicateBlock.ql | 1 + cpp/ql/src/external/DuplicateFunction.ql | 1 + cpp/ql/src/external/MostlyDuplicateClass.ql | 1 + cpp/ql/src/external/MostlyDuplicateFile.ql | 1 + cpp/ql/src/external/MostlyDuplicateFunction.ql | 1 + cpp/ql/src/external/MostlySimilarFile.ql | 1 + csharp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql | 1 + csharp/ql/src/codeql-suites/csharp-lgtm-full.qls | 3 --- csharp/ql/src/external/DuplicateMethod.ql | 1 + csharp/ql/src/external/MostlyDuplicateClass.ql | 1 + csharp/ql/src/external/MostlyDuplicateFile.ql | 1 + csharp/ql/src/external/MostlyDuplicateMethod.ql | 1 + csharp/ql/src/external/MostlySimilarFile.ql | 1 + java/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql | 1 + java/ql/src/Metrics/Files/FLinesOfSimilarCode.ql | 1 + java/ql/src/codeql-suites/java-lgtm-full.qls | 3 --- java/ql/src/external/DuplicateAnonymous.ql | 1 + java/ql/src/external/DuplicateBlock.ql | 1 + java/ql/src/external/DuplicateMethod.ql | 1 + java/ql/src/external/MostlyDuplicateClass.ql | 1 + java/ql/src/external/MostlyDuplicateFile.ql | 1 + java/ql/src/external/MostlyDuplicateMethod.ql | 1 + java/ql/src/external/MostlySimilarFile.ql | 1 + javascript/ql/src/Metrics/FLinesOfDuplicatedCode.ql | 1 + javascript/ql/src/Metrics/FLinesOfSimilarCode.ql | 1 + javascript/ql/src/codeql-suites/javascript-lgtm-full.qls | 4 ---- javascript/ql/src/external/DuplicateFunction.ql | 1 + javascript/ql/src/external/DuplicateToplevel.ql | 1 + javascript/ql/src/external/SimilarFunction.ql | 1 + javascript/ql/src/external/SimilarToplevel.ql | 1 + python/ql/src/Metrics/FLinesOfDuplicatedCode.ql | 1 + python/ql/src/Metrics/FLinesOfSimilarCode.ql | 1 + python/ql/src/codeql-suites/python-lgtm-full.qls | 4 ---- python/ql/src/external/DuplicateFunction.ql | 1 + python/ql/src/external/MostlyDuplicateClass.ql | 1 + python/ql/src/external/MostlyDuplicateFile.ql | 1 + python/ql/src/external/MostlySimilarFile.ql | 1 + python/ql/src/external/SimilarFunction.ql | 1 + 40 files changed, 35 insertions(+), 17 deletions(-) diff --git a/cpp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql b/cpp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql index 3a11eb3575a..ab9317ea316 100644 --- a/cpp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql +++ b/cpp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Duplicated lines in files * @description The number of lines in a file, including code, comment * and whitespace lines, which are duplicated in at least diff --git a/cpp/ql/src/codeql-suites/cpp-lgtm-full.qls b/cpp/ql/src/codeql-suites/cpp-lgtm-full.qls index 5e47d12e97c..b6775597c30 100644 --- a/cpp/ql/src/codeql-suites/cpp-lgtm-full.qls +++ b/cpp/ql/src/codeql-suites/cpp-lgtm-full.qls @@ -9,10 +9,7 @@ tags contain: - ide-contextual-queries/local-definitions - ide-contextual-queries/local-references -- query: Metrics/Dependencies/ExternalDependencies.ql -- query: Metrics/Dependencies/ExternalDependenciesSourceLinks.ql - query: Metrics/Files/FLinesOfCode.ql - query: Metrics/Files/FLinesOfCommentedOutCode.ql - query: Metrics/Files/FLinesOfComments.ql -- query: Metrics/Files/FLinesOfDuplicatedCode.ql - query: Metrics/Files/FNumberOfTests.ql diff --git a/cpp/ql/src/external/DuplicateBlock.ql b/cpp/ql/src/external/DuplicateBlock.ql index 90070ed6a7d..3fdef9b510d 100644 --- a/cpp/ql/src/external/DuplicateBlock.ql +++ b/cpp/ql/src/external/DuplicateBlock.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Duplicate code * @description This block of code is duplicated elsewhere. If possible, the shared code should be refactored so there is only one occurrence left. It may not always be possible to address these issues; other duplicate code checks (such as duplicate function, duplicate class) give subsets of the results with higher confidence. * @kind problem diff --git a/cpp/ql/src/external/DuplicateFunction.ql b/cpp/ql/src/external/DuplicateFunction.ql index ca749315bbf..1a861867fcb 100644 --- a/cpp/ql/src/external/DuplicateFunction.ql +++ b/cpp/ql/src/external/DuplicateFunction.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Duplicate function * @description There is another identical implementation of this function. Extract the code to a common file or superclass or delegate to improve sharing. * @kind problem diff --git a/cpp/ql/src/external/MostlyDuplicateClass.ql b/cpp/ql/src/external/MostlyDuplicateClass.ql index a7d6cc605a6..20b9f39214e 100644 --- a/cpp/ql/src/external/MostlyDuplicateClass.ql +++ b/cpp/ql/src/external/MostlyDuplicateClass.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Mostly duplicate class * @description More than 80% of the methods in this class are duplicated in another class. Create a common supertype to improve code sharing. * @kind problem diff --git a/cpp/ql/src/external/MostlyDuplicateFile.ql b/cpp/ql/src/external/MostlyDuplicateFile.ql index 13ad0707ce8..8cb23a432d2 100644 --- a/cpp/ql/src/external/MostlyDuplicateFile.ql +++ b/cpp/ql/src/external/MostlyDuplicateFile.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Mostly duplicate file * @description There is another file that shares a lot of the code with this file. Merge the two files to improve maintainability. * @kind problem diff --git a/cpp/ql/src/external/MostlyDuplicateFunction.ql b/cpp/ql/src/external/MostlyDuplicateFunction.ql index 1ec592a6568..8a7454e4c97 100644 --- a/cpp/ql/src/external/MostlyDuplicateFunction.ql +++ b/cpp/ql/src/external/MostlyDuplicateFunction.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Mostly duplicate function * @description There is another function that shares a lot of the code with this one. Extract the code to a common file/superclass or delegate to improve sharing. * @kind problem diff --git a/cpp/ql/src/external/MostlySimilarFile.ql b/cpp/ql/src/external/MostlySimilarFile.ql index 27830a5c951..81a6ed02d6c 100644 --- a/cpp/ql/src/external/MostlySimilarFile.ql +++ b/cpp/ql/src/external/MostlySimilarFile.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Mostly similar file * @description There is another file that shares a lot of the code with this file. Notice that names of variables and types may have been changed. Merge the two files to improve maintainability. * @kind problem diff --git a/csharp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql b/csharp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql index 3237035f897..bf3da5e1f80 100644 --- a/csharp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql +++ b/csharp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Duplicated lines in files * @description The number of lines in a file, including code, comment and whitespace lines, * which are duplicated in at least one other place. diff --git a/csharp/ql/src/codeql-suites/csharp-lgtm-full.qls b/csharp/ql/src/codeql-suites/csharp-lgtm-full.qls index b1a5b783905..8ba077663d0 100644 --- a/csharp/ql/src/codeql-suites/csharp-lgtm-full.qls +++ b/csharp/ql/src/codeql-suites/csharp-lgtm-full.qls @@ -7,10 +7,7 @@ tags contain: - ide-contextual-queries/local-definitions - ide-contextual-queries/local-references -- query: Metrics/Dependencies/ExternalDependencies.ql -- query: Metrics/Dependencies/ExternalDependenciesSourceLinks.ql - query: Metrics/Files/FLinesOfCode.ql - query: Metrics/Files/FLinesOfCommentedCode.ql - query: Metrics/Files/FLinesOfComment.ql -- query: Metrics/Files/FLinesOfDuplicatedCode.ql - query: Metrics/Files/FNumberOfTests.ql diff --git a/csharp/ql/src/external/DuplicateMethod.ql b/csharp/ql/src/external/DuplicateMethod.ql index 57255ce51d0..371315cd4e6 100644 --- a/csharp/ql/src/external/DuplicateMethod.ql +++ b/csharp/ql/src/external/DuplicateMethod.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Duplicate method * @description There is another identical implementation of this method. Extract the code to a common superclass or delegate to improve sharing. * @kind problem diff --git a/csharp/ql/src/external/MostlyDuplicateClass.ql b/csharp/ql/src/external/MostlyDuplicateClass.ql index fd4fc87c176..7b7d5ef3eff 100644 --- a/csharp/ql/src/external/MostlyDuplicateClass.ql +++ b/csharp/ql/src/external/MostlyDuplicateClass.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Duplicate class * @description More than 80% of the methods in this class are duplicated in another class. Create a common supertype to improve code sharing. * @kind problem diff --git a/csharp/ql/src/external/MostlyDuplicateFile.ql b/csharp/ql/src/external/MostlyDuplicateFile.ql index 0100e94bc7c..2dbc2e17ffb 100644 --- a/csharp/ql/src/external/MostlyDuplicateFile.ql +++ b/csharp/ql/src/external/MostlyDuplicateFile.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Mostly duplicate file * @description There is another file that shares a lot of the code with this file. Merge the two files to improve maintainability. * @kind problem diff --git a/csharp/ql/src/external/MostlyDuplicateMethod.ql b/csharp/ql/src/external/MostlyDuplicateMethod.ql index a7d01ed0ed9..aa0003c113b 100644 --- a/csharp/ql/src/external/MostlyDuplicateMethod.ql +++ b/csharp/ql/src/external/MostlyDuplicateMethod.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Mostly duplicate method * @description There is another method that shares a lot of the code with this method. Extract the code to a common superclass or delegate to improve sharing. * @kind problem diff --git a/csharp/ql/src/external/MostlySimilarFile.ql b/csharp/ql/src/external/MostlySimilarFile.ql index 1c175a72bbd..a66df834aca 100644 --- a/csharp/ql/src/external/MostlySimilarFile.ql +++ b/csharp/ql/src/external/MostlySimilarFile.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Mostly similar file * @description There is another file that shares a lot of the code with this file. Notice that names of variables and types may have been changed. Merge the two files to improve maintainability. * @kind problem diff --git a/java/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql b/java/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql index 30a14df6c60..f6e99fa6b4b 100644 --- a/java/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql +++ b/java/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Duplicated lines in files * @description The number of lines in a file, including code, comment and whitespace lines, * which are duplicated in at least one other place. diff --git a/java/ql/src/Metrics/Files/FLinesOfSimilarCode.ql b/java/ql/src/Metrics/Files/FLinesOfSimilarCode.ql index b8d503bb01a..f7de197055f 100644 --- a/java/ql/src/Metrics/Files/FLinesOfSimilarCode.ql +++ b/java/ql/src/Metrics/Files/FLinesOfSimilarCode.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Similar lines in files * @description The number of lines in a file, including code, comment and whitespace lines, * which are similar to lines in at least one other place. diff --git a/java/ql/src/codeql-suites/java-lgtm-full.qls b/java/ql/src/codeql-suites/java-lgtm-full.qls index 40469bd45bb..542174d9101 100644 --- a/java/ql/src/codeql-suites/java-lgtm-full.qls +++ b/java/ql/src/codeql-suites/java-lgtm-full.qls @@ -7,10 +7,7 @@ tags contain: - ide-contextual-queries/local-definitions - ide-contextual-queries/local-references -- query: Metrics/Dependencies/ExternalDependencies.ql -- query: Metrics/Dependencies/ExternalDependenciesSourceLinks.ql - query: Metrics/Files/FLinesOfCode.ql - query: Metrics/Files/FLinesOfCommentedCode.ql - query: Metrics/Files/FLinesOfComment.ql -- query: Metrics/Files/FLinesOfDuplicatedCode.ql - query: Metrics/Files/FNumberOfTests.ql diff --git a/java/ql/src/external/DuplicateAnonymous.ql b/java/ql/src/external/DuplicateAnonymous.ql index 79b291dca01..1be9ff3922f 100644 --- a/java/ql/src/external/DuplicateAnonymous.ql +++ b/java/ql/src/external/DuplicateAnonymous.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Duplicate anonymous class * @description Duplicated anonymous classes indicate that refactoring is necessary. * @kind problem diff --git a/java/ql/src/external/DuplicateBlock.ql b/java/ql/src/external/DuplicateBlock.ql index dbee6e5767c..0e4c5d7eb93 100644 --- a/java/ql/src/external/DuplicateBlock.ql +++ b/java/ql/src/external/DuplicateBlock.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Duplicate code * @description This block of code is duplicated elsewhere. If possible, the shared code should be refactored so there is only one occurrence left. It may not always be possible to address these issues; other duplicate code checks (such as duplicate function, duplicate class) give subsets of the results with higher confidence. * @kind problem diff --git a/java/ql/src/external/DuplicateMethod.ql b/java/ql/src/external/DuplicateMethod.ql index f094707ac56..4ec8740e475 100644 --- a/java/ql/src/external/DuplicateMethod.ql +++ b/java/ql/src/external/DuplicateMethod.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Duplicate method * @description Duplicated methods make code more difficult to understand and introduce a risk of * changes being made to only one copy. diff --git a/java/ql/src/external/MostlyDuplicateClass.ql b/java/ql/src/external/MostlyDuplicateClass.ql index 897e117c799..864c44384c6 100644 --- a/java/ql/src/external/MostlyDuplicateClass.ql +++ b/java/ql/src/external/MostlyDuplicateClass.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Mostly duplicate class * @description Classes in which most of the methods are duplicated in another class make code more * difficult to understand and introduce a risk of changes being made to only one copy. diff --git a/java/ql/src/external/MostlyDuplicateFile.ql b/java/ql/src/external/MostlyDuplicateFile.ql index 8c194342934..86dfa725c25 100644 --- a/java/ql/src/external/MostlyDuplicateFile.ql +++ b/java/ql/src/external/MostlyDuplicateFile.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Mostly duplicate file * @description Files in which most of the lines are duplicated in another file make code more * difficult to understand and introduce a risk of changes being made to only one copy. diff --git a/java/ql/src/external/MostlyDuplicateMethod.ql b/java/ql/src/external/MostlyDuplicateMethod.ql index 7e276836043..2f47c9ea373 100644 --- a/java/ql/src/external/MostlyDuplicateMethod.ql +++ b/java/ql/src/external/MostlyDuplicateMethod.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Mostly duplicate method * @description Methods in which most of the lines are duplicated in another method make code more * difficult to understand and introduce a risk of changes being made to only one copy. diff --git a/java/ql/src/external/MostlySimilarFile.ql b/java/ql/src/external/MostlySimilarFile.ql index 1d30077cdd9..5b0ab87c91a 100644 --- a/java/ql/src/external/MostlySimilarFile.ql +++ b/java/ql/src/external/MostlySimilarFile.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Mostly similar file * @description Files in which most of the lines are similar to those in another file make code more * difficult to understand and introduce a risk of changes being made to only one copy. diff --git a/javascript/ql/src/Metrics/FLinesOfDuplicatedCode.ql b/javascript/ql/src/Metrics/FLinesOfDuplicatedCode.ql index ca323c8b18b..59bb0b337fb 100644 --- a/javascript/ql/src/Metrics/FLinesOfDuplicatedCode.ql +++ b/javascript/ql/src/Metrics/FLinesOfDuplicatedCode.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Duplicated lines in files * @description The number of lines in a file (including code, comment and whitespace lines) * occurring in a block of lines that is duplicated at least once somewhere else. diff --git a/javascript/ql/src/Metrics/FLinesOfSimilarCode.ql b/javascript/ql/src/Metrics/FLinesOfSimilarCode.ql index d088242ab1e..be6685af968 100644 --- a/javascript/ql/src/Metrics/FLinesOfSimilarCode.ql +++ b/javascript/ql/src/Metrics/FLinesOfSimilarCode.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Similar lines in files * @description The number of lines in a file (including code, comment and whitespace lines) * occurring in a block of lines that is similar to a block of lines seen diff --git a/javascript/ql/src/codeql-suites/javascript-lgtm-full.qls b/javascript/ql/src/codeql-suites/javascript-lgtm-full.qls index 7e45fb7fe01..98de43e41a9 100644 --- a/javascript/ql/src/codeql-suites/javascript-lgtm-full.qls +++ b/javascript/ql/src/codeql-suites/javascript-lgtm-full.qls @@ -8,10 +8,6 @@ - ide-contextual-queries/local-definitions - ide-contextual-queries/local-references - query: Comments/FCommentedOutCode.ql -- query: Metrics/Dependencies/ExternalDependencies.ql -- query: Metrics/Dependencies/ExternalDependenciesSourceLinks.ql - query: Metrics/FLinesOfCode.ql - query: Metrics/FLinesOfComment.ql -- query: Metrics/FLinesOfDuplicatedCode.ql -- query: Metrics/FLinesOfSimilarCode.ql - query: Metrics/FNumberOfTests.ql diff --git a/javascript/ql/src/external/DuplicateFunction.ql b/javascript/ql/src/external/DuplicateFunction.ql index 5d466a123a2..a59741a3670 100644 --- a/javascript/ql/src/external/DuplicateFunction.ql +++ b/javascript/ql/src/external/DuplicateFunction.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Duplicate function * @description There is another function that shares a lot of code with this function. * Extract the common parts to a shared utility function to improve maintainability. diff --git a/javascript/ql/src/external/DuplicateToplevel.ql b/javascript/ql/src/external/DuplicateToplevel.ql index c1459cd0efe..07d0c5a3d87 100644 --- a/javascript/ql/src/external/DuplicateToplevel.ql +++ b/javascript/ql/src/external/DuplicateToplevel.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Duplicate script * @description There is another script that shares a lot of code with this script. Consider combining the * two scripts to improve maintainability. diff --git a/javascript/ql/src/external/SimilarFunction.ql b/javascript/ql/src/external/SimilarFunction.ql index fe4d10edda7..13437dffc54 100644 --- a/javascript/ql/src/external/SimilarFunction.ql +++ b/javascript/ql/src/external/SimilarFunction.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Similar function * @description There is another function that shares a lot of code with this function. * Extract the common parts to a shared utility function to improve maintainability. diff --git a/javascript/ql/src/external/SimilarToplevel.ql b/javascript/ql/src/external/SimilarToplevel.ql index 7307344102c..c9cbba38be0 100644 --- a/javascript/ql/src/external/SimilarToplevel.ql +++ b/javascript/ql/src/external/SimilarToplevel.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Similar script * @description There is another script that shares a lot of code with this script. * Extract the common parts to a new script to improve maintainability.. diff --git a/python/ql/src/Metrics/FLinesOfDuplicatedCode.ql b/python/ql/src/Metrics/FLinesOfDuplicatedCode.ql index 36602310dd5..3b503f697d1 100644 --- a/python/ql/src/Metrics/FLinesOfDuplicatedCode.ql +++ b/python/ql/src/Metrics/FLinesOfDuplicatedCode.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Duplicated lines in files * @description The number of lines in a file, including code, comment and whitespace lines, * which are duplicated in at least one other place. diff --git a/python/ql/src/Metrics/FLinesOfSimilarCode.ql b/python/ql/src/Metrics/FLinesOfSimilarCode.ql index b9eb3ddfaa1..714286a8047 100644 --- a/python/ql/src/Metrics/FLinesOfSimilarCode.ql +++ b/python/ql/src/Metrics/FLinesOfSimilarCode.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Similar lines in files * @description The number of lines in a file, including code, comment and whitespace lines, * which are similar in at least one other place. diff --git a/python/ql/src/codeql-suites/python-lgtm-full.qls b/python/ql/src/codeql-suites/python-lgtm-full.qls index 232e63e77aa..f13d4607b66 100644 --- a/python/ql/src/codeql-suites/python-lgtm-full.qls +++ b/python/ql/src/codeql-suites/python-lgtm-full.qls @@ -8,10 +8,6 @@ - ide-contextual-queries/local-definitions - ide-contextual-queries/local-references - query: Lexical/FCommentedOutCode.ql -- query: Metrics/Dependencies/ExternalDependencies.ql -- query: Metrics/Dependencies/ExternalDependenciesSourceLinks.ql - query: Metrics/FLinesOfCode.ql - query: Metrics/FLinesOfComments.ql -- query: Metrics/FLinesOfDuplicatedCode.ql -- query: Metrics/FLinesOfSimilarCode.ql - query: Metrics/FNumberOfTests.ql diff --git a/python/ql/src/external/DuplicateFunction.ql b/python/ql/src/external/DuplicateFunction.ql index 57a566449d3..4583eede278 100644 --- a/python/ql/src/external/DuplicateFunction.ql +++ b/python/ql/src/external/DuplicateFunction.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Duplicate function * @description There is another identical implementation of this function. Extract the code to a common file or superclass to improve sharing. * @kind problem diff --git a/python/ql/src/external/MostlyDuplicateClass.ql b/python/ql/src/external/MostlyDuplicateClass.ql index 9cdcd4502f2..2e530fef4d0 100644 --- a/python/ql/src/external/MostlyDuplicateClass.ql +++ b/python/ql/src/external/MostlyDuplicateClass.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Mostly duplicate class * @description More than 80% of the methods in this class are duplicated in another class. Create a common supertype to improve code sharing. * @kind problem diff --git a/python/ql/src/external/MostlyDuplicateFile.ql b/python/ql/src/external/MostlyDuplicateFile.ql index 78df1a4166e..274d3758b1d 100644 --- a/python/ql/src/external/MostlyDuplicateFile.ql +++ b/python/ql/src/external/MostlyDuplicateFile.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Mostly duplicate module * @description There is another file that shares a lot of the code with this file. Merge the two files to improve maintainability. * @kind problem diff --git a/python/ql/src/external/MostlySimilarFile.ql b/python/ql/src/external/MostlySimilarFile.ql index 97413885962..bad174f8fc5 100644 --- a/python/ql/src/external/MostlySimilarFile.ql +++ b/python/ql/src/external/MostlySimilarFile.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Mostly similar module * @description There is another module that shares a lot of the code with this module. Notice that names of variables and types may have been changed. Merge the two modules to improve maintainability. * @kind problem diff --git a/python/ql/src/external/SimilarFunction.ql b/python/ql/src/external/SimilarFunction.ql index 9e8db82dcd4..509790c89af 100644 --- a/python/ql/src/external/SimilarFunction.ql +++ b/python/ql/src/external/SimilarFunction.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name Similar function * @description There is another function that is very similar this one. Extract the common code to a common function to improve sharing. * @kind problem From daa1bcc06e069a850f76e2363c7a2a0dafa07c74 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Thu, 1 Oct 2020 20:28:14 +0200 Subject: [PATCH 186/411] Also mark 'tech inventory' queries as deprecated --- cpp/ql/src/Metrics/Dependencies/ExternalDependencies.ql | 1 + .../src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql | 1 + csharp/ql/src/Metrics/Dependencies/ExternalDependencies.ql | 1 + .../src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql | 1 + java/ql/src/Metrics/Dependencies/ExternalDependencies.ql | 1 + .../src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql | 1 + javascript/ql/src/Metrics/Dependencies/ExternalDependencies.ql | 1 + .../src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql | 1 + python/ql/src/Metrics/Dependencies/ExternalDependencies.ql | 1 + .../src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql | 1 + 10 files changed, 10 insertions(+) diff --git a/cpp/ql/src/Metrics/Dependencies/ExternalDependencies.ql b/cpp/ql/src/Metrics/Dependencies/ExternalDependencies.ql index 7062911ca4d..47ddb9d1f1e 100644 --- a/cpp/ql/src/Metrics/Dependencies/ExternalDependencies.ql +++ b/cpp/ql/src/Metrics/Dependencies/ExternalDependencies.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name External dependencies * @description Count the number of dependencies a C/C++ source file has on external libraries. * @kind treemap diff --git a/cpp/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql b/cpp/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql index f2c110a0ac1..cf305ab0aea 100644 --- a/cpp/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql +++ b/cpp/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name External dependency source links * @kind source-link * @metricType externalDependency diff --git a/csharp/ql/src/Metrics/Dependencies/ExternalDependencies.ql b/csharp/ql/src/Metrics/Dependencies/ExternalDependencies.ql index 1c2e9aaa721..6139262afd3 100644 --- a/csharp/ql/src/Metrics/Dependencies/ExternalDependencies.ql +++ b/csharp/ql/src/Metrics/Dependencies/ExternalDependencies.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name External dependencies * @description Count the number of dependencies a C# source file has on assembly files. * @kind treemap diff --git a/csharp/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql b/csharp/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql index e9cda425592..59d2dbdf586 100644 --- a/csharp/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql +++ b/csharp/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name External dependency source links * @kind source-link * @metricType externalDependency diff --git a/java/ql/src/Metrics/Dependencies/ExternalDependencies.ql b/java/ql/src/Metrics/Dependencies/ExternalDependencies.ql index b4fc18b8fe2..79fd9db7557 100644 --- a/java/ql/src/Metrics/Dependencies/ExternalDependencies.ql +++ b/java/ql/src/Metrics/Dependencies/ExternalDependencies.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name External dependencies * @description Count the number of dependencies a Java source file has on jar files. * @kind treemap diff --git a/java/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql b/java/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql index f8761c874c2..48379fa6fa7 100644 --- a/java/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql +++ b/java/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name External dependency source links * @kind source-link * @metricType externalDependency diff --git a/javascript/ql/src/Metrics/Dependencies/ExternalDependencies.ql b/javascript/ql/src/Metrics/Dependencies/ExternalDependencies.ql index a63830647f1..d0d2782893a 100644 --- a/javascript/ql/src/Metrics/Dependencies/ExternalDependencies.ql +++ b/javascript/ql/src/Metrics/Dependencies/ExternalDependencies.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name External dependencies * @description Count the number of dependencies a JavaScript source file has on * NPM packages or framework libraries. diff --git a/javascript/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql b/javascript/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql index fa0fe3edd91..c1863de9e53 100644 --- a/javascript/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql +++ b/javascript/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name External dependency source links * @kind source-link * @metricType externalDependency diff --git a/python/ql/src/Metrics/Dependencies/ExternalDependencies.ql b/python/ql/src/Metrics/Dependencies/ExternalDependencies.ql index 6eaf7422b18..5efec24c7b6 100644 --- a/python/ql/src/Metrics/Dependencies/ExternalDependencies.ql +++ b/python/ql/src/Metrics/Dependencies/ExternalDependencies.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name External dependencies * @description Count the number of dependencies that a Python source file has on external packages. * @kind treemap diff --git a/python/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql b/python/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql index c752ec8bc5e..98bb4e63cc3 100644 --- a/python/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql +++ b/python/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql @@ -1,4 +1,5 @@ /** + * @deprecated * @name External dependency source links * @kind source-link * @metricType externalDependency From d4a1acedde307c14631fefcbd00ff733dccd4534 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 Oct 2020 16:23:48 +0100 Subject: [PATCH 187/411] C++: Remove StdSetBeginEnd as we now have a general model BeginOrEndFunction in main. --- .../code/cpp/models/implementations/StdSet.qll | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll index 891c282dda7..a5b9c8dab61 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdSet.qll @@ -49,23 +49,6 @@ class StdSetInsert extends TaintFunction { } } -/** - * The standard set `begin` and `end` functions and their - * variants. - */ -class StdSetBeginEnd extends TaintFunction { - StdSetBeginEnd() { - this.hasQualifiedName("std", ["set", "unordered_set"], ["begin", "end", "cbegin", "cend"]) - or - this.hasQualifiedName("std", "set", ["rbegin", "crbegin", "rend", "crend"]) - } - - override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - input.isQualifierObject() and - output.isReturnValue() - } -} - /** * The standard set `swap` functions. */ From 2dc8fba7fe91cf309e41b8bdcdf5257319d97076 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 Oct 2020 16:39:23 +0100 Subject: [PATCH 188/411] C++: Remove StdMapBeginEnd as we now have a general model BeginOrEndFunction in main. --- .../code/cpp/models/implementations/StdMap.qll | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll index 7f2f3a1f4eb..9996e9e2343 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll @@ -24,23 +24,6 @@ class StdMapInsert extends TaintFunction { } } -/** - * The standard map `begin` and `end` functions and their - * variants. - */ -class StdMapBeginEnd extends TaintFunction { - StdMapBeginEnd() { - this.hasQualifiedName("std", ["map", "unordered_map"], ["begin", "end", "cbegin", "cend"]) - or - this.hasQualifiedName("std", "map", ["rbegin", "crbegin", "rend", "crend"]) - } - - override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - input.isQualifierObject() and - output.isReturnValue() - } -} - /** * The standard map `swap` functions. */ From f1d6f7cd0c128092b0314a491ce585a910e20aa4 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 18 Sep 2020 11:41:19 +0200 Subject: [PATCH 189/411] C#: Model assertions in the CFG --- .../semmle/code/csharp/commons/Assertions.qll | 12 +- .../semmle/code/csharp/controlflow/Guards.qll | 85 +- .../controlflow/internal/Completion.qll | 19 + .../controlflow/internal/PreBasicBlocks.qll | 23 +- .../csharp/controlflow/internal/Splitting.qll | 135 +- .../semmle/code/csharp/dataflow/Nullness.qll | 29 +- .../controlflow/graph/BasicBlock.expected | 140 +- .../controlflow/graph/Condition.expected | 408 ++++- .../controlflow/graph/Dominance.expected | 1421 +++++++++++------ .../graph/EnclosingCallable.expected | 369 +++-- .../controlflow/graph/ExitElement.expected | 170 +- .../controlflow/graph/NodeGraph.expected | 375 +++-- .../controlflow/graph/Nodes.expected | 166 +- .../guards/BooleanGuardedExpr.expected | 8 - .../guards/GuardedControlFlowNode.expected | 40 +- .../controlflow/guards/GuardedExpr.expected | 12 - .../controlflow/guards/Implications.expected | 4 + .../guards/NullGuardedExpr.expected | 2 - .../dataflow/signanalysis/SignAnalysis.cs | 2 +- .../signanalysis/SignAnalysis.expected | 1 + .../FormatInvalid/FormatInvalid.expected | 4 +- .../Nullness/Implications.expected | 8 + .../query-tests/Nullness/NullCheck.expected | 8 + .../query-tests/Nullness/NullMaybe.expected | 15 +- 24 files changed, 2251 insertions(+), 1205 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/commons/Assertions.qll b/csharp/ql/src/semmle/code/csharp/commons/Assertions.qll index 94752606137..bf29195547f 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/Assertions.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/Assertions.qll @@ -62,7 +62,7 @@ class Assertion extends MethodCall { * does not work. */ pragma[nomagic] - private predicate immediatelyDominatesBlockSplit(BasicBlock succ) { + deprecated private predicate immediatelyDominatesBlockSplit(BasicBlock succ) { // Only calculate dominance by explicit recursion for split nodes; // all other nodes can use regular CFG dominance this instanceof ControlFlow::Internal::SplitControlFlowElement and @@ -78,11 +78,11 @@ class Assertion extends MethodCall { } pragma[noinline] - private predicate strictlyDominatesJoinBlockPredecessor(JoinBlock jb, int i) { + deprecated private predicate strictlyDominatesJoinBlockPredecessor(JoinBlock jb, int i) { this.strictlyDominatesSplit(jb.getJoinBlockPredecessor(i)) } - private predicate strictlyDominatesJoinBlockSplit(JoinBlock jb, int i) { + deprecated private predicate strictlyDominatesJoinBlockSplit(JoinBlock jb, int i) { i = -1 and this.strictlyDominatesJoinBlockPredecessor(jb, _) or @@ -95,7 +95,7 @@ class Assertion extends MethodCall { } pragma[nomagic] - private predicate strictlyDominatesSplit(BasicBlock bb) { + deprecated private predicate strictlyDominatesSplit(BasicBlock bb) { this.immediatelyDominatesBlockSplit(bb) or // Equivalent with @@ -121,6 +121,8 @@ class Assertion extends MethodCall { } /** + * DEPRECATED: Use `getExpr().controlsBlock()` instead. + * * Holds if this assertion strictly dominates basic block `bb`. That is, `bb` * can only be reached from the callable entry point by going via *some* basic * block containing this element. @@ -130,7 +132,7 @@ class Assertion extends MethodCall { * in that it takes control flow splitting into account. */ pragma[nomagic] - predicate strictlyDominates(BasicBlock bb) { + deprecated predicate strictlyDominates(BasicBlock bb) { this.strictlyDominatesSplit(bb) or this.getAControlFlowNode().getBasicBlock().strictlyDominates(bb) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll b/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll index 65a3bfe7213..8097c4b6671 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll @@ -612,14 +612,11 @@ private Ssa::Definition getAnSsaQualifier(Expr e, ControlFlow::Node cfn) { } private AssignableAccess getATrackedAccess(Ssa::Definition def, ControlFlow::Node cfn) { - ( - result = def.getAReadAtNode(cfn) - or - result = def.(Ssa::ExplicitDefinition).getADefinition().getTargetAccess() and - result.getAControlFlowNode() = cfn and - cfn.getBasicBlock() = def.getBasicBlock() - ) and + result = def.getAReadAtNode(cfn) and not def instanceof Ssa::ImplicitUntrackedDefinition + or + result = def.(Ssa::ExplicitDefinition).getADefinition().getTargetAccess() and + cfn = def.getControlFlowNode() } /** @@ -962,41 +959,6 @@ module Internal { e = any(BinaryArithmeticOperation bao | result = bao.getAnOperand()) } - pragma[noinline] - private predicate assertionControlsNodeInSameBasicBlock0( - Guard g, AbstractValue v, BasicBlock bb, int i - ) { - exists(Assertion a, Guard g0, AbstractValue v0 | - asserts(a, g0, v0) and - impliesSteps(g0, v0, g, v) and - bb.getNode(i) = a.getAControlFlowNode() - ) - } - - /** - * Holds if control flow node `cfn` only is reached when guard `g` evaluates to `v`, - * because of an assertion. - */ - private predicate assertionControlsNodeInSameBasicBlock( - Guard g, ControlFlow::Node cfn, AbstractValue v - ) { - exists(BasicBlock bb, int i, int j | - assertionControlsNodeInSameBasicBlock0(g, v, bb, i) and - bb.getNode(j) = cfn and - j > i - ) - } - - /** - * Holds if control flow element `cfe` only is reached when guard `g` evaluates to `v`, - * because of an assertion. - */ - private predicate guardAssertionControlsElement(Guard g, ControlFlowElement cfe, AbstractValue v) { - forex(ControlFlow::Node cfn | cfn = cfe.getAControlFlowNode() | - assertionControlsNodeInSameBasicBlock(g, cfn, v) - ) - } - /** Same as `this.getAChildExpr*()`, but avoids `fastTC`. */ private Expr getAChildExprStar(Guard g) { result = g @@ -1004,26 +966,6 @@ module Internal { result = getAChildExprStar(g).getAChildExpr() } - /** - * Holds if assertion `a` directly asserts that expression `e` evaluates to value `v`. - */ - predicate asserts(Assertion a, Expr e, AbstractValue v) { - e = a.getExpr() and - ( - a.getAssertMethod() instanceof AssertTrueMethod and - v.(BooleanValue).getValue() = true - or - a.getAssertMethod() instanceof AssertFalseMethod and - v.(BooleanValue).getValue() = false - or - a.getAssertMethod() instanceof AssertNullMethod and - v.(NullValue).isNull() - or - a.getAssertMethod() instanceof AssertNonNullMethod and - v.(NullValue).isNonNull() - ) - } - private Expr stripConditionalExpr(Expr e) { e = any(ConditionalExpr ce | @@ -1453,8 +1395,6 @@ module Internal { or val.branch(_, _, e) or - asserts(_, e, val) - or e instanceof CollectionExpr and val = TEmptyCollectionValue(_) ) and @@ -1767,11 +1707,7 @@ module Internal { pragma[noinline] private predicate candidateAux(AccessOrCallExpr e, Declaration target, BasicBlock bb) { target = e.getTarget() and - exists(Guard g | e = getAChildExprStar(g) | - guardControls(g, bb, _) - or - assertionControlsNodeInSameBasicBlock(g, bb.getANode(), _) - ) + exists(Guard g | e = getAChildExprStar(g) | guardControls(g, bb, _)) } } @@ -1786,11 +1722,6 @@ module Internal { exists(ControlFlowElement cfe, ConditionalSuccessor s | v0.branch(cfe, s, g0) and cfe.controlsBlock(bb, s) ) - or - exists(Assertion a | - asserts(a, g0, v0) and - a.strictlyDominates(bb) - ) ) } @@ -1812,9 +1743,6 @@ module Internal { forex(ControlFlow::Node cfn | cfn = guarded.getAControlFlowNode() | isGuardedByNode0(cfn, guarded, g, sub, v) ) - or - guardAssertionControlsElement(g, guarded, v) and - exists(ConditionOnExprComparisonConfig c | c.same(sub, guarded)) } private predicate adjacentReadPairSameVarUniquePredecessor( @@ -1848,9 +1776,6 @@ module Internal { ControlFlow::Nodes::ElementNode guarded, Guard g, AccessOrCallExpr sub, AbstractValue v ) { isGuardedByNode0(guarded, _, g, sub, v) - or - assertionControlsNodeInSameBasicBlock(g, guarded, v) and - exists(ConditionOnExprComparisonConfig c | c.same(sub, guarded.getElement())) } pragma[noinline] diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll index b497a819f1b..a1c77b78eed 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll @@ -20,6 +20,7 @@ */ import csharp +private import semmle.code.csharp.commons.Assertions private import semmle.code.csharp.commons.Constants private import semmle.code.csharp.frameworks.System private import NonReturning @@ -98,6 +99,13 @@ class Completion extends TCompletion { cfe instanceof ThrowElement and this = TThrowCompletion(cfe.(ThrowElement).getThrownExceptionType()) or + exists(AssertMethod m | assertion(cfe, m, _) | + this = TThrowCompletion(m.getExceptionClass()) + or + not exists(m.getExceptionClass()) and + this = TExitCompletion() + ) + or completionIsValidForStmt(cfe, this) or mustHaveBooleanCompletion(cfe) and @@ -382,6 +390,11 @@ private predicate invalidCastCandidate(CastExpr ce) { ce.getType() = ce.getExpr().getType().(ValueOrRefType).getASubType+() } +private predicate assertion(Assertion a, AssertMethod am, Expr e) { + e = a.getExpr() and + am = a.getAssertMethod() +} + /** * Holds if a normal completion of `e` must be a Boolean completion. */ @@ -409,6 +422,9 @@ private predicate inBooleanContext(Expr e, boolean isBooleanCompletionForParent) or exists(SpecificCatchClause scc | scc.getFilterClause() = e | isBooleanCompletionForParent = false) or + assertion(_, [any(AssertTrueMethod m).(AssertMethod), any(AssertFalseMethod m)], e) and + isBooleanCompletionForParent = false + or exists(LogicalNotExpr lne | lne.getAnOperand() = e | inBooleanContext(lne, _) and isBooleanCompletionForParent = true @@ -479,6 +495,9 @@ private predicate inNullnessContext(Expr e, boolean isNullnessCompletionForParen isNullnessCompletionForParent = false ) or + assertion(_, [any(AssertNullMethod m).(AssertMethod), any(AssertNonNullMethod m)], e) and + isNullnessCompletionForParent = false + or exists(ConditionalExpr ce | inNullnessContext(ce, _) | (e = ce.getThen() or e = ce.getElse()) and isNullnessCompletionForParent = true diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll index b2c9398a9b1..f71ea9dba36 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll @@ -89,10 +89,14 @@ class PreBasicBlock extends ControlFlowElement { private predicate dominatesPredecessor(PreBasicBlock df) { this.dominates(df.getAPredecessor()) } } +private Completion getConditionalCompletion(ConditionalCompletion cc) { + result.getInnerCompletion() = cc +} + class ConditionBlock extends PreBasicBlock { ConditionBlock() { strictcount(Completion c | - c.getInnerCompletion() instanceof ConditionalCompletion and + c = getConditionalCompletion(_) and ( exists(succ(this.getLastElement(), c)) or @@ -102,9 +106,20 @@ class ConditionBlock extends PreBasicBlock { } private predicate immediatelyControls(PreBasicBlock succ, ConditionalCompletion cc) { - succ = succ(this.getLastElement(), any(Completion c | c.getInnerCompletion() = cc)) and - forall(PreBasicBlock pred | pred = succ.getAPredecessor() and pred != this | - succ.dominates(pred) + exists(ControlFlowElement last, Completion c | + last = this.getLastElement() and + c = getConditionalCompletion(cc) and + succ = succ(last, c) and + // In the pre-CFG, we need to account for case where one predecessor node has + // two edges to the same successor node. Assertion expressions are examples of + // such nodes. + not exists(Completion other | + succ = succ(last, other) and + other != c + ) and + forall(PreBasicBlock pred | pred = succ.getAPredecessor() and pred != this | + succ.dominates(pred) + ) ) } diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll index 44d5f03c3be..1fedd716806 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll @@ -27,6 +27,7 @@ private module Cached { cached newtype TSplitKind = TInitializerSplitKind() or + TAssertionSplitKind() or TFinallySplitKind(int nestLevel) { nestLevel = FinallySplitting::nestLevel(_) } or TExceptionHandlerSplitKind() or TBooleanSplitKind(BooleanSplitting::BooleanSplitSubKind kind) { kind.startsSplit(_) } or @@ -35,6 +36,7 @@ private module Cached { cached newtype TSplit = TInitializerSplit(Constructor c) { InitializerSplitting::constructorInitializes(c, _) } or + TAssertionSplit(AssertionSplitting::Assertion a, boolean success) { success = [true, false] } or TFinallySplit(FinallySplitting::FinallySplitType type, int nestLevel) { nestLevel = FinallySplitting::nestLevel(_) } or @@ -385,6 +387,135 @@ module InitializerSplitting { } } +module AssertionSplitting { + import semmle.code.csharp.commons.Assertions + private import semmle.code.csharp.ExprOrStmtParent + + private ControlFlowElement getAnAssertionDescendant(Assertion a) { + result = a + or + result = getAnAssertionDescendant(a).getAChild() + } + + /** + * A split for assertions. For example, in + * + * ```csharp + * void M(int i) + * { + * Debug.Assert(i >= 0); + * System.Console.WriteLine("i is positive") + * } + * ``` + * + * we record whether `i >= 0` evaluates to `true` or `false`, and restrict the + * edges out out of the assertion accordingly. + */ + class AssertionSplitImpl extends SplitImpl, TAssertionSplit { + Assertion a; + boolean success; + + AssertionSplitImpl() { this = TAssertionSplit(a, success) } + + /** Gets the assertion. */ + Assertion getAssertion() { result = a } + + /** Holds if this split represents a successful assertion. */ + predicate isSuccess() { success = true } + + override string toString() { + success = true and result = "assertion success" + or + success = false and result = "assertion failure" + } + } + + private class AssertionSplitKind extends SplitKind, TAssertionSplitKind { + override int getListOrder() { result = InitializerSplitting::getNextListOrder() } + + override predicate isEnabled(ControlFlowElement cfe) { this.appliesTo(cfe) } + + override string toString() { result = "Assertion" } + } + + int getNextListOrder() { result = InitializerSplitting::getNextListOrder() + 1 } + + private class AssertionSplitInternal extends SplitInternal, AssertionSplitImpl { + override AssertionSplitKind getKind() { any() } + + override predicate hasEntry(ControlFlowElement pred, ControlFlowElement succ, Completion c) { + exists(AssertMethod m | + pred = last(a.getExpr(), c) and + succ = succ(pred, c) and + this.getAssertion() = a and + m = a.getAssertMethod() + | + m instanceof AssertTrueMethod and + ( + c instanceof TrueCompletion and success = true + or + c instanceof FalseCompletion and success = false + ) + or + m instanceof AssertFalseMethod and + ( + c instanceof TrueCompletion and success = false + or + c instanceof FalseCompletion and success = true + ) + or + m instanceof AssertNullMethod and + ( + c.(NullnessCompletion).isNull() and success = true + or + c.(NullnessCompletion).isNonNull() and success = false + ) + or + m instanceof AssertNonNullMethod and + ( + c.(NullnessCompletion).isNull() and success = false + or + c.(NullnessCompletion).isNonNull() and success = true + ) + ) + } + + override predicate hasEntry(Callable c, ControlFlowElement succ) { none() } + + override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) { + this.appliesTo(pred) and + pred = a and + succ = succ(pred, c) and + ( + success = true and + c instanceof NormalCompletion + or + success = false and + not c instanceof NormalCompletion + ) + } + + override Callable hasExit(ControlFlowElement pred, Completion c) { + this.appliesTo(pred) and + pred = a and + result = succExit(pred, c) and + ( + success = true and + c instanceof NormalCompletion + or + success = false and + not c instanceof NormalCompletion + ) + } + + override predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c) { + this.appliesTo(pred) and + succ = succ(pred, c) and + succ = getAnAssertionDescendant(a) + } + } +} + pragma[noinline] private ControlFlowElement getAChild(ControlFlowElement cfe, Callable c) { result = cfe.getAChild() and @@ -509,11 +640,11 @@ module FinallySplitting { } private int getListOrder(FinallySplitKind kind) { - result = InitializerSplitting::getNextListOrder() + kind.getNestLevel() + result = AssertionSplitting::getNextListOrder() + kind.getNestLevel() } int getNextListOrder() { - result = max(int i | i = getListOrder(_) + 1 or i = InitializerSplitting::getNextListOrder()) + result = max(int i | i = getListOrder(_) + 1 or i = AssertionSplitting::getNextListOrder()) } private class FinallySplitKind extends SplitKind, TFinallySplitKind { diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll b/csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll index ed10e700966..f76b3414a86 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll @@ -136,30 +136,6 @@ private predicate exprImpliesSsaDef( ) } -/** - * Holds if the `i`th node of basic block `bb` ensures that SSA definition - * `def` is not `null` in any subsequent uses. - */ -private predicate ensureNotNullAt(BasicBlock bb, int i, Ssa::Definition def) { - exists(Expr e, G::AbstractValue v, NullValue nv | - G::Internal::asserts(bb.getNode(i).getElement(), e, v) - | - exprImpliesSsaDef(e, v, def, nv) and - nv.isNonNull() - ) -} - -/** - * Holds if the `i`th node of basic block `bb` is a dereference `d` of SSA - * definition `def`, and `def` may potentially be `null`. - */ -private predicate potentialNullDereferenceAt( - BasicBlock bb, int i, Ssa::Definition def, Dereference d -) { - dereferenceAt(bb, i, def, d) and - not exists(int j | ensureNotNullAt(bb, j, def) | j < i) -} - /** * Gets an element that tests whether a given SSA definition, `def`, is * `null` or not. @@ -269,7 +245,6 @@ private predicate defNullImpliesStep( bb2 = def.getBasicBlock() ) ) and - not ensureNotNullAt(bb1, _, def1) and not exists(SuccessorTypes::ConditionalSuccessor s, NullValue nv | bb1.getLastNode() = getANullCheck(def1, s, nv).getAControlFlowNode() | @@ -296,7 +271,7 @@ private predicate defMaybeNullInBlock(Ssa::Definition def, BasicBlock bb) { * dereference. */ private predicate nullDerefCandidateVariable(Ssa::SourceVariable v) { - exists(Ssa::Definition def, BasicBlock bb | potentialNullDereferenceAt(bb, _, def, _) | + exists(Ssa::Definition def, BasicBlock bb | dereferenceAt(bb, _, def, _) | defMaybeNullInBlock(def, bb) and v = def.getSourceVariable() ) @@ -328,7 +303,7 @@ private newtype TPathNode = succNullArgument(_, def, bb) } or TSinkPathNode(Ssa::Definition def, BasicBlock bb, int i, Dereference d) { - potentialNullDereferenceAt(bb, i, def, d) and + dereferenceAt(bb, i, def, d) and ( succStep(_, def, bb) or diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index d5921114b9b..9faf0d672f0 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -16,75 +16,124 @@ | ArrayCreation.cs:7:11:7:12 | enter M3 | ArrayCreation.cs:7:11:7:12 | exit M3 | 6 | | ArrayCreation.cs:9:12:9:13 | enter M4 | ArrayCreation.cs:9:12:9:13 | exit M4 | 10 | | Assert.cs:7:10:7:11 | enter M1 | Assert.cs:9:20:9:20 | access to parameter b | 5 | -| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:7:10:7:11 | exit M1 | 11 | +| Assert.cs:7:10:7:11 | exit M1 | Assert.cs:7:10:7:11 | exit M1 | 1 | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:10:22:10:30 | ... != ... | 5 | | Assert.cs:9:24:9:27 | null | Assert.cs:9:24:9:27 | null | 1 | | Assert.cs:9:31:9:32 | "" | Assert.cs:9:31:9:32 | "" | 1 | +| Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | 1 | +| Assert.cs:10:9:10:31 | [assertion success] call to method Assert | Assert.cs:11:9:11:35 | call to method WriteLine | 5 | | Assert.cs:14:10:14:11 | enter M2 | Assert.cs:16:20:16:20 | access to parameter b | 5 | -| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:14:10:14:11 | exit M2 | 9 | +| Assert.cs:14:10:14:11 | exit M2 | Assert.cs:14:10:14:11 | exit M2 | 1 | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:17:23:17:23 | access to local variable s | 3 | | Assert.cs:16:24:16:27 | null | Assert.cs:16:24:16:27 | null | 1 | | Assert.cs:16:31:16:32 | "" | Assert.cs:16:31:16:32 | "" | 1 | +| Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | 1 | +| Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | Assert.cs:18:9:18:35 | call to method WriteLine | 5 | | Assert.cs:21:10:21:11 | enter M3 | Assert.cs:23:20:23:20 | access to parameter b | 5 | -| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:21:10:21:11 | exit M3 | 9 | +| Assert.cs:21:10:21:11 | exit M3 | Assert.cs:21:10:21:11 | exit M3 | 1 | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:24:26:24:26 | access to local variable s | 3 | | Assert.cs:23:24:23:27 | null | Assert.cs:23:24:23:27 | null | 1 | | Assert.cs:23:31:23:32 | "" | Assert.cs:23:31:23:32 | "" | 1 | +| Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | 1 | +| Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | Assert.cs:25:9:25:35 | call to method WriteLine | 5 | | Assert.cs:28:10:28:11 | enter M4 | Assert.cs:30:20:30:20 | access to parameter b | 5 | -| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:28:10:28:11 | exit M4 | 11 | +| Assert.cs:28:10:28:11 | exit M4 | Assert.cs:28:10:28:11 | exit M4 | 1 | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:31:23:31:31 | ... == ... | 5 | | Assert.cs:30:24:30:27 | null | Assert.cs:30:24:30:27 | null | 1 | | Assert.cs:30:31:30:32 | "" | Assert.cs:30:31:30:32 | "" | 1 | +| Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | 1 | +| Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | Assert.cs:32:9:32:35 | call to method WriteLine | 5 | | Assert.cs:35:10:35:11 | enter M5 | Assert.cs:37:20:37:20 | access to parameter b | 5 | -| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:35:10:35:11 | exit M5 | 11 | +| Assert.cs:35:10:35:11 | exit M5 | Assert.cs:35:10:35:11 | exit M5 | 1 | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:38:23:38:31 | ... != ... | 5 | | Assert.cs:37:24:37:27 | null | Assert.cs:37:24:37:27 | null | 1 | | Assert.cs:37:31:37:32 | "" | Assert.cs:37:31:37:32 | "" | 1 | +| Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | 1 | +| Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | Assert.cs:39:9:39:35 | call to method WriteLine | 5 | | Assert.cs:42:10:42:11 | enter M6 | Assert.cs:44:20:44:20 | access to parameter b | 5 | -| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:42:10:42:11 | exit M6 | 11 | +| Assert.cs:42:10:42:11 | exit M6 | Assert.cs:42:10:42:11 | exit M6 | 1 | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:45:24:45:32 | ... != ... | 5 | | Assert.cs:44:24:44:27 | null | Assert.cs:44:24:44:27 | null | 1 | | Assert.cs:44:31:44:32 | "" | Assert.cs:44:31:44:32 | "" | 1 | +| Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | 1 | +| Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | Assert.cs:46:9:46:35 | call to method WriteLine | 5 | | Assert.cs:49:10:49:11 | enter M7 | Assert.cs:51:20:51:20 | access to parameter b | 5 | -| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:49:10:49:11 | exit M7 | 11 | +| Assert.cs:49:10:49:11 | exit M7 | Assert.cs:49:10:49:11 | exit M7 | 1 | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:52:24:52:32 | ... == ... | 5 | | Assert.cs:51:24:51:27 | null | Assert.cs:51:24:51:27 | null | 1 | | Assert.cs:51:31:51:32 | "" | Assert.cs:51:31:51:32 | "" | 1 | +| Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | 1 | +| Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | Assert.cs:53:9:53:35 | call to method WriteLine | 5 | | Assert.cs:56:10:56:11 | enter M8 | Assert.cs:58:20:58:20 | access to parameter b | 5 | -| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:59:23:59:31 | ... != ... | 6 | -| Assert.cs:58:24:58:27 | null | Assert.cs:58:24:58:27 | null | 1 | -| Assert.cs:58:31:58:32 | "" | Assert.cs:58:31:58:32 | "" | 1 | -| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:56:10:56:11 | exit M8 | 6 | -| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:59:36:59:36 | access to parameter b | 1 | +| Assert.cs:56:10:56:11 | exit M8 | Assert.cs:56:10:56:11 | exit M8 | 1 | +| Assert.cs:58:24:58:27 | [b (line 56): true] null | Assert.cs:59:23:59:31 | [b (line 56): true] ... != ... | 7 | +| Assert.cs:58:31:58:32 | [b (line 56): false] "" | Assert.cs:59:23:59:31 | [b (line 56): false] ... != ... | 7 | +| Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | 1 | +| Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | 1 | +| Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | Assert.cs:60:9:60:35 | call to method WriteLine | 6 | | Assert.cs:63:10:63:11 | enter M9 | Assert.cs:65:20:65:20 | access to parameter b | 5 | -| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:66:24:66:32 | ... == ... | 6 | -| Assert.cs:65:24:65:27 | null | Assert.cs:65:24:65:27 | null | 1 | -| Assert.cs:65:31:65:32 | "" | Assert.cs:65:31:65:32 | "" | 1 | -| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:63:10:63:11 | exit M9 | 6 | -| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:66:37:66:37 | access to parameter b | 1 | +| Assert.cs:63:10:63:11 | exit M9 | Assert.cs:63:10:63:11 | exit M9 | 1 | +| Assert.cs:65:24:65:27 | [b (line 63): true] null | Assert.cs:66:24:66:32 | [b (line 63): true] ... == ... | 7 | +| Assert.cs:65:31:65:32 | [b (line 63): false] "" | Assert.cs:66:24:66:32 | [b (line 63): false] ... == ... | 7 | +| Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | 1 | +| Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | Assert.cs:67:9:67:35 | call to method WriteLine | 6 | +| Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | 1 | | Assert.cs:70:10:70:12 | enter M10 | Assert.cs:72:20:72:20 | access to parameter b | 5 | -| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:73:23:73:31 | ... == ... | 6 | -| Assert.cs:72:24:72:27 | null | Assert.cs:72:24:72:27 | null | 1 | -| Assert.cs:72:31:72:32 | "" | Assert.cs:72:31:72:32 | "" | 1 | -| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:70:10:70:12 | exit M10 | 6 | -| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:73:36:73:36 | access to parameter b | 1 | +| Assert.cs:70:10:70:12 | exit M10 | Assert.cs:70:10:70:12 | exit M10 | 1 | +| Assert.cs:72:24:72:27 | [b (line 70): true] null | Assert.cs:73:23:73:31 | [b (line 70): true] ... == ... | 7 | +| Assert.cs:72:31:72:32 | [b (line 70): false] "" | Assert.cs:73:23:73:31 | [b (line 70): false] ... == ... | 7 | +| Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | 1 | +| Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | 1 | +| Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | Assert.cs:74:9:74:35 | call to method WriteLine | 6 | | Assert.cs:77:10:77:12 | enter M11 | Assert.cs:79:20:79:20 | access to parameter b | 5 | -| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:80:24:80:32 | ... != ... | 6 | -| Assert.cs:79:24:79:27 | null | Assert.cs:79:24:79:27 | null | 1 | -| Assert.cs:79:31:79:32 | "" | Assert.cs:79:31:79:32 | "" | 1 | -| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:77:10:77:12 | exit M11 | 6 | -| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:80:37:80:37 | access to parameter b | 1 | +| Assert.cs:77:10:77:12 | exit M11 | Assert.cs:77:10:77:12 | exit M11 | 1 | +| Assert.cs:79:24:79:27 | [b (line 77): true] null | Assert.cs:80:24:80:32 | [b (line 77): true] ... != ... | 7 | +| Assert.cs:79:31:79:32 | [b (line 77): false] "" | Assert.cs:80:24:80:32 | [b (line 77): false] ... != ... | 7 | +| Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | 1 | +| Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | Assert.cs:81:9:81:35 | call to method WriteLine | 6 | +| Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | 1 | | Assert.cs:84:10:84:12 | enter M12 | Assert.cs:86:20:86:20 | access to parameter b | 5 | -| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | 101 | -| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | 101 | -| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | 15 | -| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | 15 | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:84:10:84:12 | exit M12 | 1 | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | 6 | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | 6 | +| Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | 1 | +| Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | 1 | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | 12 | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | 12 | +| Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | 1 | +| Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | 1 | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | 12 | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | 12 | +| Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | 1 | +| Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | 1 | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | 14 | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | 14 | +| Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | 1 | +| Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | 1 | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | 14 | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | 14 | +| Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | 1 | +| Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | 1 | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | 14 | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | 14 | +| Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | 1 | +| Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | 1 | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | 14 | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | 14 | +| Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | 1 | +| Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | 1 | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | 15 | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | 15 | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | 1 | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | 1 | | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | 1 | -| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | 1 | -| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | 15 | -| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | 15 | -| Assert.cs:119:37:119:38 | [b (line 84): false] !... | Assert.cs:119:38:119:38 | [b (line 84): false] access to parameter b | 2 | -| Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | 2 | -| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:126:24:126:25 | "" | 9 | -| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:126:17:126:20 | null | 9 | -| Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | 1 | -| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | 1 | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:127:24:127:32 | ... != ... | 6 | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:84:10:84:12 | exit M12 | 6 | -| Assert.cs:127:37:127:38 | !... | Assert.cs:127:38:127:38 | access to parameter b | 2 | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | 16 | +| Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | 1 | +| Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | 17 | +| Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | 1 | +| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:127:24:127:32 | [b (line 84): true] ... != ... | 16 | +| Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | 1 | +| Assert.cs:127:37:127:38 | [b (line 84): true] !... | Assert.cs:128:9:128:35 | call to method WriteLine | 7 | | Assignments.cs:3:10:3:10 | enter M | Assignments.cs:3:10:3:10 | exit M | 33 | | Assignments.cs:14:18:14:35 | enter (...) => ... | Assignments.cs:14:18:14:35 | exit (...) => ... | 3 | | Assignments.cs:17:40:17:40 | enter + | Assignments.cs:17:40:17:40 | exit + | 5 | @@ -274,7 +323,10 @@ | ExitMethods.cs:116:38:116:38 | 1 | ExitMethods.cs:116:38:116:38 | 1 | 1 | | ExitMethods.cs:119:17:119:32 | enter FailingAssertion | ExitMethods.cs:119:17:119:32 | exit FailingAssertion | 6 | | ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | ExitMethods.cs:125:17:125:33 | exit FailingAssertion2 | 6 | -| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse | 4 | +| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:48:131:48 | access to parameter b | 2 | +| ExitMethods.cs:131:10:131:20 | exit AssertFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse | 1 | +| ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | 1 | +| ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | 1 | | ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 | 7 | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:5:23:5:29 | exit ToInt32 | 6 | | Extensions.cs:10:24:10:29 | enter ToBool | Extensions.cs:10:24:10:29 | exit ToBool | 7 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected index ba6816e4233..0357a7ab06e 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected @@ -1,51 +1,299 @@ conditionBlock | Assert.cs:7:10:7:11 | enter M1 | Assert.cs:9:24:9:27 | null | true | | Assert.cs:7:10:7:11 | enter M1 | Assert.cs:9:31:9:32 | "" | false | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | false | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:10:9:10:31 | [assertion success] call to method Assert | true | | Assert.cs:14:10:14:11 | enter M2 | Assert.cs:16:24:16:27 | null | true | | Assert.cs:14:10:14:11 | enter M2 | Assert.cs:16:31:16:32 | "" | false | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | false | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | true | | Assert.cs:21:10:21:11 | enter M3 | Assert.cs:23:24:23:27 | null | true | | Assert.cs:21:10:21:11 | enter M3 | Assert.cs:23:31:23:32 | "" | false | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | true | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | false | | Assert.cs:28:10:28:11 | enter M4 | Assert.cs:30:24:30:27 | null | true | | Assert.cs:28:10:28:11 | enter M4 | Assert.cs:30:31:30:32 | "" | false | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | false | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | true | | Assert.cs:35:10:35:11 | enter M5 | Assert.cs:37:24:37:27 | null | true | | Assert.cs:35:10:35:11 | enter M5 | Assert.cs:37:31:37:32 | "" | false | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | false | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | true | | Assert.cs:42:10:42:11 | enter M6 | Assert.cs:44:24:44:27 | null | true | | Assert.cs:42:10:42:11 | enter M6 | Assert.cs:44:31:44:32 | "" | false | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | true | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | false | | Assert.cs:49:10:49:11 | enter M7 | Assert.cs:51:24:51:27 | null | true | | Assert.cs:49:10:49:11 | enter M7 | Assert.cs:51:31:51:32 | "" | false | -| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:58:24:58:27 | null | true | -| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:58:31:58:32 | "" | false | -| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:59:36:59:36 | access to parameter b | true | -| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:65:24:65:27 | null | true | -| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:65:31:65:32 | "" | false | -| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:66:37:66:37 | access to parameter b | false | -| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:72:24:72:27 | null | true | -| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:72:31:72:32 | "" | false | -| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:73:36:73:36 | access to parameter b | true | -| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:79:24:79:27 | null | true | -| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:79:31:79:32 | "" | false | -| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:80:37:80:37 | access to parameter b | false | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | true | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | false | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:58:24:58:27 | [b (line 56): true] null | true | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:58:31:58:32 | [b (line 56): false] "" | false | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | false | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | true | +| Assert.cs:58:24:58:27 | [b (line 56): true] null | Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | true | +| Assert.cs:58:31:58:32 | [b (line 56): false] "" | Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | true | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:65:24:65:27 | [b (line 63): true] null | true | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:65:31:65:32 | [b (line 63): false] "" | false | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | false | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | true | +| Assert.cs:65:24:65:27 | [b (line 63): true] null | Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | false | +| Assert.cs:65:31:65:32 | [b (line 63): false] "" | Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | false | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:72:24:72:27 | [b (line 70): true] null | true | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:72:31:72:32 | [b (line 70): false] "" | false | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | false | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | true | +| Assert.cs:72:24:72:27 | [b (line 70): true] null | Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | true | +| Assert.cs:72:31:72:32 | [b (line 70): false] "" | Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | true | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:79:24:79:27 | [b (line 77): true] null | true | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:79:31:79:32 | [b (line 77): false] "" | false | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | false | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | true | +| Assert.cs:79:24:79:27 | [b (line 77): true] null | Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | false | +| Assert.cs:79:31:79:32 | [b (line 77): false] "" | Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | false | | Assert.cs:84:10:84:12 | enter M12 | Assert.cs:86:24:86:27 | [b (line 84): true] null | true | | Assert.cs:84:10:84:12 | enter M12 | Assert.cs:86:31:86:32 | [b (line 84): false] "" | false | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | false | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | true | | Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | false | | Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | true | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | false | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | true | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:37:119:38 | [b (line 84): false] !... | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | true | | Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:37:119:38 | [b (line 84): true] !... | true | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | false | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | true | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | false | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | true | | Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | true | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:127:37:127:38 | [b (line 84): true] !... | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | false | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | true | | Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:119:37:119:38 | [b (line 84): true] !... | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | true | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:127:37:127:38 | [b (line 84): true] !... | true | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | false | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | true | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | true | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | true | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | true | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | true | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | true | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | true | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | true | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | true | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | true | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | true | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | true | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | true | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | true | | Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | true | -| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:119:37:119:38 | [b (line 84): false] !... | false | -| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:119:37:119:38 | [b (line 84): true] !... | false | -| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | true | -| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | true | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:127:37:127:38 | !... | false | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | false | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | false | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:119:37:119:38 | [b (line 84): true] !... | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:127:37:127:38 | [b (line 84): true] !... | true | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | true | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | true | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:119:37:119:38 | [b (line 84): true] !... | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:127:37:127:38 | [b (line 84): true] !... | false | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | false | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | false | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:119:37:119:38 | [b (line 84): true] !... | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:127:37:127:38 | [b (line 84): true] !... | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | false | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | false | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:119:37:119:38 | [b (line 84): true] !... | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:127:37:127:38 | [b (line 84): true] !... | true | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | true | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | false | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | false | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | false | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | false | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | false | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | false | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | false | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | false | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | false | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | false | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | false | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:119:37:119:38 | [b (line 84): true] !... | false | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | false | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | false | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | false | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:127:37:127:38 | [b (line 84): true] !... | false | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | true | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | false | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | false | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | false | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | false | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | false | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | false | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | false | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:119:37:119:38 | [b (line 84): true] !... | false | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | false | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | false | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | false | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:127:37:127:38 | [b (line 84): true] !... | false | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | true | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | false | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:119:37:119:38 | [b (line 84): true] !... | true | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | true | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | true | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:127:37:127:38 | [b (line 84): true] !... | true | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:119:37:119:38 | [b (line 84): true] !... | false | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | false | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | false | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | false | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:127:37:127:38 | [b (line 84): true] !... | false | +| Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | false | +| Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | true | +| Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | true | +| Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:127:37:127:38 | [b (line 84): true] !... | true | +| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | true | +| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:127:37:127:38 | [b (line 84): true] !... | false | | BreakInTry.cs:7:13:11:13 | foreach (... ... in ...) ... | BreakInTry.cs:7:26:7:28 | String arg | false | | BreakInTry.cs:7:13:11:13 | foreach (... ... in ...) ... | BreakInTry.cs:10:21:10:26 | break; | false | | BreakInTry.cs:7:26:7:28 | String arg | BreakInTry.cs:10:21:10:26 | break; | true | @@ -194,6 +442,8 @@ conditionBlock | ExitMethods.cs:109:13:109:21 | enter ThrowExpr | ExitMethods.cs:111:69:111:75 | "input" | false | | ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | ExitMethods.cs:116:34:116:34 | 0 | true | | ExitMethods.cs:114:16:114:34 | enter ExtensionMethodCall | ExitMethods.cs:116:38:116:38 | 1 | false | +| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | true | +| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | false | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:26:38:26:39 | [exception: Exception] IOException ex | true | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:30:9:40:9 | [exception: Exception] catch (...) {...} | false | | Finally.cs:26:9:29:9 | [exception: Exception] catch (...) {...} | Finally.cs:30:41:30:42 | [exception: Exception] ArgumentException ex | false | @@ -841,70 +1091,114 @@ conditionBlock conditionFlow | Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:9:24:9:27 | null | true | | Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:9:31:9:32 | "" | false | +| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | false | +| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:9:10:31 | [assertion success] call to method Assert | true | | Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:16:24:16:27 | null | true | | Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:16:31:16:32 | "" | false | | Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:23:24:23:27 | null | true | | Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:23:31:23:32 | "" | false | | Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:30:24:30:27 | null | true | | Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:30:31:30:32 | "" | false | +| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | false | +| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | true | | Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:37:24:37:27 | null | true | | Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:37:31:37:32 | "" | false | +| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | false | +| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | true | | Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:44:24:44:27 | null | true | | Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:44:31:44:32 | "" | false | +| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | true | +| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | false | | Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:51:24:51:27 | null | true | | Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:51:31:51:32 | "" | false | -| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:24:58:27 | null | true | -| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:31:58:32 | "" | false | -| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:9:59:37 | call to method IsTrue | false | -| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:36:59:36 | access to parameter b | true | -| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:24:65:27 | null | true | -| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:31:65:32 | "" | false | -| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:9:66:38 | call to method IsFalse | true | -| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:37:66:37 | access to parameter b | false | -| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:24:72:27 | null | true | -| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:31:72:32 | "" | false | -| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:9:73:37 | call to method IsTrue | false | -| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:36:73:36 | access to parameter b | true | -| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:24:79:27 | null | true | -| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:31:79:32 | "" | false | -| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:9:80:38 | call to method IsFalse | true | -| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:37:80:37 | access to parameter b | false | +| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | true | +| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | false | +| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:24:58:27 | [b (line 56): true] null | true | +| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:31:58:32 | [b (line 56): false] "" | false | +| Assert.cs:59:23:59:31 | [b (line 56): false] ... != ... | Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | false | +| Assert.cs:59:23:59:31 | [b (line 56): false] ... != ... | Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | true | +| Assert.cs:59:23:59:31 | [b (line 56): true] ... != ... | Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | false | +| Assert.cs:59:23:59:31 | [b (line 56): true] ... != ... | Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | true | +| Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | false | +| Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | Assert.cs:59:9:59:37 | [assertion success] call to method IsTrue | true | +| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:24:65:27 | [b (line 63): true] null | true | +| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:31:65:32 | [b (line 63): false] "" | false | +| Assert.cs:66:24:66:32 | [b (line 63): false] ... == ... | Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | true | +| Assert.cs:66:24:66:32 | [b (line 63): false] ... == ... | Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | false | +| Assert.cs:66:24:66:32 | [b (line 63): true] ... == ... | Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | true | +| Assert.cs:66:24:66:32 | [b (line 63): true] ... == ... | Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | false | +| Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | Assert.cs:66:9:66:38 | [assertion success] call to method IsFalse | false | +| Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | true | +| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:24:72:27 | [b (line 70): true] null | true | +| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:31:72:32 | [b (line 70): false] "" | false | +| Assert.cs:73:23:73:31 | [b (line 70): false] ... == ... | Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | false | +| Assert.cs:73:23:73:31 | [b (line 70): false] ... == ... | Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | true | +| Assert.cs:73:23:73:31 | [b (line 70): true] ... == ... | Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | false | +| Assert.cs:73:23:73:31 | [b (line 70): true] ... == ... | Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | true | +| Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | false | +| Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | Assert.cs:73:9:73:37 | [assertion success] call to method IsTrue | true | +| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:24:79:27 | [b (line 77): true] null | true | +| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:31:79:32 | [b (line 77): false] "" | false | +| Assert.cs:80:24:80:32 | [b (line 77): false] ... != ... | Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | true | +| Assert.cs:80:24:80:32 | [b (line 77): false] ... != ... | Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | false | +| Assert.cs:80:24:80:32 | [b (line 77): true] ... != ... | Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | true | +| Assert.cs:80:24:80:32 | [b (line 77): true] ... != ... | Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | false | +| Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | Assert.cs:80:9:80:38 | [assertion success] call to method IsFalse | false | +| Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | true | | Assert.cs:86:20:86:20 | access to parameter b | Assert.cs:86:24:86:27 | [b (line 84): true] null | true | | Assert.cs:86:20:86:20 | access to parameter b | Assert.cs:86:31:86:32 | [b (line 84): false] "" | false | +| Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | false | +| Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | true | +| Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | false | +| Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | true | | Assert.cs:90:13:90:13 | [b (line 84): false] access to parameter b | Assert.cs:90:24:90:25 | [b (line 84): false] "" | false | | Assert.cs:90:13:90:13 | [b (line 84): true] access to parameter b | Assert.cs:90:17:90:20 | [b (line 84): true] null | true | | Assert.cs:94:13:94:13 | [b (line 84): false] access to parameter b | Assert.cs:94:24:94:25 | [b (line 84): false] "" | false | | Assert.cs:94:13:94:13 | [b (line 84): true] access to parameter b | Assert.cs:94:17:94:20 | [b (line 84): true] null | true | | Assert.cs:98:13:98:13 | [b (line 84): false] access to parameter b | Assert.cs:98:24:98:25 | [b (line 84): false] "" | false | | Assert.cs:98:13:98:13 | [b (line 84): true] access to parameter b | Assert.cs:98:17:98:20 | [b (line 84): true] null | true | +| Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | false | +| Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | true | +| Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | false | +| Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | true | | Assert.cs:102:13:102:13 | [b (line 84): false] access to parameter b | Assert.cs:102:24:102:25 | [b (line 84): false] "" | false | | Assert.cs:102:13:102:13 | [b (line 84): true] access to parameter b | Assert.cs:102:17:102:20 | [b (line 84): true] null | true | +| Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | false | +| Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | true | +| Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | false | +| Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | true | | Assert.cs:106:13:106:13 | [b (line 84): false] access to parameter b | Assert.cs:106:24:106:25 | [b (line 84): false] "" | false | | Assert.cs:106:13:106:13 | [b (line 84): true] access to parameter b | Assert.cs:106:17:106:20 | [b (line 84): true] null | true | +| Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | true | +| Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | false | +| Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | false | | Assert.cs:110:13:110:13 | [b (line 84): false] access to parameter b | Assert.cs:110:24:110:25 | [b (line 84): false] "" | false | | Assert.cs:110:13:110:13 | [b (line 84): true] access to parameter b | Assert.cs:110:17:110:20 | [b (line 84): true] null | true | +| Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | true | +| Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | false | +| Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | true | +| Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | false | | Assert.cs:114:13:114:13 | [b (line 84): false] access to parameter b | Assert.cs:114:24:114:25 | [b (line 84): false] "" | false | | Assert.cs:114:13:114:13 | [b (line 84): true] access to parameter b | Assert.cs:114:17:114:20 | [b (line 84): true] null | true | -| Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | false | +| Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | false | | Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | true | -| Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | false | +| Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | false | | Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | true | -| Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | Assert.cs:118:24:118:25 | [b (line 84): false] "" | false | +| Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | false | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:115:9:115:37 | [assertion success, b (line 84): true] call to method IsTrue | true | | Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | Assert.cs:118:17:118:20 | [b (line 84): true] null | true | -| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | true | -| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | Assert.cs:119:37:119:38 | [b (line 84): false] !... | false | -| Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | true | +| Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | true | | Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:37:119:38 | [b (line 84): true] !... | false | -| Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | Assert.cs:122:24:122:25 | [b (line 84): false] "" | false | +| Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | Assert.cs:119:9:119:39 | [assertion success, b (line 84): true] call to method IsFalse | true | | Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | Assert.cs:122:17:122:20 | [b (line 84): true] null | true | -| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | false | -| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | true | -| Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | false | +| Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | false | | Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | true | -| Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | Assert.cs:126:24:126:25 | "" | false | -| Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | Assert.cs:126:17:126:20 | null | true | -| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:9:127:39 | call to method IsFalse | true | -| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:37:127:38 | !... | false | +| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:123:9:123:37 | [assertion success, b (line 84): true] call to method IsTrue | true | +| Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | Assert.cs:126:17:126:20 | [b (line 84): true] null | true | +| Assert.cs:127:24:127:32 | [b (line 84): true] ... != ... | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | true | +| Assert.cs:127:24:127:32 | [b (line 84): true] ... != ... | Assert.cs:127:37:127:38 | [b (line 84): true] !... | false | +| Assert.cs:127:38:127:38 | [b (line 84): true] access to parameter b | Assert.cs:127:9:127:39 | [assertion success] call to method IsFalse | true | | BreakInTry.cs:9:21:9:31 | ... == ... | BreakInTry.cs:7:13:11:13 | foreach (... ... in ...) ... | false | | BreakInTry.cs:9:21:9:31 | ... == ... | BreakInTry.cs:10:21:10:26 | break; | true | | BreakInTry.cs:15:17:15:28 | ... == ... | BreakInTry.cs:3:10:3:11 | exit M1 | false | @@ -1025,6 +1319,10 @@ conditionFlow | ExitMethods.cs:111:16:111:25 | ... != ... | ExitMethods.cs:111:69:111:75 | "input" | false | | ExitMethods.cs:116:16:116:30 | call to method Contains | ExitMethods.cs:116:34:116:34 | 0 | true | | ExitMethods.cs:116:16:116:30 | call to method Contains | ExitMethods.cs:116:38:116:38 | 1 | false | +| ExitMethods.cs:121:23:121:27 | false | ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | false | +| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | true | +| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | false | +| ExitMethods.cs:135:21:135:24 | true | ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | true | | Finally.cs:26:48:26:51 | [exception: Exception] true | Finally.cs:27:9:29:9 | {...} | true | | Finally.cs:34:21:34:24 | true | Finally.cs:34:27:34:32 | throw ...; | true | | Finally.cs:61:48:61:51 | [exception: Exception] true | Finally.cs:62:9:64:9 | {...} | true | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index 75d607cd710..7c5d265e40d 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -315,12 +315,12 @@ dominance | Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:9:24:9:27 | null | | Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:9:31:9:32 | "" | | Assert.cs:9:20:9:32 | ... ? ... : ... | Assert.cs:9:20:9:20 | access to parameter b | -| Assert.cs:10:9:10:31 | call to method Assert | Assert.cs:11:9:11:36 | ...; | +| Assert.cs:10:9:10:31 | [assertion success] call to method Assert | Assert.cs:11:9:11:36 | ...; | | Assert.cs:10:9:10:32 | ...; | Assert.cs:10:22:10:22 | access to local variable s | | Assert.cs:10:22:10:22 | access to local variable s | Assert.cs:10:27:10:30 | null | -| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:9:10:31 | call to method Assert | +| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | +| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:9:10:31 | [assertion success] call to method Assert | | Assert.cs:10:27:10:30 | null | Assert.cs:10:22:10:30 | ... != ... | -| Assert.cs:11:9:11:35 | call to method WriteLine | Assert.cs:7:10:7:11 | exit M1 | | Assert.cs:11:9:11:36 | ...; | Assert.cs:11:27:11:27 | access to local variable s | | Assert.cs:11:27:11:27 | access to local variable s | Assert.cs:11:27:11:34 | access to property Length | | Assert.cs:11:27:11:34 | access to property Length | Assert.cs:11:9:11:35 | call to method WriteLine | @@ -331,10 +331,10 @@ dominance | Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:16:24:16:27 | null | | Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:16:31:16:32 | "" | | Assert.cs:16:20:16:32 | ... ? ... : ... | Assert.cs:16:20:16:20 | access to parameter b | -| Assert.cs:17:9:17:24 | call to method IsNull | Assert.cs:18:9:18:36 | ...; | +| Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | Assert.cs:18:9:18:36 | ...; | | Assert.cs:17:9:17:25 | ...; | Assert.cs:17:23:17:23 | access to local variable s | -| Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:17:9:17:24 | call to method IsNull | -| Assert.cs:18:9:18:35 | call to method WriteLine | Assert.cs:14:10:14:11 | exit M2 | +| Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | +| Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | | Assert.cs:18:9:18:36 | ...; | Assert.cs:18:27:18:27 | access to local variable s | | Assert.cs:18:27:18:27 | access to local variable s | Assert.cs:18:27:18:34 | access to property Length | | Assert.cs:18:27:18:34 | access to property Length | Assert.cs:18:9:18:35 | call to method WriteLine | @@ -345,10 +345,10 @@ dominance | Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:23:24:23:27 | null | | Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:23:31:23:32 | "" | | Assert.cs:23:20:23:32 | ... ? ... : ... | Assert.cs:23:20:23:20 | access to parameter b | -| Assert.cs:24:9:24:27 | call to method IsNotNull | Assert.cs:25:9:25:36 | ...; | +| Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | Assert.cs:25:9:25:36 | ...; | | Assert.cs:24:9:24:28 | ...; | Assert.cs:24:26:24:26 | access to local variable s | -| Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:24:9:24:27 | call to method IsNotNull | -| Assert.cs:25:9:25:35 | call to method WriteLine | Assert.cs:21:10:21:11 | exit M3 | +| Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | +| Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | | Assert.cs:25:9:25:36 | ...; | Assert.cs:25:27:25:27 | access to local variable s | | Assert.cs:25:27:25:27 | access to local variable s | Assert.cs:25:27:25:34 | access to property Length | | Assert.cs:25:27:25:34 | access to property Length | Assert.cs:25:9:25:35 | call to method WriteLine | @@ -359,12 +359,12 @@ dominance | Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:30:24:30:27 | null | | Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:30:31:30:32 | "" | | Assert.cs:30:20:30:32 | ... ? ... : ... | Assert.cs:30:20:30:20 | access to parameter b | -| Assert.cs:31:9:31:32 | call to method IsTrue | Assert.cs:32:9:32:36 | ...; | +| Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | Assert.cs:32:9:32:36 | ...; | | Assert.cs:31:9:31:33 | ...; | Assert.cs:31:23:31:23 | access to local variable s | | Assert.cs:31:23:31:23 | access to local variable s | Assert.cs:31:28:31:31 | null | -| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:9:31:32 | call to method IsTrue | +| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | +| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | | Assert.cs:31:28:31:31 | null | Assert.cs:31:23:31:31 | ... == ... | -| Assert.cs:32:9:32:35 | call to method WriteLine | Assert.cs:28:10:28:11 | exit M4 | | Assert.cs:32:9:32:36 | ...; | Assert.cs:32:27:32:27 | access to local variable s | | Assert.cs:32:27:32:27 | access to local variable s | Assert.cs:32:27:32:34 | access to property Length | | Assert.cs:32:27:32:34 | access to property Length | Assert.cs:32:9:32:35 | call to method WriteLine | @@ -375,12 +375,12 @@ dominance | Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:37:24:37:27 | null | | Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:37:31:37:32 | "" | | Assert.cs:37:20:37:32 | ... ? ... : ... | Assert.cs:37:20:37:20 | access to parameter b | -| Assert.cs:38:9:38:32 | call to method IsTrue | Assert.cs:39:9:39:36 | ...; | +| Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | Assert.cs:39:9:39:36 | ...; | | Assert.cs:38:9:38:33 | ...; | Assert.cs:38:23:38:23 | access to local variable s | | Assert.cs:38:23:38:23 | access to local variable s | Assert.cs:38:28:38:31 | null | -| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:9:38:32 | call to method IsTrue | +| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | +| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | | Assert.cs:38:28:38:31 | null | Assert.cs:38:23:38:31 | ... != ... | -| Assert.cs:39:9:39:35 | call to method WriteLine | Assert.cs:35:10:35:11 | exit M5 | | Assert.cs:39:9:39:36 | ...; | Assert.cs:39:27:39:27 | access to local variable s | | Assert.cs:39:27:39:27 | access to local variable s | Assert.cs:39:27:39:34 | access to property Length | | Assert.cs:39:27:39:34 | access to property Length | Assert.cs:39:9:39:35 | call to method WriteLine | @@ -391,12 +391,12 @@ dominance | Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:44:24:44:27 | null | | Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:44:31:44:32 | "" | | Assert.cs:44:20:44:32 | ... ? ... : ... | Assert.cs:44:20:44:20 | access to parameter b | -| Assert.cs:45:9:45:33 | call to method IsFalse | Assert.cs:46:9:46:36 | ...; | +| Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | Assert.cs:46:9:46:36 | ...; | | Assert.cs:45:9:45:34 | ...; | Assert.cs:45:24:45:24 | access to local variable s | | Assert.cs:45:24:45:24 | access to local variable s | Assert.cs:45:29:45:32 | null | -| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:9:45:33 | call to method IsFalse | +| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | +| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | | Assert.cs:45:29:45:32 | null | Assert.cs:45:24:45:32 | ... != ... | -| Assert.cs:46:9:46:35 | call to method WriteLine | Assert.cs:42:10:42:11 | exit M6 | | Assert.cs:46:9:46:36 | ...; | Assert.cs:46:27:46:27 | access to local variable s | | Assert.cs:46:27:46:27 | access to local variable s | Assert.cs:46:27:46:34 | access to property Length | | Assert.cs:46:27:46:34 | access to property Length | Assert.cs:46:9:46:35 | call to method WriteLine | @@ -407,84 +407,112 @@ dominance | Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:51:24:51:27 | null | | Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:51:31:51:32 | "" | | Assert.cs:51:20:51:32 | ... ? ... : ... | Assert.cs:51:20:51:20 | access to parameter b | -| Assert.cs:52:9:52:33 | call to method IsFalse | Assert.cs:53:9:53:36 | ...; | +| Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | Assert.cs:53:9:53:36 | ...; | | Assert.cs:52:9:52:34 | ...; | Assert.cs:52:24:52:24 | access to local variable s | | Assert.cs:52:24:52:24 | access to local variable s | Assert.cs:52:29:52:32 | null | -| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:9:52:33 | call to method IsFalse | +| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | +| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | | Assert.cs:52:29:52:32 | null | Assert.cs:52:24:52:32 | ... == ... | -| Assert.cs:53:9:53:35 | call to method WriteLine | Assert.cs:49:10:49:11 | exit M7 | | Assert.cs:53:9:53:36 | ...; | Assert.cs:53:27:53:27 | access to local variable s | | Assert.cs:53:27:53:27 | access to local variable s | Assert.cs:53:27:53:34 | access to property Length | | Assert.cs:53:27:53:34 | access to property Length | Assert.cs:53:9:53:35 | call to method WriteLine | | Assert.cs:56:10:56:11 | enter M8 | Assert.cs:57:5:61:5 | {...} | | Assert.cs:57:5:61:5 | {...} | Assert.cs:58:9:58:33 | ... ...; | | Assert.cs:58:9:58:33 | ... ...; | Assert.cs:58:20:58:32 | ... ? ... : ... | -| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:59:9:59:38 | ...; | -| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:24:58:27 | null | -| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:31:58:32 | "" | +| Assert.cs:58:16:58:32 | [b (line 56): false] String s = ... | Assert.cs:59:9:59:38 | [b (line 56): false] ...; | +| Assert.cs:58:16:58:32 | [b (line 56): true] String s = ... | Assert.cs:59:9:59:38 | [b (line 56): true] ...; | +| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:24:58:27 | [b (line 56): true] null | +| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:31:58:32 | [b (line 56): false] "" | | Assert.cs:58:20:58:32 | ... ? ... : ... | Assert.cs:58:20:58:20 | access to parameter b | -| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:60:9:60:36 | ...; | -| Assert.cs:59:9:59:38 | ...; | Assert.cs:59:23:59:36 | ... && ... | -| Assert.cs:59:23:59:23 | access to local variable s | Assert.cs:59:28:59:31 | null | -| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:9:59:37 | call to method IsTrue | -| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:36:59:36 | access to parameter b | -| Assert.cs:59:23:59:36 | ... && ... | Assert.cs:59:23:59:23 | access to local variable s | -| Assert.cs:59:28:59:31 | null | Assert.cs:59:23:59:31 | ... != ... | -| Assert.cs:60:9:60:35 | call to method WriteLine | Assert.cs:56:10:56:11 | exit M8 | +| Assert.cs:58:24:58:27 | [b (line 56): true] null | Assert.cs:58:16:58:32 | [b (line 56): true] String s = ... | +| Assert.cs:58:31:58:32 | [b (line 56): false] "" | Assert.cs:58:16:58:32 | [b (line 56): false] String s = ... | +| Assert.cs:59:9:59:37 | [assertion success] call to method IsTrue | Assert.cs:60:9:60:36 | ...; | +| Assert.cs:59:9:59:38 | [b (line 56): false] ...; | Assert.cs:59:23:59:36 | [b (line 56): false] ... && ... | +| Assert.cs:59:9:59:38 | [b (line 56): true] ...; | Assert.cs:59:23:59:36 | [b (line 56): true] ... && ... | +| Assert.cs:59:23:59:23 | [b (line 56): false] access to local variable s | Assert.cs:59:28:59:31 | [b (line 56): false] null | +| Assert.cs:59:23:59:23 | [b (line 56): true] access to local variable s | Assert.cs:59:28:59:31 | [b (line 56): true] null | +| Assert.cs:59:23:59:31 | [b (line 56): false] ... != ... | Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | +| Assert.cs:59:23:59:31 | [b (line 56): true] ... != ... | Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | +| Assert.cs:59:23:59:36 | [b (line 56): false] ... && ... | Assert.cs:59:23:59:23 | [b (line 56): false] access to local variable s | +| Assert.cs:59:23:59:36 | [b (line 56): true] ... && ... | Assert.cs:59:23:59:23 | [b (line 56): true] access to local variable s | +| Assert.cs:59:28:59:31 | [b (line 56): false] null | Assert.cs:59:23:59:31 | [b (line 56): false] ... != ... | +| Assert.cs:59:28:59:31 | [b (line 56): true] null | Assert.cs:59:23:59:31 | [b (line 56): true] ... != ... | +| Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | Assert.cs:59:9:59:37 | [assertion success] call to method IsTrue | | Assert.cs:60:9:60:36 | ...; | Assert.cs:60:27:60:27 | access to local variable s | | Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:60:27:60:34 | access to property Length | | Assert.cs:60:27:60:34 | access to property Length | Assert.cs:60:9:60:35 | call to method WriteLine | | Assert.cs:63:10:63:11 | enter M9 | Assert.cs:64:5:68:5 | {...} | | Assert.cs:64:5:68:5 | {...} | Assert.cs:65:9:65:33 | ... ...; | | Assert.cs:65:9:65:33 | ... ...; | Assert.cs:65:20:65:32 | ... ? ... : ... | -| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:66:9:66:39 | ...; | -| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:24:65:27 | null | -| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:31:65:32 | "" | +| Assert.cs:65:16:65:32 | [b (line 63): false] String s = ... | Assert.cs:66:9:66:39 | [b (line 63): false] ...; | +| Assert.cs:65:16:65:32 | [b (line 63): true] String s = ... | Assert.cs:66:9:66:39 | [b (line 63): true] ...; | +| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:24:65:27 | [b (line 63): true] null | +| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:31:65:32 | [b (line 63): false] "" | | Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:65:20:65:20 | access to parameter b | -| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:67:9:67:36 | ...; | -| Assert.cs:66:9:66:39 | ...; | Assert.cs:66:24:66:37 | ... \|\| ... | -| Assert.cs:66:24:66:24 | access to local variable s | Assert.cs:66:29:66:32 | null | -| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:9:66:38 | call to method IsFalse | -| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:37:66:37 | access to parameter b | -| Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:66:24:66:24 | access to local variable s | -| Assert.cs:66:29:66:32 | null | Assert.cs:66:24:66:32 | ... == ... | -| Assert.cs:67:9:67:35 | call to method WriteLine | Assert.cs:63:10:63:11 | exit M9 | +| Assert.cs:65:24:65:27 | [b (line 63): true] null | Assert.cs:65:16:65:32 | [b (line 63): true] String s = ... | +| Assert.cs:65:31:65:32 | [b (line 63): false] "" | Assert.cs:65:16:65:32 | [b (line 63): false] String s = ... | +| Assert.cs:66:9:66:38 | [assertion success] call to method IsFalse | Assert.cs:67:9:67:36 | ...; | +| Assert.cs:66:9:66:39 | [b (line 63): false] ...; | Assert.cs:66:24:66:37 | [b (line 63): false] ... \|\| ... | +| Assert.cs:66:9:66:39 | [b (line 63): true] ...; | Assert.cs:66:24:66:37 | [b (line 63): true] ... \|\| ... | +| Assert.cs:66:24:66:24 | [b (line 63): false] access to local variable s | Assert.cs:66:29:66:32 | [b (line 63): false] null | +| Assert.cs:66:24:66:24 | [b (line 63): true] access to local variable s | Assert.cs:66:29:66:32 | [b (line 63): true] null | +| Assert.cs:66:24:66:32 | [b (line 63): false] ... == ... | Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | +| Assert.cs:66:24:66:32 | [b (line 63): true] ... == ... | Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | +| Assert.cs:66:24:66:37 | [b (line 63): false] ... \|\| ... | Assert.cs:66:24:66:24 | [b (line 63): false] access to local variable s | +| Assert.cs:66:24:66:37 | [b (line 63): true] ... \|\| ... | Assert.cs:66:24:66:24 | [b (line 63): true] access to local variable s | +| Assert.cs:66:29:66:32 | [b (line 63): false] null | Assert.cs:66:24:66:32 | [b (line 63): false] ... == ... | +| Assert.cs:66:29:66:32 | [b (line 63): true] null | Assert.cs:66:24:66:32 | [b (line 63): true] ... == ... | +| Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | Assert.cs:66:9:66:38 | [assertion success] call to method IsFalse | | Assert.cs:67:9:67:36 | ...; | Assert.cs:67:27:67:27 | access to local variable s | | Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:67:27:67:34 | access to property Length | | Assert.cs:67:27:67:34 | access to property Length | Assert.cs:67:9:67:35 | call to method WriteLine | | Assert.cs:70:10:70:12 | enter M10 | Assert.cs:71:5:75:5 | {...} | | Assert.cs:71:5:75:5 | {...} | Assert.cs:72:9:72:33 | ... ...; | | Assert.cs:72:9:72:33 | ... ...; | Assert.cs:72:20:72:32 | ... ? ... : ... | -| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:73:9:73:38 | ...; | -| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:24:72:27 | null | -| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:31:72:32 | "" | +| Assert.cs:72:16:72:32 | [b (line 70): false] String s = ... | Assert.cs:73:9:73:38 | [b (line 70): false] ...; | +| Assert.cs:72:16:72:32 | [b (line 70): true] String s = ... | Assert.cs:73:9:73:38 | [b (line 70): true] ...; | +| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:24:72:27 | [b (line 70): true] null | +| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:31:72:32 | [b (line 70): false] "" | | Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:72:20:72:20 | access to parameter b | -| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:74:9:74:36 | ...; | -| Assert.cs:73:9:73:38 | ...; | Assert.cs:73:23:73:36 | ... && ... | -| Assert.cs:73:23:73:23 | access to local variable s | Assert.cs:73:28:73:31 | null | -| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:9:73:37 | call to method IsTrue | -| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:36:73:36 | access to parameter b | -| Assert.cs:73:23:73:36 | ... && ... | Assert.cs:73:23:73:23 | access to local variable s | -| Assert.cs:73:28:73:31 | null | Assert.cs:73:23:73:31 | ... == ... | -| Assert.cs:74:9:74:35 | call to method WriteLine | Assert.cs:70:10:70:12 | exit M10 | +| Assert.cs:72:24:72:27 | [b (line 70): true] null | Assert.cs:72:16:72:32 | [b (line 70): true] String s = ... | +| Assert.cs:72:31:72:32 | [b (line 70): false] "" | Assert.cs:72:16:72:32 | [b (line 70): false] String s = ... | +| Assert.cs:73:9:73:37 | [assertion success] call to method IsTrue | Assert.cs:74:9:74:36 | ...; | +| Assert.cs:73:9:73:38 | [b (line 70): false] ...; | Assert.cs:73:23:73:36 | [b (line 70): false] ... && ... | +| Assert.cs:73:9:73:38 | [b (line 70): true] ...; | Assert.cs:73:23:73:36 | [b (line 70): true] ... && ... | +| Assert.cs:73:23:73:23 | [b (line 70): false] access to local variable s | Assert.cs:73:28:73:31 | [b (line 70): false] null | +| Assert.cs:73:23:73:23 | [b (line 70): true] access to local variable s | Assert.cs:73:28:73:31 | [b (line 70): true] null | +| Assert.cs:73:23:73:31 | [b (line 70): false] ... == ... | Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | +| Assert.cs:73:23:73:31 | [b (line 70): true] ... == ... | Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | +| Assert.cs:73:23:73:36 | [b (line 70): false] ... && ... | Assert.cs:73:23:73:23 | [b (line 70): false] access to local variable s | +| Assert.cs:73:23:73:36 | [b (line 70): true] ... && ... | Assert.cs:73:23:73:23 | [b (line 70): true] access to local variable s | +| Assert.cs:73:28:73:31 | [b (line 70): false] null | Assert.cs:73:23:73:31 | [b (line 70): false] ... == ... | +| Assert.cs:73:28:73:31 | [b (line 70): true] null | Assert.cs:73:23:73:31 | [b (line 70): true] ... == ... | +| Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | Assert.cs:73:9:73:37 | [assertion success] call to method IsTrue | | Assert.cs:74:9:74:36 | ...; | Assert.cs:74:27:74:27 | access to local variable s | | Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:74:27:74:34 | access to property Length | | Assert.cs:74:27:74:34 | access to property Length | Assert.cs:74:9:74:35 | call to method WriteLine | | Assert.cs:77:10:77:12 | enter M11 | Assert.cs:78:5:82:5 | {...} | | Assert.cs:78:5:82:5 | {...} | Assert.cs:79:9:79:33 | ... ...; | | Assert.cs:79:9:79:33 | ... ...; | Assert.cs:79:20:79:32 | ... ? ... : ... | -| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:80:9:80:39 | ...; | -| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:24:79:27 | null | -| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:31:79:32 | "" | +| Assert.cs:79:16:79:32 | [b (line 77): false] String s = ... | Assert.cs:80:9:80:39 | [b (line 77): false] ...; | +| Assert.cs:79:16:79:32 | [b (line 77): true] String s = ... | Assert.cs:80:9:80:39 | [b (line 77): true] ...; | +| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:24:79:27 | [b (line 77): true] null | +| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:31:79:32 | [b (line 77): false] "" | | Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:79:20:79:20 | access to parameter b | -| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:81:9:81:36 | ...; | -| Assert.cs:80:9:80:39 | ...; | Assert.cs:80:24:80:37 | ... \|\| ... | -| Assert.cs:80:24:80:24 | access to local variable s | Assert.cs:80:29:80:32 | null | -| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:9:80:38 | call to method IsFalse | -| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:37:80:37 | access to parameter b | -| Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:24:80:24 | access to local variable s | -| Assert.cs:80:29:80:32 | null | Assert.cs:80:24:80:32 | ... != ... | -| Assert.cs:81:9:81:35 | call to method WriteLine | Assert.cs:77:10:77:12 | exit M11 | +| Assert.cs:79:24:79:27 | [b (line 77): true] null | Assert.cs:79:16:79:32 | [b (line 77): true] String s = ... | +| Assert.cs:79:31:79:32 | [b (line 77): false] "" | Assert.cs:79:16:79:32 | [b (line 77): false] String s = ... | +| Assert.cs:80:9:80:38 | [assertion success] call to method IsFalse | Assert.cs:81:9:81:36 | ...; | +| Assert.cs:80:9:80:39 | [b (line 77): false] ...; | Assert.cs:80:24:80:37 | [b (line 77): false] ... \|\| ... | +| Assert.cs:80:9:80:39 | [b (line 77): true] ...; | Assert.cs:80:24:80:37 | [b (line 77): true] ... \|\| ... | +| Assert.cs:80:24:80:24 | [b (line 77): false] access to local variable s | Assert.cs:80:29:80:32 | [b (line 77): false] null | +| Assert.cs:80:24:80:24 | [b (line 77): true] access to local variable s | Assert.cs:80:29:80:32 | [b (line 77): true] null | +| Assert.cs:80:24:80:32 | [b (line 77): false] ... != ... | Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | +| Assert.cs:80:24:80:32 | [b (line 77): true] ... != ... | Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | +| Assert.cs:80:24:80:37 | [b (line 77): false] ... \|\| ... | Assert.cs:80:24:80:24 | [b (line 77): false] access to local variable s | +| Assert.cs:80:24:80:37 | [b (line 77): true] ... \|\| ... | Assert.cs:80:24:80:24 | [b (line 77): true] access to local variable s | +| Assert.cs:80:29:80:32 | [b (line 77): false] null | Assert.cs:80:24:80:32 | [b (line 77): false] ... != ... | +| Assert.cs:80:29:80:32 | [b (line 77): true] null | Assert.cs:80:24:80:32 | [b (line 77): true] ... != ... | +| Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | Assert.cs:80:9:80:38 | [assertion success] call to method IsFalse | | Assert.cs:81:9:81:36 | ...; | Assert.cs:81:27:81:27 | access to local variable s | | Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:81:27:81:34 | access to property Length | | Assert.cs:81:27:81:34 | access to property Length | Assert.cs:81:9:81:35 | call to method WriteLine | @@ -498,14 +526,16 @@ dominance | Assert.cs:86:20:86:32 | ... ? ... : ... | Assert.cs:86:20:86:20 | access to parameter b | | Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:86:16:86:32 | [b (line 84): true] String s = ... | | Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:86:16:86:32 | [b (line 84): false] String s = ... | -| Assert.cs:87:9:87:31 | [b (line 84): false] call to method Assert | Assert.cs:88:9:88:36 | [b (line 84): false] ...; | -| Assert.cs:87:9:87:31 | [b (line 84): true] call to method Assert | Assert.cs:88:9:88:36 | [b (line 84): true] ...; | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:88:9:88:36 | [b (line 84): false] ...; | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:88:9:88:36 | [b (line 84): true] ...; | | Assert.cs:87:9:87:32 | [b (line 84): false] ...; | Assert.cs:87:22:87:22 | [b (line 84): false] access to local variable s | | Assert.cs:87:9:87:32 | [b (line 84): true] ...; | Assert.cs:87:22:87:22 | [b (line 84): true] access to local variable s | | Assert.cs:87:22:87:22 | [b (line 84): false] access to local variable s | Assert.cs:87:27:87:30 | [b (line 84): false] null | | Assert.cs:87:22:87:22 | [b (line 84): true] access to local variable s | Assert.cs:87:27:87:30 | [b (line 84): true] null | -| Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | Assert.cs:87:9:87:31 | [b (line 84): false] call to method Assert | -| Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | Assert.cs:87:9:87:31 | [b (line 84): true] call to method Assert | +| Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | +| Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | +| Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | +| Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | | Assert.cs:87:27:87:30 | [b (line 84): false] null | Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | | Assert.cs:87:27:87:30 | [b (line 84): true] null | Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | | Assert.cs:88:9:88:35 | [b (line 84): false] call to method WriteLine | Assert.cs:90:9:90:26 | [b (line 84): false] ...; | @@ -526,12 +556,14 @@ dominance | Assert.cs:90:13:90:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:90:13:90:13 | [b (line 84): true] access to parameter b | | Assert.cs:90:17:90:20 | [b (line 84): true] null | Assert.cs:90:9:90:25 | [b (line 84): true] ... = ... | | Assert.cs:90:24:90:25 | [b (line 84): false] "" | Assert.cs:90:9:90:25 | [b (line 84): false] ... = ... | -| Assert.cs:91:9:91:24 | [b (line 84): false] call to method IsNull | Assert.cs:92:9:92:36 | [b (line 84): false] ...; | -| Assert.cs:91:9:91:24 | [b (line 84): true] call to method IsNull | Assert.cs:92:9:92:36 | [b (line 84): true] ...; | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:92:9:92:36 | [b (line 84): false] ...; | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:92:9:92:36 | [b (line 84): true] ...; | | Assert.cs:91:9:91:25 | [b (line 84): false] ...; | Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | | Assert.cs:91:9:91:25 | [b (line 84): true] ...; | Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | -| Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | Assert.cs:91:9:91:24 | [b (line 84): false] call to method IsNull | -| Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | Assert.cs:91:9:91:24 | [b (line 84): true] call to method IsNull | +| Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | +| Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | +| Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | +| Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | | Assert.cs:92:9:92:35 | [b (line 84): false] call to method WriteLine | Assert.cs:94:9:94:26 | [b (line 84): false] ...; | | Assert.cs:92:9:92:35 | [b (line 84): true] call to method WriteLine | Assert.cs:94:9:94:26 | [b (line 84): true] ...; | | Assert.cs:92:9:92:36 | [b (line 84): false] ...; | Assert.cs:92:27:92:27 | [b (line 84): false] access to local variable s | @@ -550,12 +582,14 @@ dominance | Assert.cs:94:13:94:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:94:13:94:13 | [b (line 84): true] access to parameter b | | Assert.cs:94:17:94:20 | [b (line 84): true] null | Assert.cs:94:9:94:25 | [b (line 84): true] ... = ... | | Assert.cs:94:24:94:25 | [b (line 84): false] "" | Assert.cs:94:9:94:25 | [b (line 84): false] ... = ... | -| Assert.cs:95:9:95:27 | [b (line 84): false] call to method IsNotNull | Assert.cs:96:9:96:36 | [b (line 84): false] ...; | -| Assert.cs:95:9:95:27 | [b (line 84): true] call to method IsNotNull | Assert.cs:96:9:96:36 | [b (line 84): true] ...; | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:96:9:96:36 | [b (line 84): false] ...; | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:96:9:96:36 | [b (line 84): true] ...; | | Assert.cs:95:9:95:28 | [b (line 84): false] ...; | Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | | Assert.cs:95:9:95:28 | [b (line 84): true] ...; | Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | -| Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | Assert.cs:95:9:95:27 | [b (line 84): false] call to method IsNotNull | -| Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | Assert.cs:95:9:95:27 | [b (line 84): true] call to method IsNotNull | +| Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | +| Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | +| Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | +| Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | | Assert.cs:96:9:96:35 | [b (line 84): false] call to method WriteLine | Assert.cs:98:9:98:26 | [b (line 84): false] ...; | | Assert.cs:96:9:96:35 | [b (line 84): true] call to method WriteLine | Assert.cs:98:9:98:26 | [b (line 84): true] ...; | | Assert.cs:96:9:96:36 | [b (line 84): false] ...; | Assert.cs:96:27:96:27 | [b (line 84): false] access to local variable s | @@ -574,14 +608,16 @@ dominance | Assert.cs:98:13:98:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:98:13:98:13 | [b (line 84): true] access to parameter b | | Assert.cs:98:17:98:20 | [b (line 84): true] null | Assert.cs:98:9:98:25 | [b (line 84): true] ... = ... | | Assert.cs:98:24:98:25 | [b (line 84): false] "" | Assert.cs:98:9:98:25 | [b (line 84): false] ... = ... | -| Assert.cs:99:9:99:32 | [b (line 84): false] call to method IsTrue | Assert.cs:100:9:100:36 | [b (line 84): false] ...; | -| Assert.cs:99:9:99:32 | [b (line 84): true] call to method IsTrue | Assert.cs:100:9:100:36 | [b (line 84): true] ...; | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:100:9:100:36 | [b (line 84): false] ...; | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:100:9:100:36 | [b (line 84): true] ...; | | Assert.cs:99:9:99:33 | [b (line 84): false] ...; | Assert.cs:99:23:99:23 | [b (line 84): false] access to local variable s | | Assert.cs:99:9:99:33 | [b (line 84): true] ...; | Assert.cs:99:23:99:23 | [b (line 84): true] access to local variable s | | Assert.cs:99:23:99:23 | [b (line 84): false] access to local variable s | Assert.cs:99:28:99:31 | [b (line 84): false] null | | Assert.cs:99:23:99:23 | [b (line 84): true] access to local variable s | Assert.cs:99:28:99:31 | [b (line 84): true] null | -| Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | Assert.cs:99:9:99:32 | [b (line 84): false] call to method IsTrue | -| Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | Assert.cs:99:9:99:32 | [b (line 84): true] call to method IsTrue | +| Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | | Assert.cs:99:28:99:31 | [b (line 84): false] null | Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | | Assert.cs:99:28:99:31 | [b (line 84): true] null | Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | | Assert.cs:100:9:100:35 | [b (line 84): false] call to method WriteLine | Assert.cs:102:9:102:26 | [b (line 84): false] ...; | @@ -602,14 +638,16 @@ dominance | Assert.cs:102:13:102:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:102:13:102:13 | [b (line 84): true] access to parameter b | | Assert.cs:102:17:102:20 | [b (line 84): true] null | Assert.cs:102:9:102:25 | [b (line 84): true] ... = ... | | Assert.cs:102:24:102:25 | [b (line 84): false] "" | Assert.cs:102:9:102:25 | [b (line 84): false] ... = ... | -| Assert.cs:103:9:103:32 | [b (line 84): false] call to method IsTrue | Assert.cs:104:9:104:36 | [b (line 84): false] ...; | -| Assert.cs:103:9:103:32 | [b (line 84): true] call to method IsTrue | Assert.cs:104:9:104:36 | [b (line 84): true] ...; | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:104:9:104:36 | [b (line 84): false] ...; | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:104:9:104:36 | [b (line 84): true] ...; | | Assert.cs:103:9:103:33 | [b (line 84): false] ...; | Assert.cs:103:23:103:23 | [b (line 84): false] access to local variable s | | Assert.cs:103:9:103:33 | [b (line 84): true] ...; | Assert.cs:103:23:103:23 | [b (line 84): true] access to local variable s | | Assert.cs:103:23:103:23 | [b (line 84): false] access to local variable s | Assert.cs:103:28:103:31 | [b (line 84): false] null | | Assert.cs:103:23:103:23 | [b (line 84): true] access to local variable s | Assert.cs:103:28:103:31 | [b (line 84): true] null | -| Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | Assert.cs:103:9:103:32 | [b (line 84): false] call to method IsTrue | -| Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | Assert.cs:103:9:103:32 | [b (line 84): true] call to method IsTrue | +| Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | | Assert.cs:103:28:103:31 | [b (line 84): false] null | Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | | Assert.cs:103:28:103:31 | [b (line 84): true] null | Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | | Assert.cs:104:9:104:35 | [b (line 84): false] call to method WriteLine | Assert.cs:106:9:106:26 | [b (line 84): false] ...; | @@ -630,14 +668,16 @@ dominance | Assert.cs:106:13:106:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:106:13:106:13 | [b (line 84): true] access to parameter b | | Assert.cs:106:17:106:20 | [b (line 84): true] null | Assert.cs:106:9:106:25 | [b (line 84): true] ... = ... | | Assert.cs:106:24:106:25 | [b (line 84): false] "" | Assert.cs:106:9:106:25 | [b (line 84): false] ... = ... | -| Assert.cs:107:9:107:33 | [b (line 84): false] call to method IsFalse | Assert.cs:108:9:108:36 | [b (line 84): false] ...; | -| Assert.cs:107:9:107:33 | [b (line 84): true] call to method IsFalse | Assert.cs:108:9:108:36 | [b (line 84): true] ...; | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:108:9:108:36 | [b (line 84): false] ...; | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:108:9:108:36 | [b (line 84): true] ...; | | Assert.cs:107:9:107:34 | [b (line 84): false] ...; | Assert.cs:107:24:107:24 | [b (line 84): false] access to local variable s | | Assert.cs:107:9:107:34 | [b (line 84): true] ...; | Assert.cs:107:24:107:24 | [b (line 84): true] access to local variable s | | Assert.cs:107:24:107:24 | [b (line 84): false] access to local variable s | Assert.cs:107:29:107:32 | [b (line 84): false] null | | Assert.cs:107:24:107:24 | [b (line 84): true] access to local variable s | Assert.cs:107:29:107:32 | [b (line 84): true] null | -| Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | Assert.cs:107:9:107:33 | [b (line 84): false] call to method IsFalse | -| Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | Assert.cs:107:9:107:33 | [b (line 84): true] call to method IsFalse | +| Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | | Assert.cs:107:29:107:32 | [b (line 84): false] null | Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | | Assert.cs:107:29:107:32 | [b (line 84): true] null | Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | | Assert.cs:108:9:108:35 | [b (line 84): false] call to method WriteLine | Assert.cs:110:9:110:26 | [b (line 84): false] ...; | @@ -658,14 +698,16 @@ dominance | Assert.cs:110:13:110:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:110:13:110:13 | [b (line 84): true] access to parameter b | | Assert.cs:110:17:110:20 | [b (line 84): true] null | Assert.cs:110:9:110:25 | [b (line 84): true] ... = ... | | Assert.cs:110:24:110:25 | [b (line 84): false] "" | Assert.cs:110:9:110:25 | [b (line 84): false] ... = ... | -| Assert.cs:111:9:111:33 | [b (line 84): false] call to method IsFalse | Assert.cs:112:9:112:36 | [b (line 84): false] ...; | -| Assert.cs:111:9:111:33 | [b (line 84): true] call to method IsFalse | Assert.cs:112:9:112:36 | [b (line 84): true] ...; | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:112:9:112:36 | [b (line 84): false] ...; | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:112:9:112:36 | [b (line 84): true] ...; | | Assert.cs:111:9:111:34 | [b (line 84): false] ...; | Assert.cs:111:24:111:24 | [b (line 84): false] access to local variable s | | Assert.cs:111:9:111:34 | [b (line 84): true] ...; | Assert.cs:111:24:111:24 | [b (line 84): true] access to local variable s | | Assert.cs:111:24:111:24 | [b (line 84): false] access to local variable s | Assert.cs:111:29:111:32 | [b (line 84): false] null | | Assert.cs:111:24:111:24 | [b (line 84): true] access to local variable s | Assert.cs:111:29:111:32 | [b (line 84): true] null | -| Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | Assert.cs:111:9:111:33 | [b (line 84): false] call to method IsFalse | -| Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | Assert.cs:111:9:111:33 | [b (line 84): true] call to method IsFalse | +| Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | | Assert.cs:111:29:111:32 | [b (line 84): false] null | Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | | Assert.cs:111:29:111:32 | [b (line 84): true] null | Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | | Assert.cs:112:9:112:35 | [b (line 84): false] call to method WriteLine | Assert.cs:114:9:114:26 | [b (line 84): false] ...; | @@ -686,110 +728,73 @@ dominance | Assert.cs:114:13:114:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:114:13:114:13 | [b (line 84): true] access to parameter b | | Assert.cs:114:17:114:20 | [b (line 84): true] null | Assert.cs:114:9:114:25 | [b (line 84): true] ... = ... | | Assert.cs:114:24:114:25 | [b (line 84): false] "" | Assert.cs:114:9:114:25 | [b (line 84): false] ... = ... | -| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:116:9:116:36 | [b (line 84): false] ...; | -| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:116:9:116:36 | [b (line 84): true] ...; | +| Assert.cs:115:9:115:37 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:116:9:116:36 | [b (line 84): true] ...; | | Assert.cs:115:9:115:38 | [b (line 84): false] ...; | Assert.cs:115:23:115:36 | [b (line 84): false] ... && ... | | Assert.cs:115:9:115:38 | [b (line 84): true] ...; | Assert.cs:115:23:115:36 | [b (line 84): true] ... && ... | | Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | Assert.cs:115:28:115:31 | [b (line 84): false] null | | Assert.cs:115:23:115:23 | [b (line 84): true] access to local variable s | Assert.cs:115:28:115:31 | [b (line 84): true] null | -| Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | | Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | -| Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | | Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | | Assert.cs:115:23:115:36 | [b (line 84): false] ... && ... | Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | | Assert.cs:115:23:115:36 | [b (line 84): true] ... && ... | Assert.cs:115:23:115:23 | [b (line 84): true] access to local variable s | | Assert.cs:115:28:115:31 | [b (line 84): false] null | Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | | Assert.cs:115:28:115:31 | [b (line 84): true] null | Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | -| Assert.cs:116:9:116:35 | [b (line 84): false] call to method WriteLine | Assert.cs:118:9:118:26 | [b (line 84): false] ...; | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:115:9:115:37 | [assertion success, b (line 84): true] call to method IsTrue | | Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | Assert.cs:118:9:118:26 | [b (line 84): true] ...; | -| Assert.cs:116:9:116:36 | [b (line 84): false] ...; | Assert.cs:116:27:116:27 | [b (line 84): false] access to local variable s | | Assert.cs:116:9:116:36 | [b (line 84): true] ...; | Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | -| Assert.cs:116:27:116:27 | [b (line 84): false] access to local variable s | Assert.cs:116:27:116:34 | [b (line 84): false] access to property Length | | Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | -| Assert.cs:116:27:116:34 | [b (line 84): false] access to property Length | Assert.cs:116:9:116:35 | [b (line 84): false] call to method WriteLine | | Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | -| Assert.cs:118:9:118:25 | [b (line 84): false] ... = ... | Assert.cs:119:9:119:40 | [b (line 84): false] ...; | | Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | Assert.cs:119:9:119:40 | [b (line 84): true] ...; | -| Assert.cs:118:9:118:26 | [b (line 84): false] ...; | Assert.cs:118:13:118:25 | [b (line 84): false] ... ? ... : ... | | Assert.cs:118:9:118:26 | [b (line 84): true] ...; | Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | -| Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | Assert.cs:118:24:118:25 | [b (line 84): false] "" | | Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | Assert.cs:118:17:118:20 | [b (line 84): true] null | -| Assert.cs:118:13:118:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | | Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | | Assert.cs:118:17:118:20 | [b (line 84): true] null | Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | -| Assert.cs:118:24:118:25 | [b (line 84): false] "" | Assert.cs:118:9:118:25 | [b (line 84): false] ... = ... | -| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:120:9:120:36 | [b (line 84): false] ...; | -| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:120:9:120:36 | [b (line 84): true] ...; | -| Assert.cs:119:9:119:40 | [b (line 84): false] ...; | Assert.cs:119:24:119:38 | [b (line 84): false] ... \|\| ... | +| Assert.cs:119:9:119:39 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:120:9:120:36 | [b (line 84): true] ...; | | Assert.cs:119:9:119:40 | [b (line 84): true] ...; | Assert.cs:119:24:119:38 | [b (line 84): true] ... \|\| ... | -| Assert.cs:119:24:119:24 | [b (line 84): false] access to local variable s | Assert.cs:119:29:119:32 | [b (line 84): false] null | | Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | Assert.cs:119:29:119:32 | [b (line 84): true] null | -| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | -| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | Assert.cs:119:37:119:38 | [b (line 84): false] !... | -| Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | +| Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | | Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:37:119:38 | [b (line 84): true] !... | -| Assert.cs:119:24:119:38 | [b (line 84): false] ... \|\| ... | Assert.cs:119:24:119:24 | [b (line 84): false] access to local variable s | | Assert.cs:119:24:119:38 | [b (line 84): true] ... \|\| ... | Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | -| Assert.cs:119:29:119:32 | [b (line 84): false] null | Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | | Assert.cs:119:29:119:32 | [b (line 84): true] null | Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | -| Assert.cs:119:37:119:38 | [b (line 84): false] !... | Assert.cs:119:38:119:38 | [b (line 84): false] access to parameter b | | Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | -| Assert.cs:120:9:120:35 | [b (line 84): false] call to method WriteLine | Assert.cs:122:9:122:26 | [b (line 84): false] ...; | +| Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | Assert.cs:119:9:119:39 | [assertion success, b (line 84): true] call to method IsFalse | | Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | Assert.cs:122:9:122:26 | [b (line 84): true] ...; | -| Assert.cs:120:9:120:36 | [b (line 84): false] ...; | Assert.cs:120:27:120:27 | [b (line 84): false] access to local variable s | | Assert.cs:120:9:120:36 | [b (line 84): true] ...; | Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | -| Assert.cs:120:27:120:27 | [b (line 84): false] access to local variable s | Assert.cs:120:27:120:34 | [b (line 84): false] access to property Length | | Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | -| Assert.cs:120:27:120:34 | [b (line 84): false] access to property Length | Assert.cs:120:9:120:35 | [b (line 84): false] call to method WriteLine | | Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | -| Assert.cs:122:9:122:25 | [b (line 84): false] ... = ... | Assert.cs:123:9:123:38 | [b (line 84): false] ...; | | Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | Assert.cs:123:9:123:38 | [b (line 84): true] ...; | -| Assert.cs:122:9:122:26 | [b (line 84): false] ...; | Assert.cs:122:13:122:25 | [b (line 84): false] ... ? ... : ... | | Assert.cs:122:9:122:26 | [b (line 84): true] ...; | Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | -| Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | Assert.cs:122:24:122:25 | [b (line 84): false] "" | | Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | Assert.cs:122:17:122:20 | [b (line 84): true] null | -| Assert.cs:122:13:122:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | | Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | | Assert.cs:122:17:122:20 | [b (line 84): true] null | Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | -| Assert.cs:122:24:122:25 | [b (line 84): false] "" | Assert.cs:122:9:122:25 | [b (line 84): false] ... = ... | -| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:124:9:124:36 | [b (line 84): false] ...; | -| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:124:9:124:36 | [b (line 84): true] ...; | -| Assert.cs:123:9:123:38 | [b (line 84): false] ...; | Assert.cs:123:23:123:36 | [b (line 84): false] ... && ... | +| Assert.cs:123:9:123:37 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:124:9:124:36 | [b (line 84): true] ...; | | Assert.cs:123:9:123:38 | [b (line 84): true] ...; | Assert.cs:123:23:123:36 | [b (line 84): true] ... && ... | -| Assert.cs:123:23:123:23 | [b (line 84): false] access to local variable s | Assert.cs:123:28:123:31 | [b (line 84): false] null | | Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | Assert.cs:123:28:123:31 | [b (line 84): true] null | -| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | -| Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | | Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | -| Assert.cs:123:23:123:36 | [b (line 84): false] ... && ... | Assert.cs:123:23:123:23 | [b (line 84): false] access to local variable s | | Assert.cs:123:23:123:36 | [b (line 84): true] ... && ... | Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | -| Assert.cs:123:28:123:31 | [b (line 84): false] null | Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | | Assert.cs:123:28:123:31 | [b (line 84): true] null | Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | -| Assert.cs:124:9:124:35 | [b (line 84): false] call to method WriteLine | Assert.cs:126:9:126:26 | [b (line 84): false] ...; | +| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:123:9:123:37 | [assertion success, b (line 84): true] call to method IsTrue | | Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | Assert.cs:126:9:126:26 | [b (line 84): true] ...; | -| Assert.cs:124:9:124:36 | [b (line 84): false] ...; | Assert.cs:124:27:124:27 | [b (line 84): false] access to local variable s | | Assert.cs:124:9:124:36 | [b (line 84): true] ...; | Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | -| Assert.cs:124:27:124:27 | [b (line 84): false] access to local variable s | Assert.cs:124:27:124:34 | [b (line 84): false] access to property Length | | Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | -| Assert.cs:124:27:124:34 | [b (line 84): false] access to property Length | Assert.cs:124:9:124:35 | [b (line 84): false] call to method WriteLine | | Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:127:9:127:40 | ...; | -| Assert.cs:126:9:126:26 | [b (line 84): false] ...; | Assert.cs:126:13:126:25 | [b (line 84): false] ... ? ... : ... | +| Assert.cs:126:9:126:25 | [b (line 84): true] ... = ... | Assert.cs:127:9:127:40 | [b (line 84): true] ...; | | Assert.cs:126:9:126:26 | [b (line 84): true] ...; | Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | -| Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | Assert.cs:126:24:126:25 | "" | -| Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | Assert.cs:126:17:126:20 | null | -| Assert.cs:126:13:126:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | +| Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | Assert.cs:126:17:126:20 | [b (line 84): true] null | | Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:128:9:128:36 | ...; | -| Assert.cs:127:9:127:40 | ...; | Assert.cs:127:24:127:38 | ... \|\| ... | -| Assert.cs:127:24:127:24 | access to local variable s | Assert.cs:127:29:127:32 | null | -| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:9:127:39 | call to method IsFalse | -| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:37:127:38 | !... | -| Assert.cs:127:24:127:38 | ... \|\| ... | Assert.cs:127:24:127:24 | access to local variable s | -| Assert.cs:127:29:127:32 | null | Assert.cs:127:24:127:32 | ... != ... | -| Assert.cs:127:37:127:38 | !... | Assert.cs:127:38:127:38 | access to parameter b | -| Assert.cs:128:9:128:35 | call to method WriteLine | Assert.cs:84:10:84:12 | exit M12 | +| Assert.cs:126:17:126:20 | [b (line 84): true] null | Assert.cs:126:9:126:25 | [b (line 84): true] ... = ... | +| Assert.cs:127:9:127:39 | [assertion success] call to method IsFalse | Assert.cs:128:9:128:36 | ...; | +| Assert.cs:127:9:127:40 | [b (line 84): true] ...; | Assert.cs:127:24:127:38 | [b (line 84): true] ... \|\| ... | +| Assert.cs:127:24:127:24 | [b (line 84): true] access to local variable s | Assert.cs:127:29:127:32 | [b (line 84): true] null | +| Assert.cs:127:24:127:32 | [b (line 84): true] ... != ... | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | +| Assert.cs:127:24:127:32 | [b (line 84): true] ... != ... | Assert.cs:127:37:127:38 | [b (line 84): true] !... | +| Assert.cs:127:24:127:38 | [b (line 84): true] ... \|\| ... | Assert.cs:127:24:127:24 | [b (line 84): true] access to local variable s | +| Assert.cs:127:29:127:32 | [b (line 84): true] null | Assert.cs:127:24:127:32 | [b (line 84): true] ... != ... | +| Assert.cs:127:37:127:38 | [b (line 84): true] !... | Assert.cs:127:38:127:38 | [b (line 84): true] access to parameter b | +| Assert.cs:127:38:127:38 | [b (line 84): true] access to parameter b | Assert.cs:127:9:127:39 | [assertion success] call to method IsFalse | | Assert.cs:128:9:128:36 | ...; | Assert.cs:128:27:128:27 | access to local variable s | | Assert.cs:128:27:128:27 | access to local variable s | Assert.cs:128:27:128:34 | access to property Length | | Assert.cs:128:27:128:34 | access to property Length | Assert.cs:128:9:128:35 | call to method WriteLine | @@ -1476,23 +1481,23 @@ dominance | ExitMethods.cs:116:27:116:29 | - | ExitMethods.cs:116:16:116:30 | call to method Contains | | ExitMethods.cs:119:17:119:32 | enter FailingAssertion | ExitMethods.cs:120:5:123:5 | {...} | | ExitMethods.cs:120:5:123:5 | {...} | ExitMethods.cs:121:9:121:29 | ...; | -| ExitMethods.cs:121:9:121:28 | call to method IsTrue | ExitMethods.cs:119:17:119:32 | exit FailingAssertion | +| ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:119:17:119:32 | exit FailingAssertion | | ExitMethods.cs:121:9:121:29 | ...; | ExitMethods.cs:121:23:121:27 | false | -| ExitMethods.cs:121:23:121:27 | false | ExitMethods.cs:121:9:121:28 | call to method IsTrue | +| ExitMethods.cs:121:23:121:27 | false | ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | | ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | ExitMethods.cs:126:5:129:5 | {...} | | ExitMethods.cs:126:5:129:5 | {...} | ExitMethods.cs:127:9:127:27 | ...; | | ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | ExitMethods.cs:125:17:125:33 | exit FailingAssertion2 | | ExitMethods.cs:127:9:127:26 | this access | ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | | ExitMethods.cs:127:9:127:27 | ...; | ExitMethods.cs:127:9:127:26 | this access | | ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:48:131:48 | access to parameter b | -| ExitMethods.cs:131:33:131:49 | call to method IsFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse | -| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:33:131:49 | call to method IsFalse | +| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | +| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | | ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | ExitMethods.cs:134:5:137:5 | {...} | | ExitMethods.cs:134:5:137:5 | {...} | ExitMethods.cs:135:9:135:26 | ...; | -| ExitMethods.cs:135:9:135:25 | call to method AssertFalse | ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 | +| ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 | | ExitMethods.cs:135:9:135:25 | this access | ExitMethods.cs:135:21:135:24 | true | | ExitMethods.cs:135:9:135:26 | ...; | ExitMethods.cs:135:9:135:25 | this access | -| ExitMethods.cs:135:21:135:24 | true | ExitMethods.cs:135:9:135:25 | call to method AssertFalse | +| ExitMethods.cs:135:21:135:24 | true | ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:6:5:8:5 | {...} | | Extensions.cs:6:5:8:5 | {...} | Extensions.cs:7:28:7:28 | access to parameter s | | Extensions.cs:7:9:7:30 | return ...; | Extensions.cs:5:23:5:29 | exit ToInt32 | @@ -4001,6 +4006,7 @@ postDominance | ArrayCreation.cs:9:43:9:50 | { ..., ... } | ArrayCreation.cs:9:48:9:48 | 3 | | ArrayCreation.cs:9:45:9:45 | 2 | ArrayCreation.cs:9:33:9:40 | { ..., ... } | | ArrayCreation.cs:9:48:9:48 | 3 | ArrayCreation.cs:9:45:9:45 | 2 | +| Assert.cs:7:10:7:11 | exit M1 | Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | | Assert.cs:7:10:7:11 | exit M1 | Assert.cs:11:9:11:35 | call to method WriteLine | | Assert.cs:8:5:12:5 | {...} | Assert.cs:7:10:7:11 | enter M1 | | Assert.cs:9:9:9:33 | ... ...; | Assert.cs:8:5:12:5 | {...} | @@ -4008,15 +4014,15 @@ postDominance | Assert.cs:9:16:9:32 | String s = ... | Assert.cs:9:31:9:32 | "" | | Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:9:20:9:32 | ... ? ... : ... | | Assert.cs:9:20:9:32 | ... ? ... : ... | Assert.cs:9:9:9:33 | ... ...; | -| Assert.cs:10:9:10:31 | call to method Assert | Assert.cs:10:22:10:30 | ... != ... | | Assert.cs:10:9:10:32 | ...; | Assert.cs:9:16:9:32 | String s = ... | | Assert.cs:10:22:10:22 | access to local variable s | Assert.cs:10:9:10:32 | ...; | | Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:27:10:30 | null | | Assert.cs:10:27:10:30 | null | Assert.cs:10:22:10:22 | access to local variable s | | Assert.cs:11:9:11:35 | call to method WriteLine | Assert.cs:11:27:11:34 | access to property Length | -| Assert.cs:11:9:11:36 | ...; | Assert.cs:10:9:10:31 | call to method Assert | +| Assert.cs:11:9:11:36 | ...; | Assert.cs:10:9:10:31 | [assertion success] call to method Assert | | Assert.cs:11:27:11:27 | access to local variable s | Assert.cs:11:9:11:36 | ...; | | Assert.cs:11:27:11:34 | access to property Length | Assert.cs:11:27:11:27 | access to local variable s | +| Assert.cs:14:10:14:11 | exit M2 | Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | | Assert.cs:14:10:14:11 | exit M2 | Assert.cs:18:9:18:35 | call to method WriteLine | | Assert.cs:15:5:19:5 | {...} | Assert.cs:14:10:14:11 | enter M2 | | Assert.cs:16:9:16:33 | ... ...; | Assert.cs:15:5:19:5 | {...} | @@ -4024,13 +4030,13 @@ postDominance | Assert.cs:16:16:16:32 | String s = ... | Assert.cs:16:31:16:32 | "" | | Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:16:20:16:32 | ... ? ... : ... | | Assert.cs:16:20:16:32 | ... ? ... : ... | Assert.cs:16:9:16:33 | ... ...; | -| Assert.cs:17:9:17:24 | call to method IsNull | Assert.cs:17:23:17:23 | access to local variable s | | Assert.cs:17:9:17:25 | ...; | Assert.cs:16:16:16:32 | String s = ... | | Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:17:9:17:25 | ...; | | Assert.cs:18:9:18:35 | call to method WriteLine | Assert.cs:18:27:18:34 | access to property Length | -| Assert.cs:18:9:18:36 | ...; | Assert.cs:17:9:17:24 | call to method IsNull | +| Assert.cs:18:9:18:36 | ...; | Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | | Assert.cs:18:27:18:27 | access to local variable s | Assert.cs:18:9:18:36 | ...; | | Assert.cs:18:27:18:34 | access to property Length | Assert.cs:18:27:18:27 | access to local variable s | +| Assert.cs:21:10:21:11 | exit M3 | Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | | Assert.cs:21:10:21:11 | exit M3 | Assert.cs:25:9:25:35 | call to method WriteLine | | Assert.cs:22:5:26:5 | {...} | Assert.cs:21:10:21:11 | enter M3 | | Assert.cs:23:9:23:33 | ... ...; | Assert.cs:22:5:26:5 | {...} | @@ -4038,13 +4044,13 @@ postDominance | Assert.cs:23:16:23:32 | String s = ... | Assert.cs:23:31:23:32 | "" | | Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:23:20:23:32 | ... ? ... : ... | | Assert.cs:23:20:23:32 | ... ? ... : ... | Assert.cs:23:9:23:33 | ... ...; | -| Assert.cs:24:9:24:27 | call to method IsNotNull | Assert.cs:24:26:24:26 | access to local variable s | | Assert.cs:24:9:24:28 | ...; | Assert.cs:23:16:23:32 | String s = ... | | Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:24:9:24:28 | ...; | | Assert.cs:25:9:25:35 | call to method WriteLine | Assert.cs:25:27:25:34 | access to property Length | -| Assert.cs:25:9:25:36 | ...; | Assert.cs:24:9:24:27 | call to method IsNotNull | +| Assert.cs:25:9:25:36 | ...; | Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | | Assert.cs:25:27:25:27 | access to local variable s | Assert.cs:25:9:25:36 | ...; | | Assert.cs:25:27:25:34 | access to property Length | Assert.cs:25:27:25:27 | access to local variable s | +| Assert.cs:28:10:28:11 | exit M4 | Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | | Assert.cs:28:10:28:11 | exit M4 | Assert.cs:32:9:32:35 | call to method WriteLine | | Assert.cs:29:5:33:5 | {...} | Assert.cs:28:10:28:11 | enter M4 | | Assert.cs:30:9:30:33 | ... ...; | Assert.cs:29:5:33:5 | {...} | @@ -4052,15 +4058,15 @@ postDominance | Assert.cs:30:16:30:32 | String s = ... | Assert.cs:30:31:30:32 | "" | | Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:30:20:30:32 | ... ? ... : ... | | Assert.cs:30:20:30:32 | ... ? ... : ... | Assert.cs:30:9:30:33 | ... ...; | -| Assert.cs:31:9:31:32 | call to method IsTrue | Assert.cs:31:23:31:31 | ... == ... | | Assert.cs:31:9:31:33 | ...; | Assert.cs:30:16:30:32 | String s = ... | | Assert.cs:31:23:31:23 | access to local variable s | Assert.cs:31:9:31:33 | ...; | | Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:28:31:31 | null | | Assert.cs:31:28:31:31 | null | Assert.cs:31:23:31:23 | access to local variable s | | Assert.cs:32:9:32:35 | call to method WriteLine | Assert.cs:32:27:32:34 | access to property Length | -| Assert.cs:32:9:32:36 | ...; | Assert.cs:31:9:31:32 | call to method IsTrue | +| Assert.cs:32:9:32:36 | ...; | Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | | Assert.cs:32:27:32:27 | access to local variable s | Assert.cs:32:9:32:36 | ...; | | Assert.cs:32:27:32:34 | access to property Length | Assert.cs:32:27:32:27 | access to local variable s | +| Assert.cs:35:10:35:11 | exit M5 | Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | | Assert.cs:35:10:35:11 | exit M5 | Assert.cs:39:9:39:35 | call to method WriteLine | | Assert.cs:36:5:40:5 | {...} | Assert.cs:35:10:35:11 | enter M5 | | Assert.cs:37:9:37:33 | ... ...; | Assert.cs:36:5:40:5 | {...} | @@ -4068,15 +4074,15 @@ postDominance | Assert.cs:37:16:37:32 | String s = ... | Assert.cs:37:31:37:32 | "" | | Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:37:20:37:32 | ... ? ... : ... | | Assert.cs:37:20:37:32 | ... ? ... : ... | Assert.cs:37:9:37:33 | ... ...; | -| Assert.cs:38:9:38:32 | call to method IsTrue | Assert.cs:38:23:38:31 | ... != ... | | Assert.cs:38:9:38:33 | ...; | Assert.cs:37:16:37:32 | String s = ... | | Assert.cs:38:23:38:23 | access to local variable s | Assert.cs:38:9:38:33 | ...; | | Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:28:38:31 | null | | Assert.cs:38:28:38:31 | null | Assert.cs:38:23:38:23 | access to local variable s | | Assert.cs:39:9:39:35 | call to method WriteLine | Assert.cs:39:27:39:34 | access to property Length | -| Assert.cs:39:9:39:36 | ...; | Assert.cs:38:9:38:32 | call to method IsTrue | +| Assert.cs:39:9:39:36 | ...; | Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | | Assert.cs:39:27:39:27 | access to local variable s | Assert.cs:39:9:39:36 | ...; | | Assert.cs:39:27:39:34 | access to property Length | Assert.cs:39:27:39:27 | access to local variable s | +| Assert.cs:42:10:42:11 | exit M6 | Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | | Assert.cs:42:10:42:11 | exit M6 | Assert.cs:46:9:46:35 | call to method WriteLine | | Assert.cs:43:5:47:5 | {...} | Assert.cs:42:10:42:11 | enter M6 | | Assert.cs:44:9:44:33 | ... ...; | Assert.cs:43:5:47:5 | {...} | @@ -4084,15 +4090,15 @@ postDominance | Assert.cs:44:16:44:32 | String s = ... | Assert.cs:44:31:44:32 | "" | | Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:44:20:44:32 | ... ? ... : ... | | Assert.cs:44:20:44:32 | ... ? ... : ... | Assert.cs:44:9:44:33 | ... ...; | -| Assert.cs:45:9:45:33 | call to method IsFalse | Assert.cs:45:24:45:32 | ... != ... | | Assert.cs:45:9:45:34 | ...; | Assert.cs:44:16:44:32 | String s = ... | | Assert.cs:45:24:45:24 | access to local variable s | Assert.cs:45:9:45:34 | ...; | | Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:29:45:32 | null | | Assert.cs:45:29:45:32 | null | Assert.cs:45:24:45:24 | access to local variable s | | Assert.cs:46:9:46:35 | call to method WriteLine | Assert.cs:46:27:46:34 | access to property Length | -| Assert.cs:46:9:46:36 | ...; | Assert.cs:45:9:45:33 | call to method IsFalse | +| Assert.cs:46:9:46:36 | ...; | Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | | Assert.cs:46:27:46:27 | access to local variable s | Assert.cs:46:9:46:36 | ...; | | Assert.cs:46:27:46:34 | access to property Length | Assert.cs:46:27:46:27 | access to local variable s | +| Assert.cs:49:10:49:11 | exit M7 | Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | | Assert.cs:49:10:49:11 | exit M7 | Assert.cs:53:9:53:35 | call to method WriteLine | | Assert.cs:50:5:54:5 | {...} | Assert.cs:49:10:49:11 | enter M7 | | Assert.cs:51:9:51:33 | ... ...; | Assert.cs:50:5:54:5 | {...} | @@ -4100,87 +4106,133 @@ postDominance | Assert.cs:51:16:51:32 | String s = ... | Assert.cs:51:31:51:32 | "" | | Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:51:20:51:32 | ... ? ... : ... | | Assert.cs:51:20:51:32 | ... ? ... : ... | Assert.cs:51:9:51:33 | ... ...; | -| Assert.cs:52:9:52:33 | call to method IsFalse | Assert.cs:52:24:52:32 | ... == ... | | Assert.cs:52:9:52:34 | ...; | Assert.cs:51:16:51:32 | String s = ... | | Assert.cs:52:24:52:24 | access to local variable s | Assert.cs:52:9:52:34 | ...; | | Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:29:52:32 | null | | Assert.cs:52:29:52:32 | null | Assert.cs:52:24:52:24 | access to local variable s | | Assert.cs:53:9:53:35 | call to method WriteLine | Assert.cs:53:27:53:34 | access to property Length | -| Assert.cs:53:9:53:36 | ...; | Assert.cs:52:9:52:33 | call to method IsFalse | +| Assert.cs:53:9:53:36 | ...; | Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | | Assert.cs:53:27:53:27 | access to local variable s | Assert.cs:53:9:53:36 | ...; | | Assert.cs:53:27:53:34 | access to property Length | Assert.cs:53:27:53:27 | access to local variable s | +| Assert.cs:56:10:56:11 | exit M8 | Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | | Assert.cs:56:10:56:11 | exit M8 | Assert.cs:60:9:60:35 | call to method WriteLine | | Assert.cs:57:5:61:5 | {...} | Assert.cs:56:10:56:11 | enter M8 | | Assert.cs:58:9:58:33 | ... ...; | Assert.cs:57:5:61:5 | {...} | -| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:58:24:58:27 | null | -| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:58:31:58:32 | "" | +| Assert.cs:58:16:58:32 | [b (line 56): false] String s = ... | Assert.cs:58:31:58:32 | [b (line 56): false] "" | +| Assert.cs:58:16:58:32 | [b (line 56): true] String s = ... | Assert.cs:58:24:58:27 | [b (line 56): true] null | | Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:20:58:32 | ... ? ... : ... | | Assert.cs:58:20:58:32 | ... ? ... : ... | Assert.cs:58:9:58:33 | ... ...; | -| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:59:23:59:31 | ... != ... | -| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:59:36:59:36 | access to parameter b | -| Assert.cs:59:9:59:38 | ...; | Assert.cs:58:16:58:32 | String s = ... | -| Assert.cs:59:23:59:23 | access to local variable s | Assert.cs:59:23:59:36 | ... && ... | -| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:28:59:31 | null | -| Assert.cs:59:23:59:36 | ... && ... | Assert.cs:59:9:59:38 | ...; | -| Assert.cs:59:28:59:31 | null | Assert.cs:59:23:59:23 | access to local variable s | +| Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | Assert.cs:59:23:59:31 | [b (line 56): false] ... != ... | +| Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | +| Assert.cs:59:9:59:37 | [assertion success] call to method IsTrue | Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | +| Assert.cs:59:9:59:38 | [b (line 56): false] ...; | Assert.cs:58:16:58:32 | [b (line 56): false] String s = ... | +| Assert.cs:59:9:59:38 | [b (line 56): true] ...; | Assert.cs:58:16:58:32 | [b (line 56): true] String s = ... | +| Assert.cs:59:23:59:23 | [b (line 56): false] access to local variable s | Assert.cs:59:23:59:36 | [b (line 56): false] ... && ... | +| Assert.cs:59:23:59:23 | [b (line 56): true] access to local variable s | Assert.cs:59:23:59:36 | [b (line 56): true] ... && ... | +| Assert.cs:59:23:59:31 | [b (line 56): false] ... != ... | Assert.cs:59:28:59:31 | [b (line 56): false] null | +| Assert.cs:59:23:59:31 | [b (line 56): true] ... != ... | Assert.cs:59:28:59:31 | [b (line 56): true] null | +| Assert.cs:59:23:59:36 | [b (line 56): false] ... && ... | Assert.cs:59:9:59:38 | [b (line 56): false] ...; | +| Assert.cs:59:23:59:36 | [b (line 56): true] ... && ... | Assert.cs:59:9:59:38 | [b (line 56): true] ...; | +| Assert.cs:59:28:59:31 | [b (line 56): false] null | Assert.cs:59:23:59:23 | [b (line 56): false] access to local variable s | +| Assert.cs:59:28:59:31 | [b (line 56): true] null | Assert.cs:59:23:59:23 | [b (line 56): true] access to local variable s | | Assert.cs:60:9:60:35 | call to method WriteLine | Assert.cs:60:27:60:34 | access to property Length | -| Assert.cs:60:9:60:36 | ...; | Assert.cs:59:9:59:37 | call to method IsTrue | +| Assert.cs:60:9:60:36 | ...; | Assert.cs:59:9:59:37 | [assertion success] call to method IsTrue | | Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:60:9:60:36 | ...; | | Assert.cs:60:27:60:34 | access to property Length | Assert.cs:60:27:60:27 | access to local variable s | +| Assert.cs:63:10:63:11 | exit M9 | Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | | Assert.cs:63:10:63:11 | exit M9 | Assert.cs:67:9:67:35 | call to method WriteLine | | Assert.cs:64:5:68:5 | {...} | Assert.cs:63:10:63:11 | enter M9 | | Assert.cs:65:9:65:33 | ... ...; | Assert.cs:64:5:68:5 | {...} | -| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:65:24:65:27 | null | -| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:65:31:65:32 | "" | +| Assert.cs:65:16:65:32 | [b (line 63): false] String s = ... | Assert.cs:65:31:65:32 | [b (line 63): false] "" | +| Assert.cs:65:16:65:32 | [b (line 63): true] String s = ... | Assert.cs:65:24:65:27 | [b (line 63): true] null | | Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:20:65:32 | ... ? ... : ... | | Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:65:9:65:33 | ... ...; | -| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:66:24:66:32 | ... == ... | -| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:66:37:66:37 | access to parameter b | -| Assert.cs:66:9:66:39 | ...; | Assert.cs:65:16:65:32 | String s = ... | -| Assert.cs:66:24:66:24 | access to local variable s | Assert.cs:66:24:66:37 | ... \|\| ... | -| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:29:66:32 | null | -| Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:66:9:66:39 | ...; | -| Assert.cs:66:29:66:32 | null | Assert.cs:66:24:66:24 | access to local variable s | +| Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | Assert.cs:66:24:66:32 | [b (line 63): true] ... == ... | +| Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | +| Assert.cs:66:9:66:38 | [assertion success] call to method IsFalse | Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | +| Assert.cs:66:9:66:39 | [b (line 63): false] ...; | Assert.cs:65:16:65:32 | [b (line 63): false] String s = ... | +| Assert.cs:66:9:66:39 | [b (line 63): true] ...; | Assert.cs:65:16:65:32 | [b (line 63): true] String s = ... | +| Assert.cs:66:24:66:24 | [b (line 63): false] access to local variable s | Assert.cs:66:24:66:37 | [b (line 63): false] ... \|\| ... | +| Assert.cs:66:24:66:24 | [b (line 63): true] access to local variable s | Assert.cs:66:24:66:37 | [b (line 63): true] ... \|\| ... | +| Assert.cs:66:24:66:32 | [b (line 63): false] ... == ... | Assert.cs:66:29:66:32 | [b (line 63): false] null | +| Assert.cs:66:24:66:32 | [b (line 63): true] ... == ... | Assert.cs:66:29:66:32 | [b (line 63): true] null | +| Assert.cs:66:24:66:37 | [b (line 63): false] ... \|\| ... | Assert.cs:66:9:66:39 | [b (line 63): false] ...; | +| Assert.cs:66:24:66:37 | [b (line 63): true] ... \|\| ... | Assert.cs:66:9:66:39 | [b (line 63): true] ...; | +| Assert.cs:66:29:66:32 | [b (line 63): false] null | Assert.cs:66:24:66:24 | [b (line 63): false] access to local variable s | +| Assert.cs:66:29:66:32 | [b (line 63): true] null | Assert.cs:66:24:66:24 | [b (line 63): true] access to local variable s | | Assert.cs:67:9:67:35 | call to method WriteLine | Assert.cs:67:27:67:34 | access to property Length | -| Assert.cs:67:9:67:36 | ...; | Assert.cs:66:9:66:38 | call to method IsFalse | +| Assert.cs:67:9:67:36 | ...; | Assert.cs:66:9:66:38 | [assertion success] call to method IsFalse | | Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:67:9:67:36 | ...; | | Assert.cs:67:27:67:34 | access to property Length | Assert.cs:67:27:67:27 | access to local variable s | +| Assert.cs:70:10:70:12 | exit M10 | Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | | Assert.cs:70:10:70:12 | exit M10 | Assert.cs:74:9:74:35 | call to method WriteLine | | Assert.cs:71:5:75:5 | {...} | Assert.cs:70:10:70:12 | enter M10 | | Assert.cs:72:9:72:33 | ... ...; | Assert.cs:71:5:75:5 | {...} | -| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:72:24:72:27 | null | -| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:72:31:72:32 | "" | +| Assert.cs:72:16:72:32 | [b (line 70): false] String s = ... | Assert.cs:72:31:72:32 | [b (line 70): false] "" | +| Assert.cs:72:16:72:32 | [b (line 70): true] String s = ... | Assert.cs:72:24:72:27 | [b (line 70): true] null | | Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:20:72:32 | ... ? ... : ... | | Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:72:9:72:33 | ... ...; | -| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:73:23:73:31 | ... == ... | -| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:73:36:73:36 | access to parameter b | -| Assert.cs:73:9:73:38 | ...; | Assert.cs:72:16:72:32 | String s = ... | -| Assert.cs:73:23:73:23 | access to local variable s | Assert.cs:73:23:73:36 | ... && ... | -| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:28:73:31 | null | -| Assert.cs:73:23:73:36 | ... && ... | Assert.cs:73:9:73:38 | ...; | -| Assert.cs:73:28:73:31 | null | Assert.cs:73:23:73:23 | access to local variable s | +| Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | Assert.cs:73:23:73:31 | [b (line 70): false] ... == ... | +| Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | +| Assert.cs:73:9:73:37 | [assertion success] call to method IsTrue | Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | +| Assert.cs:73:9:73:38 | [b (line 70): false] ...; | Assert.cs:72:16:72:32 | [b (line 70): false] String s = ... | +| Assert.cs:73:9:73:38 | [b (line 70): true] ...; | Assert.cs:72:16:72:32 | [b (line 70): true] String s = ... | +| Assert.cs:73:23:73:23 | [b (line 70): false] access to local variable s | Assert.cs:73:23:73:36 | [b (line 70): false] ... && ... | +| Assert.cs:73:23:73:23 | [b (line 70): true] access to local variable s | Assert.cs:73:23:73:36 | [b (line 70): true] ... && ... | +| Assert.cs:73:23:73:31 | [b (line 70): false] ... == ... | Assert.cs:73:28:73:31 | [b (line 70): false] null | +| Assert.cs:73:23:73:31 | [b (line 70): true] ... == ... | Assert.cs:73:28:73:31 | [b (line 70): true] null | +| Assert.cs:73:23:73:36 | [b (line 70): false] ... && ... | Assert.cs:73:9:73:38 | [b (line 70): false] ...; | +| Assert.cs:73:23:73:36 | [b (line 70): true] ... && ... | Assert.cs:73:9:73:38 | [b (line 70): true] ...; | +| Assert.cs:73:28:73:31 | [b (line 70): false] null | Assert.cs:73:23:73:23 | [b (line 70): false] access to local variable s | +| Assert.cs:73:28:73:31 | [b (line 70): true] null | Assert.cs:73:23:73:23 | [b (line 70): true] access to local variable s | | Assert.cs:74:9:74:35 | call to method WriteLine | Assert.cs:74:27:74:34 | access to property Length | -| Assert.cs:74:9:74:36 | ...; | Assert.cs:73:9:73:37 | call to method IsTrue | +| Assert.cs:74:9:74:36 | ...; | Assert.cs:73:9:73:37 | [assertion success] call to method IsTrue | | Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:74:9:74:36 | ...; | | Assert.cs:74:27:74:34 | access to property Length | Assert.cs:74:27:74:27 | access to local variable s | +| Assert.cs:77:10:77:12 | exit M11 | Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | | Assert.cs:77:10:77:12 | exit M11 | Assert.cs:81:9:81:35 | call to method WriteLine | | Assert.cs:78:5:82:5 | {...} | Assert.cs:77:10:77:12 | enter M11 | | Assert.cs:79:9:79:33 | ... ...; | Assert.cs:78:5:82:5 | {...} | -| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:79:24:79:27 | null | -| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:79:31:79:32 | "" | +| Assert.cs:79:16:79:32 | [b (line 77): false] String s = ... | Assert.cs:79:31:79:32 | [b (line 77): false] "" | +| Assert.cs:79:16:79:32 | [b (line 77): true] String s = ... | Assert.cs:79:24:79:27 | [b (line 77): true] null | | Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:32 | ... ? ... : ... | | Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:79:9:79:33 | ... ...; | -| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:80:24:80:32 | ... != ... | -| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:80:37:80:37 | access to parameter b | -| Assert.cs:80:9:80:39 | ...; | Assert.cs:79:16:79:32 | String s = ... | -| Assert.cs:80:24:80:24 | access to local variable s | Assert.cs:80:24:80:37 | ... \|\| ... | -| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:29:80:32 | null | -| Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:9:80:39 | ...; | -| Assert.cs:80:29:80:32 | null | Assert.cs:80:24:80:24 | access to local variable s | +| Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | Assert.cs:80:24:80:32 | [b (line 77): true] ... != ... | +| Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | +| Assert.cs:80:9:80:38 | [assertion success] call to method IsFalse | Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | +| Assert.cs:80:9:80:39 | [b (line 77): false] ...; | Assert.cs:79:16:79:32 | [b (line 77): false] String s = ... | +| Assert.cs:80:9:80:39 | [b (line 77): true] ...; | Assert.cs:79:16:79:32 | [b (line 77): true] String s = ... | +| Assert.cs:80:24:80:24 | [b (line 77): false] access to local variable s | Assert.cs:80:24:80:37 | [b (line 77): false] ... \|\| ... | +| Assert.cs:80:24:80:24 | [b (line 77): true] access to local variable s | Assert.cs:80:24:80:37 | [b (line 77): true] ... \|\| ... | +| Assert.cs:80:24:80:32 | [b (line 77): false] ... != ... | Assert.cs:80:29:80:32 | [b (line 77): false] null | +| Assert.cs:80:24:80:32 | [b (line 77): true] ... != ... | Assert.cs:80:29:80:32 | [b (line 77): true] null | +| Assert.cs:80:24:80:37 | [b (line 77): false] ... \|\| ... | Assert.cs:80:9:80:39 | [b (line 77): false] ...; | +| Assert.cs:80:24:80:37 | [b (line 77): true] ... \|\| ... | Assert.cs:80:9:80:39 | [b (line 77): true] ...; | +| Assert.cs:80:29:80:32 | [b (line 77): false] null | Assert.cs:80:24:80:24 | [b (line 77): false] access to local variable s | +| Assert.cs:80:29:80:32 | [b (line 77): true] null | Assert.cs:80:24:80:24 | [b (line 77): true] access to local variable s | | Assert.cs:81:9:81:35 | call to method WriteLine | Assert.cs:81:27:81:34 | access to property Length | -| Assert.cs:81:9:81:36 | ...; | Assert.cs:80:9:80:38 | call to method IsFalse | +| Assert.cs:81:9:81:36 | ...; | Assert.cs:80:9:80:38 | [assertion success] call to method IsFalse | | Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:81:9:81:36 | ...; | | Assert.cs:81:27:81:34 | access to property Length | Assert.cs:81:27:81:27 | access to local variable s | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | | Assert.cs:84:10:84:12 | exit M12 | Assert.cs:128:9:128:35 | call to method WriteLine | | Assert.cs:85:5:129:5 | {...} | Assert.cs:84:10:84:12 | enter M12 | | Assert.cs:86:9:86:33 | ... ...; | Assert.cs:85:5:129:5 | {...} | @@ -4188,8 +4240,6 @@ postDominance | Assert.cs:86:16:86:32 | [b (line 84): true] String s = ... | Assert.cs:86:24:86:27 | [b (line 84): true] null | | Assert.cs:86:20:86:20 | access to parameter b | Assert.cs:86:20:86:32 | ... ? ... : ... | | Assert.cs:86:20:86:32 | ... ? ... : ... | Assert.cs:86:9:86:33 | ... ...; | -| Assert.cs:87:9:87:31 | [b (line 84): false] call to method Assert | Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | -| Assert.cs:87:9:87:31 | [b (line 84): true] call to method Assert | Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | | Assert.cs:87:9:87:32 | [b (line 84): false] ...; | Assert.cs:86:16:86:32 | [b (line 84): false] String s = ... | | Assert.cs:87:9:87:32 | [b (line 84): true] ...; | Assert.cs:86:16:86:32 | [b (line 84): true] String s = ... | | Assert.cs:87:22:87:22 | [b (line 84): false] access to local variable s | Assert.cs:87:9:87:32 | [b (line 84): false] ...; | @@ -4200,8 +4250,8 @@ postDominance | Assert.cs:87:27:87:30 | [b (line 84): true] null | Assert.cs:87:22:87:22 | [b (line 84): true] access to local variable s | | Assert.cs:88:9:88:35 | [b (line 84): false] call to method WriteLine | Assert.cs:88:27:88:34 | [b (line 84): false] access to property Length | | Assert.cs:88:9:88:35 | [b (line 84): true] call to method WriteLine | Assert.cs:88:27:88:34 | [b (line 84): true] access to property Length | -| Assert.cs:88:9:88:36 | [b (line 84): false] ...; | Assert.cs:87:9:87:31 | [b (line 84): false] call to method Assert | -| Assert.cs:88:9:88:36 | [b (line 84): true] ...; | Assert.cs:87:9:87:31 | [b (line 84): true] call to method Assert | +| Assert.cs:88:9:88:36 | [b (line 84): false] ...; | Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | +| Assert.cs:88:9:88:36 | [b (line 84): true] ...; | Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | | Assert.cs:88:27:88:27 | [b (line 84): false] access to local variable s | Assert.cs:88:9:88:36 | [b (line 84): false] ...; | | Assert.cs:88:27:88:27 | [b (line 84): true] access to local variable s | Assert.cs:88:9:88:36 | [b (line 84): true] ...; | | Assert.cs:88:27:88:34 | [b (line 84): false] access to property Length | Assert.cs:88:27:88:27 | [b (line 84): false] access to local variable s | @@ -4216,16 +4266,14 @@ postDominance | Assert.cs:90:13:90:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:90:9:90:26 | [b (line 84): true] ...; | | Assert.cs:90:17:90:20 | [b (line 84): true] null | Assert.cs:90:13:90:13 | [b (line 84): true] access to parameter b | | Assert.cs:90:24:90:25 | [b (line 84): false] "" | Assert.cs:90:13:90:13 | [b (line 84): false] access to parameter b | -| Assert.cs:91:9:91:24 | [b (line 84): false] call to method IsNull | Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | -| Assert.cs:91:9:91:24 | [b (line 84): true] call to method IsNull | Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | | Assert.cs:91:9:91:25 | [b (line 84): false] ...; | Assert.cs:90:9:90:25 | [b (line 84): false] ... = ... | | Assert.cs:91:9:91:25 | [b (line 84): true] ...; | Assert.cs:90:9:90:25 | [b (line 84): true] ... = ... | | Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | Assert.cs:91:9:91:25 | [b (line 84): false] ...; | | Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | Assert.cs:91:9:91:25 | [b (line 84): true] ...; | | Assert.cs:92:9:92:35 | [b (line 84): false] call to method WriteLine | Assert.cs:92:27:92:34 | [b (line 84): false] access to property Length | | Assert.cs:92:9:92:35 | [b (line 84): true] call to method WriteLine | Assert.cs:92:27:92:34 | [b (line 84): true] access to property Length | -| Assert.cs:92:9:92:36 | [b (line 84): false] ...; | Assert.cs:91:9:91:24 | [b (line 84): false] call to method IsNull | -| Assert.cs:92:9:92:36 | [b (line 84): true] ...; | Assert.cs:91:9:91:24 | [b (line 84): true] call to method IsNull | +| Assert.cs:92:9:92:36 | [b (line 84): false] ...; | Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | +| Assert.cs:92:9:92:36 | [b (line 84): true] ...; | Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | | Assert.cs:92:27:92:27 | [b (line 84): false] access to local variable s | Assert.cs:92:9:92:36 | [b (line 84): false] ...; | | Assert.cs:92:27:92:27 | [b (line 84): true] access to local variable s | Assert.cs:92:9:92:36 | [b (line 84): true] ...; | | Assert.cs:92:27:92:34 | [b (line 84): false] access to property Length | Assert.cs:92:27:92:27 | [b (line 84): false] access to local variable s | @@ -4240,16 +4288,14 @@ postDominance | Assert.cs:94:13:94:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:94:9:94:26 | [b (line 84): true] ...; | | Assert.cs:94:17:94:20 | [b (line 84): true] null | Assert.cs:94:13:94:13 | [b (line 84): true] access to parameter b | | Assert.cs:94:24:94:25 | [b (line 84): false] "" | Assert.cs:94:13:94:13 | [b (line 84): false] access to parameter b | -| Assert.cs:95:9:95:27 | [b (line 84): false] call to method IsNotNull | Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | -| Assert.cs:95:9:95:27 | [b (line 84): true] call to method IsNotNull | Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | | Assert.cs:95:9:95:28 | [b (line 84): false] ...; | Assert.cs:94:9:94:25 | [b (line 84): false] ... = ... | | Assert.cs:95:9:95:28 | [b (line 84): true] ...; | Assert.cs:94:9:94:25 | [b (line 84): true] ... = ... | | Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | Assert.cs:95:9:95:28 | [b (line 84): false] ...; | | Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | Assert.cs:95:9:95:28 | [b (line 84): true] ...; | | Assert.cs:96:9:96:35 | [b (line 84): false] call to method WriteLine | Assert.cs:96:27:96:34 | [b (line 84): false] access to property Length | | Assert.cs:96:9:96:35 | [b (line 84): true] call to method WriteLine | Assert.cs:96:27:96:34 | [b (line 84): true] access to property Length | -| Assert.cs:96:9:96:36 | [b (line 84): false] ...; | Assert.cs:95:9:95:27 | [b (line 84): false] call to method IsNotNull | -| Assert.cs:96:9:96:36 | [b (line 84): true] ...; | Assert.cs:95:9:95:27 | [b (line 84): true] call to method IsNotNull | +| Assert.cs:96:9:96:36 | [b (line 84): false] ...; | Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | +| Assert.cs:96:9:96:36 | [b (line 84): true] ...; | Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | | Assert.cs:96:27:96:27 | [b (line 84): false] access to local variable s | Assert.cs:96:9:96:36 | [b (line 84): false] ...; | | Assert.cs:96:27:96:27 | [b (line 84): true] access to local variable s | Assert.cs:96:9:96:36 | [b (line 84): true] ...; | | Assert.cs:96:27:96:34 | [b (line 84): false] access to property Length | Assert.cs:96:27:96:27 | [b (line 84): false] access to local variable s | @@ -4264,8 +4310,6 @@ postDominance | Assert.cs:98:13:98:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:98:9:98:26 | [b (line 84): true] ...; | | Assert.cs:98:17:98:20 | [b (line 84): true] null | Assert.cs:98:13:98:13 | [b (line 84): true] access to parameter b | | Assert.cs:98:24:98:25 | [b (line 84): false] "" | Assert.cs:98:13:98:13 | [b (line 84): false] access to parameter b | -| Assert.cs:99:9:99:32 | [b (line 84): false] call to method IsTrue | Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | -| Assert.cs:99:9:99:32 | [b (line 84): true] call to method IsTrue | Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | | Assert.cs:99:9:99:33 | [b (line 84): false] ...; | Assert.cs:98:9:98:25 | [b (line 84): false] ... = ... | | Assert.cs:99:9:99:33 | [b (line 84): true] ...; | Assert.cs:98:9:98:25 | [b (line 84): true] ... = ... | | Assert.cs:99:23:99:23 | [b (line 84): false] access to local variable s | Assert.cs:99:9:99:33 | [b (line 84): false] ...; | @@ -4276,8 +4320,8 @@ postDominance | Assert.cs:99:28:99:31 | [b (line 84): true] null | Assert.cs:99:23:99:23 | [b (line 84): true] access to local variable s | | Assert.cs:100:9:100:35 | [b (line 84): false] call to method WriteLine | Assert.cs:100:27:100:34 | [b (line 84): false] access to property Length | | Assert.cs:100:9:100:35 | [b (line 84): true] call to method WriteLine | Assert.cs:100:27:100:34 | [b (line 84): true] access to property Length | -| Assert.cs:100:9:100:36 | [b (line 84): false] ...; | Assert.cs:99:9:99:32 | [b (line 84): false] call to method IsTrue | -| Assert.cs:100:9:100:36 | [b (line 84): true] ...; | Assert.cs:99:9:99:32 | [b (line 84): true] call to method IsTrue | +| Assert.cs:100:9:100:36 | [b (line 84): false] ...; | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:100:9:100:36 | [b (line 84): true] ...; | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | | Assert.cs:100:27:100:27 | [b (line 84): false] access to local variable s | Assert.cs:100:9:100:36 | [b (line 84): false] ...; | | Assert.cs:100:27:100:27 | [b (line 84): true] access to local variable s | Assert.cs:100:9:100:36 | [b (line 84): true] ...; | | Assert.cs:100:27:100:34 | [b (line 84): false] access to property Length | Assert.cs:100:27:100:27 | [b (line 84): false] access to local variable s | @@ -4292,8 +4336,6 @@ postDominance | Assert.cs:102:13:102:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:102:9:102:26 | [b (line 84): true] ...; | | Assert.cs:102:17:102:20 | [b (line 84): true] null | Assert.cs:102:13:102:13 | [b (line 84): true] access to parameter b | | Assert.cs:102:24:102:25 | [b (line 84): false] "" | Assert.cs:102:13:102:13 | [b (line 84): false] access to parameter b | -| Assert.cs:103:9:103:32 | [b (line 84): false] call to method IsTrue | Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | -| Assert.cs:103:9:103:32 | [b (line 84): true] call to method IsTrue | Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | | Assert.cs:103:9:103:33 | [b (line 84): false] ...; | Assert.cs:102:9:102:25 | [b (line 84): false] ... = ... | | Assert.cs:103:9:103:33 | [b (line 84): true] ...; | Assert.cs:102:9:102:25 | [b (line 84): true] ... = ... | | Assert.cs:103:23:103:23 | [b (line 84): false] access to local variable s | Assert.cs:103:9:103:33 | [b (line 84): false] ...; | @@ -4304,8 +4346,8 @@ postDominance | Assert.cs:103:28:103:31 | [b (line 84): true] null | Assert.cs:103:23:103:23 | [b (line 84): true] access to local variable s | | Assert.cs:104:9:104:35 | [b (line 84): false] call to method WriteLine | Assert.cs:104:27:104:34 | [b (line 84): false] access to property Length | | Assert.cs:104:9:104:35 | [b (line 84): true] call to method WriteLine | Assert.cs:104:27:104:34 | [b (line 84): true] access to property Length | -| Assert.cs:104:9:104:36 | [b (line 84): false] ...; | Assert.cs:103:9:103:32 | [b (line 84): false] call to method IsTrue | -| Assert.cs:104:9:104:36 | [b (line 84): true] ...; | Assert.cs:103:9:103:32 | [b (line 84): true] call to method IsTrue | +| Assert.cs:104:9:104:36 | [b (line 84): false] ...; | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:104:9:104:36 | [b (line 84): true] ...; | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | | Assert.cs:104:27:104:27 | [b (line 84): false] access to local variable s | Assert.cs:104:9:104:36 | [b (line 84): false] ...; | | Assert.cs:104:27:104:27 | [b (line 84): true] access to local variable s | Assert.cs:104:9:104:36 | [b (line 84): true] ...; | | Assert.cs:104:27:104:34 | [b (line 84): false] access to property Length | Assert.cs:104:27:104:27 | [b (line 84): false] access to local variable s | @@ -4320,8 +4362,6 @@ postDominance | Assert.cs:106:13:106:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:106:9:106:26 | [b (line 84): true] ...; | | Assert.cs:106:17:106:20 | [b (line 84): true] null | Assert.cs:106:13:106:13 | [b (line 84): true] access to parameter b | | Assert.cs:106:24:106:25 | [b (line 84): false] "" | Assert.cs:106:13:106:13 | [b (line 84): false] access to parameter b | -| Assert.cs:107:9:107:33 | [b (line 84): false] call to method IsFalse | Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | -| Assert.cs:107:9:107:33 | [b (line 84): true] call to method IsFalse | Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | | Assert.cs:107:9:107:34 | [b (line 84): false] ...; | Assert.cs:106:9:106:25 | [b (line 84): false] ... = ... | | Assert.cs:107:9:107:34 | [b (line 84): true] ...; | Assert.cs:106:9:106:25 | [b (line 84): true] ... = ... | | Assert.cs:107:24:107:24 | [b (line 84): false] access to local variable s | Assert.cs:107:9:107:34 | [b (line 84): false] ...; | @@ -4332,8 +4372,8 @@ postDominance | Assert.cs:107:29:107:32 | [b (line 84): true] null | Assert.cs:107:24:107:24 | [b (line 84): true] access to local variable s | | Assert.cs:108:9:108:35 | [b (line 84): false] call to method WriteLine | Assert.cs:108:27:108:34 | [b (line 84): false] access to property Length | | Assert.cs:108:9:108:35 | [b (line 84): true] call to method WriteLine | Assert.cs:108:27:108:34 | [b (line 84): true] access to property Length | -| Assert.cs:108:9:108:36 | [b (line 84): false] ...; | Assert.cs:107:9:107:33 | [b (line 84): false] call to method IsFalse | -| Assert.cs:108:9:108:36 | [b (line 84): true] ...; | Assert.cs:107:9:107:33 | [b (line 84): true] call to method IsFalse | +| Assert.cs:108:9:108:36 | [b (line 84): false] ...; | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:108:9:108:36 | [b (line 84): true] ...; | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | | Assert.cs:108:27:108:27 | [b (line 84): false] access to local variable s | Assert.cs:108:9:108:36 | [b (line 84): false] ...; | | Assert.cs:108:27:108:27 | [b (line 84): true] access to local variable s | Assert.cs:108:9:108:36 | [b (line 84): true] ...; | | Assert.cs:108:27:108:34 | [b (line 84): false] access to property Length | Assert.cs:108:27:108:27 | [b (line 84): false] access to local variable s | @@ -4348,8 +4388,6 @@ postDominance | Assert.cs:110:13:110:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:110:9:110:26 | [b (line 84): true] ...; | | Assert.cs:110:17:110:20 | [b (line 84): true] null | Assert.cs:110:13:110:13 | [b (line 84): true] access to parameter b | | Assert.cs:110:24:110:25 | [b (line 84): false] "" | Assert.cs:110:13:110:13 | [b (line 84): false] access to parameter b | -| Assert.cs:111:9:111:33 | [b (line 84): false] call to method IsFalse | Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | -| Assert.cs:111:9:111:33 | [b (line 84): true] call to method IsFalse | Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | | Assert.cs:111:9:111:34 | [b (line 84): false] ...; | Assert.cs:110:9:110:25 | [b (line 84): false] ... = ... | | Assert.cs:111:9:111:34 | [b (line 84): true] ...; | Assert.cs:110:9:110:25 | [b (line 84): true] ... = ... | | Assert.cs:111:24:111:24 | [b (line 84): false] access to local variable s | Assert.cs:111:9:111:34 | [b (line 84): false] ...; | @@ -4360,8 +4398,8 @@ postDominance | Assert.cs:111:29:111:32 | [b (line 84): true] null | Assert.cs:111:24:111:24 | [b (line 84): true] access to local variable s | | Assert.cs:112:9:112:35 | [b (line 84): false] call to method WriteLine | Assert.cs:112:27:112:34 | [b (line 84): false] access to property Length | | Assert.cs:112:9:112:35 | [b (line 84): true] call to method WriteLine | Assert.cs:112:27:112:34 | [b (line 84): true] access to property Length | -| Assert.cs:112:9:112:36 | [b (line 84): false] ...; | Assert.cs:111:9:111:33 | [b (line 84): false] call to method IsFalse | -| Assert.cs:112:9:112:36 | [b (line 84): true] ...; | Assert.cs:111:9:111:33 | [b (line 84): true] call to method IsFalse | +| Assert.cs:112:9:112:36 | [b (line 84): false] ...; | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:112:9:112:36 | [b (line 84): true] ...; | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | | Assert.cs:112:27:112:27 | [b (line 84): false] access to local variable s | Assert.cs:112:9:112:36 | [b (line 84): false] ...; | | Assert.cs:112:27:112:27 | [b (line 84): true] access to local variable s | Assert.cs:112:9:112:36 | [b (line 84): true] ...; | | Assert.cs:112:27:112:34 | [b (line 84): false] access to property Length | Assert.cs:112:27:112:27 | [b (line 84): false] access to local variable s | @@ -4376,10 +4414,9 @@ postDominance | Assert.cs:114:13:114:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:114:9:114:26 | [b (line 84): true] ...; | | Assert.cs:114:17:114:20 | [b (line 84): true] null | Assert.cs:114:13:114:13 | [b (line 84): true] access to parameter b | | Assert.cs:114:24:114:25 | [b (line 84): false] "" | Assert.cs:114:13:114:13 | [b (line 84): false] access to parameter b | -| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | -| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | -| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | -| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:115:9:115:37 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | | Assert.cs:115:9:115:38 | [b (line 84): false] ...; | Assert.cs:114:9:114:25 | [b (line 84): false] ... = ... | | Assert.cs:115:9:115:38 | [b (line 84): true] ...; | Assert.cs:114:9:114:25 | [b (line 84): true] ... = ... | | Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | Assert.cs:115:23:115:36 | [b (line 84): false] ... && ... | @@ -4390,100 +4427,55 @@ postDominance | Assert.cs:115:23:115:36 | [b (line 84): true] ... && ... | Assert.cs:115:9:115:38 | [b (line 84): true] ...; | | Assert.cs:115:28:115:31 | [b (line 84): false] null | Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | | Assert.cs:115:28:115:31 | [b (line 84): true] null | Assert.cs:115:23:115:23 | [b (line 84): true] access to local variable s | -| Assert.cs:116:9:116:35 | [b (line 84): false] call to method WriteLine | Assert.cs:116:27:116:34 | [b (line 84): false] access to property Length | | Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | -| Assert.cs:116:9:116:36 | [b (line 84): false] ...; | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:116:9:116:36 | [b (line 84): true] ...; | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | -| Assert.cs:116:27:116:27 | [b (line 84): false] access to local variable s | Assert.cs:116:9:116:36 | [b (line 84): false] ...; | +| Assert.cs:116:9:116:36 | [b (line 84): true] ...; | Assert.cs:115:9:115:37 | [assertion success, b (line 84): true] call to method IsTrue | | Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | Assert.cs:116:9:116:36 | [b (line 84): true] ...; | -| Assert.cs:116:27:116:34 | [b (line 84): false] access to property Length | Assert.cs:116:27:116:27 | [b (line 84): false] access to local variable s | | Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | -| Assert.cs:118:9:118:25 | [b (line 84): false] ... = ... | Assert.cs:118:24:118:25 | [b (line 84): false] "" | | Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | Assert.cs:118:17:118:20 | [b (line 84): true] null | -| Assert.cs:118:9:118:26 | [b (line 84): false] ...; | Assert.cs:116:9:116:35 | [b (line 84): false] call to method WriteLine | | Assert.cs:118:9:118:26 | [b (line 84): true] ...; | Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | -| Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | Assert.cs:118:13:118:25 | [b (line 84): false] ... ? ... : ... | | Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | -| Assert.cs:118:13:118:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:118:9:118:26 | [b (line 84): false] ...; | | Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:118:9:118:26 | [b (line 84): true] ...; | | Assert.cs:118:17:118:20 | [b (line 84): true] null | Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | -| Assert.cs:118:24:118:25 | [b (line 84): false] "" | Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | -| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | -| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:119:38:119:38 | [b (line 84): false] access to parameter b | -| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | -| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | -| Assert.cs:119:9:119:40 | [b (line 84): false] ...; | Assert.cs:118:9:118:25 | [b (line 84): false] ... = ... | +| Assert.cs:119:9:119:39 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | | Assert.cs:119:9:119:40 | [b (line 84): true] ...; | Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | -| Assert.cs:119:24:119:24 | [b (line 84): false] access to local variable s | Assert.cs:119:24:119:38 | [b (line 84): false] ... \|\| ... | | Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | Assert.cs:119:24:119:38 | [b (line 84): true] ... \|\| ... | -| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | Assert.cs:119:29:119:32 | [b (line 84): false] null | | Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:29:119:32 | [b (line 84): true] null | -| Assert.cs:119:24:119:38 | [b (line 84): false] ... \|\| ... | Assert.cs:119:9:119:40 | [b (line 84): false] ...; | | Assert.cs:119:24:119:38 | [b (line 84): true] ... \|\| ... | Assert.cs:119:9:119:40 | [b (line 84): true] ...; | -| Assert.cs:119:29:119:32 | [b (line 84): false] null | Assert.cs:119:24:119:24 | [b (line 84): false] access to local variable s | | Assert.cs:119:29:119:32 | [b (line 84): true] null | Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | -| Assert.cs:119:38:119:38 | [b (line 84): false] access to parameter b | Assert.cs:119:37:119:38 | [b (line 84): false] !... | | Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | Assert.cs:119:37:119:38 | [b (line 84): true] !... | -| Assert.cs:120:9:120:35 | [b (line 84): false] call to method WriteLine | Assert.cs:120:27:120:34 | [b (line 84): false] access to property Length | | Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | -| Assert.cs:120:9:120:36 | [b (line 84): false] ...; | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | -| Assert.cs:120:9:120:36 | [b (line 84): true] ...; | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | -| Assert.cs:120:27:120:27 | [b (line 84): false] access to local variable s | Assert.cs:120:9:120:36 | [b (line 84): false] ...; | +| Assert.cs:120:9:120:36 | [b (line 84): true] ...; | Assert.cs:119:9:119:39 | [assertion success, b (line 84): true] call to method IsFalse | | Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | Assert.cs:120:9:120:36 | [b (line 84): true] ...; | -| Assert.cs:120:27:120:34 | [b (line 84): false] access to property Length | Assert.cs:120:27:120:27 | [b (line 84): false] access to local variable s | | Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | -| Assert.cs:122:9:122:25 | [b (line 84): false] ... = ... | Assert.cs:122:24:122:25 | [b (line 84): false] "" | | Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | Assert.cs:122:17:122:20 | [b (line 84): true] null | -| Assert.cs:122:9:122:26 | [b (line 84): false] ...; | Assert.cs:120:9:120:35 | [b (line 84): false] call to method WriteLine | | Assert.cs:122:9:122:26 | [b (line 84): true] ...; | Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | -| Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | Assert.cs:122:13:122:25 | [b (line 84): false] ... ? ... : ... | | Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | -| Assert.cs:122:13:122:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:122:9:122:26 | [b (line 84): false] ...; | | Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:122:9:122:26 | [b (line 84): true] ...; | | Assert.cs:122:17:122:20 | [b (line 84): true] null | Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | -| Assert.cs:122:24:122:25 | [b (line 84): false] "" | Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | -| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | -| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | -| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | -| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | -| Assert.cs:123:9:123:38 | [b (line 84): false] ...; | Assert.cs:122:9:122:25 | [b (line 84): false] ... = ... | +| Assert.cs:123:9:123:37 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | | Assert.cs:123:9:123:38 | [b (line 84): true] ...; | Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | -| Assert.cs:123:23:123:23 | [b (line 84): false] access to local variable s | Assert.cs:123:23:123:36 | [b (line 84): false] ... && ... | | Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | Assert.cs:123:23:123:36 | [b (line 84): true] ... && ... | -| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | Assert.cs:123:28:123:31 | [b (line 84): false] null | | Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:28:123:31 | [b (line 84): true] null | -| Assert.cs:123:23:123:36 | [b (line 84): false] ... && ... | Assert.cs:123:9:123:38 | [b (line 84): false] ...; | | Assert.cs:123:23:123:36 | [b (line 84): true] ... && ... | Assert.cs:123:9:123:38 | [b (line 84): true] ...; | -| Assert.cs:123:28:123:31 | [b (line 84): false] null | Assert.cs:123:23:123:23 | [b (line 84): false] access to local variable s | | Assert.cs:123:28:123:31 | [b (line 84): true] null | Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | -| Assert.cs:124:9:124:35 | [b (line 84): false] call to method WriteLine | Assert.cs:124:27:124:34 | [b (line 84): false] access to property Length | | Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | -| Assert.cs:124:9:124:36 | [b (line 84): false] ...; | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:124:9:124:36 | [b (line 84): true] ...; | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | -| Assert.cs:124:27:124:27 | [b (line 84): false] access to local variable s | Assert.cs:124:9:124:36 | [b (line 84): false] ...; | +| Assert.cs:124:9:124:36 | [b (line 84): true] ...; | Assert.cs:123:9:123:37 | [assertion success, b (line 84): true] call to method IsTrue | | Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | Assert.cs:124:9:124:36 | [b (line 84): true] ...; | -| Assert.cs:124:27:124:34 | [b (line 84): false] access to property Length | Assert.cs:124:27:124:27 | [b (line 84): false] access to local variable s | | Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:126:17:126:20 | null | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:126:24:126:25 | "" | -| Assert.cs:126:9:126:26 | [b (line 84): false] ...; | Assert.cs:124:9:124:35 | [b (line 84): false] call to method WriteLine | +| Assert.cs:126:9:126:25 | [b (line 84): true] ... = ... | Assert.cs:126:17:126:20 | [b (line 84): true] null | | Assert.cs:126:9:126:26 | [b (line 84): true] ...; | Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | -| Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | Assert.cs:126:13:126:25 | [b (line 84): false] ... ? ... : ... | | Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | -| Assert.cs:126:13:126:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:126:9:126:26 | [b (line 84): false] ...; | | Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:126:9:126:26 | [b (line 84): true] ...; | -| Assert.cs:126:17:126:20 | null | Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | -| Assert.cs:126:24:126:25 | "" | Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:127:24:127:32 | ... != ... | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:127:38:127:38 | access to parameter b | -| Assert.cs:127:9:127:40 | ...; | Assert.cs:126:9:126:25 | ... = ... | -| Assert.cs:127:24:127:24 | access to local variable s | Assert.cs:127:24:127:38 | ... \|\| ... | -| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:29:127:32 | null | -| Assert.cs:127:24:127:38 | ... \|\| ... | Assert.cs:127:9:127:40 | ...; | -| Assert.cs:127:29:127:32 | null | Assert.cs:127:24:127:24 | access to local variable s | -| Assert.cs:127:38:127:38 | access to parameter b | Assert.cs:127:37:127:38 | !... | +| Assert.cs:126:17:126:20 | [b (line 84): true] null | Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | +| Assert.cs:127:9:127:39 | [assertion success] call to method IsFalse | Assert.cs:127:38:127:38 | [b (line 84): true] access to parameter b | +| Assert.cs:127:9:127:40 | [b (line 84): true] ...; | Assert.cs:126:9:126:25 | [b (line 84): true] ... = ... | +| Assert.cs:127:24:127:24 | [b (line 84): true] access to local variable s | Assert.cs:127:24:127:38 | [b (line 84): true] ... \|\| ... | +| Assert.cs:127:24:127:32 | [b (line 84): true] ... != ... | Assert.cs:127:29:127:32 | [b (line 84): true] null | +| Assert.cs:127:24:127:38 | [b (line 84): true] ... \|\| ... | Assert.cs:127:9:127:40 | [b (line 84): true] ...; | +| Assert.cs:127:29:127:32 | [b (line 84): true] null | Assert.cs:127:24:127:24 | [b (line 84): true] access to local variable s | +| Assert.cs:127:38:127:38 | [b (line 84): true] access to parameter b | Assert.cs:127:37:127:38 | [b (line 84): true] !... | | Assert.cs:128:9:128:35 | call to method WriteLine | Assert.cs:128:27:128:34 | access to property Length | -| Assert.cs:128:9:128:36 | ...; | Assert.cs:127:9:127:39 | call to method IsFalse | +| Assert.cs:128:9:128:36 | ...; | Assert.cs:127:9:127:39 | [assertion success] call to method IsFalse | | Assert.cs:128:27:128:27 | access to local variable s | Assert.cs:128:9:128:36 | ...; | | Assert.cs:128:27:128:34 | access to property Length | Assert.cs:128:27:128:27 | access to local variable s | | Assignments.cs:3:10:3:10 | exit M | Assignments.cs:14:9:14:35 | ... += ... | @@ -5156,9 +5148,9 @@ postDominance | ExitMethods.cs:116:16:116:30 | call to method Contains | ExitMethods.cs:116:27:116:29 | - | | ExitMethods.cs:116:16:116:38 | ... ? ... : ... | ExitMethods.cs:115:5:117:5 | {...} | | ExitMethods.cs:116:27:116:29 | - | ExitMethods.cs:116:16:116:16 | access to parameter s | -| ExitMethods.cs:119:17:119:32 | exit FailingAssertion | ExitMethods.cs:121:9:121:28 | call to method IsTrue | +| ExitMethods.cs:119:17:119:32 | exit FailingAssertion | ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | | ExitMethods.cs:120:5:123:5 | {...} | ExitMethods.cs:119:17:119:32 | enter FailingAssertion | -| ExitMethods.cs:121:9:121:28 | call to method IsTrue | ExitMethods.cs:121:23:121:27 | false | +| ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:121:23:121:27 | false | | ExitMethods.cs:121:9:121:29 | ...; | ExitMethods.cs:120:5:123:5 | {...} | | ExitMethods.cs:121:23:121:27 | false | ExitMethods.cs:121:9:121:29 | ...; | | ExitMethods.cs:125:17:125:33 | exit FailingAssertion2 | ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | @@ -5166,12 +5158,12 @@ postDominance | ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | ExitMethods.cs:127:9:127:26 | this access | | ExitMethods.cs:127:9:127:26 | this access | ExitMethods.cs:127:9:127:27 | ...; | | ExitMethods.cs:127:9:127:27 | ...; | ExitMethods.cs:126:5:129:5 | {...} | -| ExitMethods.cs:131:10:131:20 | exit AssertFalse | ExitMethods.cs:131:33:131:49 | call to method IsFalse | -| ExitMethods.cs:131:33:131:49 | call to method IsFalse | ExitMethods.cs:131:48:131:48 | access to parameter b | +| ExitMethods.cs:131:10:131:20 | exit AssertFalse | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | +| ExitMethods.cs:131:10:131:20 | exit AssertFalse | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | | ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:10:131:20 | enter AssertFalse | -| ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 | ExitMethods.cs:135:9:135:25 | call to method AssertFalse | +| ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 | ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | | ExitMethods.cs:134:5:137:5 | {...} | ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | -| ExitMethods.cs:135:9:135:25 | call to method AssertFalse | ExitMethods.cs:135:21:135:24 | true | +| ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:135:21:135:24 | true | | ExitMethods.cs:135:9:135:25 | this access | ExitMethods.cs:135:9:135:26 | ...; | | ExitMethods.cs:135:9:135:26 | ...; | ExitMethods.cs:134:5:137:5 | {...} | | ExitMethods.cs:135:21:135:24 | true | ExitMethods.cs:135:9:135:25 | this access | @@ -7324,167 +7316,464 @@ blockDominance | ArrayCreation.cs:7:11:7:12 | enter M3 | ArrayCreation.cs:7:11:7:12 | enter M3 | | ArrayCreation.cs:9:12:9:13 | enter M4 | ArrayCreation.cs:9:12:9:13 | enter M4 | | Assert.cs:7:10:7:11 | enter M1 | Assert.cs:7:10:7:11 | enter M1 | +| Assert.cs:7:10:7:11 | enter M1 | Assert.cs:7:10:7:11 | exit M1 | | Assert.cs:7:10:7:11 | enter M1 | Assert.cs:9:16:9:32 | String s = ... | | Assert.cs:7:10:7:11 | enter M1 | Assert.cs:9:24:9:27 | null | | Assert.cs:7:10:7:11 | enter M1 | Assert.cs:9:31:9:32 | "" | +| Assert.cs:7:10:7:11 | enter M1 | Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | +| Assert.cs:7:10:7:11 | enter M1 | Assert.cs:10:9:10:31 | [assertion success] call to method Assert | +| Assert.cs:7:10:7:11 | exit M1 | Assert.cs:7:10:7:11 | exit M1 | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:7:10:7:11 | exit M1 | | Assert.cs:9:16:9:32 | String s = ... | Assert.cs:9:16:9:32 | String s = ... | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | +| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:10:9:10:31 | [assertion success] call to method Assert | | Assert.cs:9:24:9:27 | null | Assert.cs:9:24:9:27 | null | | Assert.cs:9:31:9:32 | "" | Assert.cs:9:31:9:32 | "" | +| Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | +| Assert.cs:10:9:10:31 | [assertion success] call to method Assert | Assert.cs:10:9:10:31 | [assertion success] call to method Assert | | Assert.cs:14:10:14:11 | enter M2 | Assert.cs:14:10:14:11 | enter M2 | +| Assert.cs:14:10:14:11 | enter M2 | Assert.cs:14:10:14:11 | exit M2 | | Assert.cs:14:10:14:11 | enter M2 | Assert.cs:16:16:16:32 | String s = ... | | Assert.cs:14:10:14:11 | enter M2 | Assert.cs:16:24:16:27 | null | | Assert.cs:14:10:14:11 | enter M2 | Assert.cs:16:31:16:32 | "" | +| Assert.cs:14:10:14:11 | enter M2 | Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | +| Assert.cs:14:10:14:11 | enter M2 | Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | +| Assert.cs:14:10:14:11 | exit M2 | Assert.cs:14:10:14:11 | exit M2 | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:14:10:14:11 | exit M2 | | Assert.cs:16:16:16:32 | String s = ... | Assert.cs:16:16:16:32 | String s = ... | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | +| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | | Assert.cs:16:24:16:27 | null | Assert.cs:16:24:16:27 | null | | Assert.cs:16:31:16:32 | "" | Assert.cs:16:31:16:32 | "" | +| Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | +| Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | | Assert.cs:21:10:21:11 | enter M3 | Assert.cs:21:10:21:11 | enter M3 | +| Assert.cs:21:10:21:11 | enter M3 | Assert.cs:21:10:21:11 | exit M3 | | Assert.cs:21:10:21:11 | enter M3 | Assert.cs:23:16:23:32 | String s = ... | | Assert.cs:21:10:21:11 | enter M3 | Assert.cs:23:24:23:27 | null | | Assert.cs:21:10:21:11 | enter M3 | Assert.cs:23:31:23:32 | "" | +| Assert.cs:21:10:21:11 | enter M3 | Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | +| Assert.cs:21:10:21:11 | enter M3 | Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | +| Assert.cs:21:10:21:11 | exit M3 | Assert.cs:21:10:21:11 | exit M3 | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:21:10:21:11 | exit M3 | | Assert.cs:23:16:23:32 | String s = ... | Assert.cs:23:16:23:32 | String s = ... | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | +| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | | Assert.cs:23:24:23:27 | null | Assert.cs:23:24:23:27 | null | | Assert.cs:23:31:23:32 | "" | Assert.cs:23:31:23:32 | "" | +| Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | +| Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | | Assert.cs:28:10:28:11 | enter M4 | Assert.cs:28:10:28:11 | enter M4 | +| Assert.cs:28:10:28:11 | enter M4 | Assert.cs:28:10:28:11 | exit M4 | | Assert.cs:28:10:28:11 | enter M4 | Assert.cs:30:16:30:32 | String s = ... | | Assert.cs:28:10:28:11 | enter M4 | Assert.cs:30:24:30:27 | null | | Assert.cs:28:10:28:11 | enter M4 | Assert.cs:30:31:30:32 | "" | +| Assert.cs:28:10:28:11 | enter M4 | Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | +| Assert.cs:28:10:28:11 | enter M4 | Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | +| Assert.cs:28:10:28:11 | exit M4 | Assert.cs:28:10:28:11 | exit M4 | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:28:10:28:11 | exit M4 | | Assert.cs:30:16:30:32 | String s = ... | Assert.cs:30:16:30:32 | String s = ... | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | +| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | | Assert.cs:30:24:30:27 | null | Assert.cs:30:24:30:27 | null | | Assert.cs:30:31:30:32 | "" | Assert.cs:30:31:30:32 | "" | +| Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | +| Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | | Assert.cs:35:10:35:11 | enter M5 | Assert.cs:35:10:35:11 | enter M5 | +| Assert.cs:35:10:35:11 | enter M5 | Assert.cs:35:10:35:11 | exit M5 | | Assert.cs:35:10:35:11 | enter M5 | Assert.cs:37:16:37:32 | String s = ... | | Assert.cs:35:10:35:11 | enter M5 | Assert.cs:37:24:37:27 | null | | Assert.cs:35:10:35:11 | enter M5 | Assert.cs:37:31:37:32 | "" | +| Assert.cs:35:10:35:11 | enter M5 | Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | +| Assert.cs:35:10:35:11 | enter M5 | Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | +| Assert.cs:35:10:35:11 | exit M5 | Assert.cs:35:10:35:11 | exit M5 | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:35:10:35:11 | exit M5 | | Assert.cs:37:16:37:32 | String s = ... | Assert.cs:37:16:37:32 | String s = ... | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | +| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | | Assert.cs:37:24:37:27 | null | Assert.cs:37:24:37:27 | null | | Assert.cs:37:31:37:32 | "" | Assert.cs:37:31:37:32 | "" | +| Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | +| Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | | Assert.cs:42:10:42:11 | enter M6 | Assert.cs:42:10:42:11 | enter M6 | +| Assert.cs:42:10:42:11 | enter M6 | Assert.cs:42:10:42:11 | exit M6 | | Assert.cs:42:10:42:11 | enter M6 | Assert.cs:44:16:44:32 | String s = ... | | Assert.cs:42:10:42:11 | enter M6 | Assert.cs:44:24:44:27 | null | | Assert.cs:42:10:42:11 | enter M6 | Assert.cs:44:31:44:32 | "" | +| Assert.cs:42:10:42:11 | enter M6 | Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | +| Assert.cs:42:10:42:11 | enter M6 | Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | +| Assert.cs:42:10:42:11 | exit M6 | Assert.cs:42:10:42:11 | exit M6 | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:42:10:42:11 | exit M6 | | Assert.cs:44:16:44:32 | String s = ... | Assert.cs:44:16:44:32 | String s = ... | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | +| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | | Assert.cs:44:24:44:27 | null | Assert.cs:44:24:44:27 | null | | Assert.cs:44:31:44:32 | "" | Assert.cs:44:31:44:32 | "" | +| Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | +| Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | | Assert.cs:49:10:49:11 | enter M7 | Assert.cs:49:10:49:11 | enter M7 | +| Assert.cs:49:10:49:11 | enter M7 | Assert.cs:49:10:49:11 | exit M7 | | Assert.cs:49:10:49:11 | enter M7 | Assert.cs:51:16:51:32 | String s = ... | | Assert.cs:49:10:49:11 | enter M7 | Assert.cs:51:24:51:27 | null | | Assert.cs:49:10:49:11 | enter M7 | Assert.cs:51:31:51:32 | "" | +| Assert.cs:49:10:49:11 | enter M7 | Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | +| Assert.cs:49:10:49:11 | enter M7 | Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | +| Assert.cs:49:10:49:11 | exit M7 | Assert.cs:49:10:49:11 | exit M7 | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:49:10:49:11 | exit M7 | | Assert.cs:51:16:51:32 | String s = ... | Assert.cs:51:16:51:32 | String s = ... | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | +| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | | Assert.cs:51:24:51:27 | null | Assert.cs:51:24:51:27 | null | | Assert.cs:51:31:51:32 | "" | Assert.cs:51:31:51:32 | "" | +| Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | +| Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | | Assert.cs:56:10:56:11 | enter M8 | Assert.cs:56:10:56:11 | enter M8 | -| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:58:16:58:32 | String s = ... | -| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:58:24:58:27 | null | -| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:58:31:58:32 | "" | -| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:59:9:59:37 | call to method IsTrue | -| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:59:36:59:36 | access to parameter b | -| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:58:16:58:32 | String s = ... | -| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:59:9:59:37 | call to method IsTrue | -| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:59:36:59:36 | access to parameter b | -| Assert.cs:58:24:58:27 | null | Assert.cs:58:24:58:27 | null | -| Assert.cs:58:31:58:32 | "" | Assert.cs:58:31:58:32 | "" | -| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:59:9:59:37 | call to method IsTrue | -| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:59:36:59:36 | access to parameter b | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:56:10:56:11 | exit M8 | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:58:24:58:27 | [b (line 56): true] null | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:58:31:58:32 | [b (line 56): false] "" | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | +| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | +| Assert.cs:56:10:56:11 | exit M8 | Assert.cs:56:10:56:11 | exit M8 | +| Assert.cs:58:24:58:27 | [b (line 56): true] null | Assert.cs:58:24:58:27 | [b (line 56): true] null | +| Assert.cs:58:24:58:27 | [b (line 56): true] null | Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | +| Assert.cs:58:31:58:32 | [b (line 56): false] "" | Assert.cs:58:31:58:32 | [b (line 56): false] "" | +| Assert.cs:58:31:58:32 | [b (line 56): false] "" | Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | +| Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | +| Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | +| Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | | Assert.cs:63:10:63:11 | enter M9 | Assert.cs:63:10:63:11 | enter M9 | -| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:65:16:65:32 | String s = ... | -| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:65:24:65:27 | null | -| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:65:31:65:32 | "" | -| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:66:9:66:38 | call to method IsFalse | -| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:66:37:66:37 | access to parameter b | -| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:65:16:65:32 | String s = ... | -| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:66:9:66:38 | call to method IsFalse | -| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:66:37:66:37 | access to parameter b | -| Assert.cs:65:24:65:27 | null | Assert.cs:65:24:65:27 | null | -| Assert.cs:65:31:65:32 | "" | Assert.cs:65:31:65:32 | "" | -| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:66:9:66:38 | call to method IsFalse | -| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:66:37:66:37 | access to parameter b | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:63:10:63:11 | exit M9 | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:65:24:65:27 | [b (line 63): true] null | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:65:31:65:32 | [b (line 63): false] "" | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | +| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | +| Assert.cs:63:10:63:11 | exit M9 | Assert.cs:63:10:63:11 | exit M9 | +| Assert.cs:65:24:65:27 | [b (line 63): true] null | Assert.cs:65:24:65:27 | [b (line 63): true] null | +| Assert.cs:65:24:65:27 | [b (line 63): true] null | Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | +| Assert.cs:65:31:65:32 | [b (line 63): false] "" | Assert.cs:65:31:65:32 | [b (line 63): false] "" | +| Assert.cs:65:31:65:32 | [b (line 63): false] "" | Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | +| Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | +| Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | +| Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | | Assert.cs:70:10:70:12 | enter M10 | Assert.cs:70:10:70:12 | enter M10 | -| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:72:16:72:32 | String s = ... | -| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:72:24:72:27 | null | -| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:72:31:72:32 | "" | -| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:73:9:73:37 | call to method IsTrue | -| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:73:36:73:36 | access to parameter b | -| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:72:16:72:32 | String s = ... | -| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:73:9:73:37 | call to method IsTrue | -| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:73:36:73:36 | access to parameter b | -| Assert.cs:72:24:72:27 | null | Assert.cs:72:24:72:27 | null | -| Assert.cs:72:31:72:32 | "" | Assert.cs:72:31:72:32 | "" | -| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:73:9:73:37 | call to method IsTrue | -| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:73:36:73:36 | access to parameter b | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:70:10:70:12 | exit M10 | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:72:24:72:27 | [b (line 70): true] null | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:72:31:72:32 | [b (line 70): false] "" | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | +| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | +| Assert.cs:70:10:70:12 | exit M10 | Assert.cs:70:10:70:12 | exit M10 | +| Assert.cs:72:24:72:27 | [b (line 70): true] null | Assert.cs:72:24:72:27 | [b (line 70): true] null | +| Assert.cs:72:24:72:27 | [b (line 70): true] null | Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | +| Assert.cs:72:31:72:32 | [b (line 70): false] "" | Assert.cs:72:31:72:32 | [b (line 70): false] "" | +| Assert.cs:72:31:72:32 | [b (line 70): false] "" | Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | +| Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | +| Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | +| Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | | Assert.cs:77:10:77:12 | enter M11 | Assert.cs:77:10:77:12 | enter M11 | -| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:79:16:79:32 | String s = ... | -| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:79:24:79:27 | null | -| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:79:31:79:32 | "" | -| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:80:9:80:38 | call to method IsFalse | -| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:80:37:80:37 | access to parameter b | -| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:79:16:79:32 | String s = ... | -| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:80:9:80:38 | call to method IsFalse | -| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:80:37:80:37 | access to parameter b | -| Assert.cs:79:24:79:27 | null | Assert.cs:79:24:79:27 | null | -| Assert.cs:79:31:79:32 | "" | Assert.cs:79:31:79:32 | "" | -| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:80:9:80:38 | call to method IsFalse | -| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:80:37:80:37 | access to parameter b | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:77:10:77:12 | exit M11 | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:79:24:79:27 | [b (line 77): true] null | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:79:31:79:32 | [b (line 77): false] "" | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | +| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | +| Assert.cs:77:10:77:12 | exit M11 | Assert.cs:77:10:77:12 | exit M11 | +| Assert.cs:79:24:79:27 | [b (line 77): true] null | Assert.cs:79:24:79:27 | [b (line 77): true] null | +| Assert.cs:79:24:79:27 | [b (line 77): true] null | Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | +| Assert.cs:79:31:79:32 | [b (line 77): false] "" | Assert.cs:79:31:79:32 | [b (line 77): false] "" | +| Assert.cs:79:31:79:32 | [b (line 77): false] "" | Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | +| Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | +| Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | +| Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | | Assert.cs:84:10:84:12 | enter M12 | Assert.cs:84:10:84:12 | enter M12 | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:84:10:84:12 | exit M12 | | Assert.cs:84:10:84:12 | enter M12 | Assert.cs:86:24:86:27 | [b (line 84): true] null | | Assert.cs:84:10:84:12 | enter M12 | Assert.cs:86:31:86:32 | [b (line 84): false] "" | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | | Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | | Assert.cs:84:10:84:12 | enter M12 | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:37:119:38 | [b (line 84): false] !... | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | | Assert.cs:84:10:84:12 | enter M12 | Assert.cs:119:37:119:38 | [b (line 84): true] !... | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | | Assert.cs:84:10:84:12 | enter M12 | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:126:9:126:25 | ... = ... | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:127:9:127:39 | call to method IsFalse | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:127:37:127:38 | !... | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | +| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:127:37:127:38 | [b (line 84): true] !... | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:84:10:84:12 | exit M12 | | Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:86:24:86:27 | [b (line 84): true] null | -| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | | Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | -| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | | Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:119:37:119:38 | [b (line 84): true] !... | -| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | | Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | +| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:127:37:127:38 | [b (line 84): true] !... | | Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:86:31:86:32 | [b (line 84): false] "" | -| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | | Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | -| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | -| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:119:37:119:38 | [b (line 84): false] !... | -| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | -| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | -| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:119:37:119:38 | [b (line 84): false] !... | -| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | -| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | -| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | -| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:119:37:119:38 | [b (line 84): true] !... | -| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | -| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | +| Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:127:37:127:38 | [b (line 84): true] !... | +| Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | +| Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:127:37:127:38 | [b (line 84): true] !... | +| Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | +| Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:127:37:127:38 | [b (line 84): true] !... | +| Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:127:37:127:38 | [b (line 84): true] !... | +| Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:127:37:127:38 | [b (line 84): true] !... | +| Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:127:37:127:38 | [b (line 84): true] !... | +| Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:127:37:127:38 | [b (line 84): true] !... | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | -| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | -| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | -| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | -| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | -| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | -| Assert.cs:119:37:119:38 | [b (line 84): false] !... | Assert.cs:119:37:119:38 | [b (line 84): false] !... | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:127:37:127:38 | [b (line 84): true] !... | +| Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | | Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:119:37:119:38 | [b (line 84): true] !... | -| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | -| Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | +| Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | +| Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:127:37:127:38 | [b (line 84): true] !... | +| Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:126:9:126:25 | ... = ... | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:127:9:127:39 | call to method IsFalse | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:127:37:127:38 | !... | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:127:9:127:39 | call to method IsFalse | -| Assert.cs:127:37:127:38 | !... | Assert.cs:127:37:127:38 | !... | +| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | +| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:127:37:127:38 | [b (line 84): true] !... | +| Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | +| Assert.cs:127:37:127:38 | [b (line 84): true] !... | Assert.cs:127:37:127:38 | [b (line 84): true] !... | | Assignments.cs:3:10:3:10 | enter M | Assignments.cs:3:10:3:10 | enter M | | Assignments.cs:14:18:14:35 | enter (...) => ... | Assignments.cs:14:18:14:35 | enter (...) => ... | | Assignments.cs:17:40:17:40 | enter + | Assignments.cs:17:40:17:40 | enter + | @@ -7927,6 +8216,12 @@ blockDominance | ExitMethods.cs:119:17:119:32 | enter FailingAssertion | ExitMethods.cs:119:17:119:32 | enter FailingAssertion | | ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | | ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:10:131:20 | enter AssertFalse | +| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse | +| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | +| ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | +| ExitMethods.cs:131:10:131:20 | exit AssertFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse | +| ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | +| ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | | ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:5:23:5:29 | enter ToInt32 | | Extensions.cs:10:24:10:29 | enter ToBool | Extensions.cs:10:24:10:29 | enter ToBool | @@ -9946,184 +10241,262 @@ postBlockDominance | ArrayCreation.cs:7:11:7:12 | enter M3 | ArrayCreation.cs:7:11:7:12 | enter M3 | | ArrayCreation.cs:9:12:9:13 | enter M4 | ArrayCreation.cs:9:12:9:13 | enter M4 | | Assert.cs:7:10:7:11 | enter M1 | Assert.cs:7:10:7:11 | enter M1 | +| Assert.cs:7:10:7:11 | exit M1 | Assert.cs:7:10:7:11 | enter M1 | +| Assert.cs:7:10:7:11 | exit M1 | Assert.cs:7:10:7:11 | exit M1 | +| Assert.cs:7:10:7:11 | exit M1 | Assert.cs:9:16:9:32 | String s = ... | +| Assert.cs:7:10:7:11 | exit M1 | Assert.cs:9:24:9:27 | null | +| Assert.cs:7:10:7:11 | exit M1 | Assert.cs:9:31:9:32 | "" | +| Assert.cs:7:10:7:11 | exit M1 | Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | +| Assert.cs:7:10:7:11 | exit M1 | Assert.cs:10:9:10:31 | [assertion success] call to method Assert | | Assert.cs:9:16:9:32 | String s = ... | Assert.cs:7:10:7:11 | enter M1 | | Assert.cs:9:16:9:32 | String s = ... | Assert.cs:9:16:9:32 | String s = ... | | Assert.cs:9:16:9:32 | String s = ... | Assert.cs:9:24:9:27 | null | | Assert.cs:9:16:9:32 | String s = ... | Assert.cs:9:31:9:32 | "" | | Assert.cs:9:24:9:27 | null | Assert.cs:9:24:9:27 | null | | Assert.cs:9:31:9:32 | "" | Assert.cs:9:31:9:32 | "" | +| Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | +| Assert.cs:10:9:10:31 | [assertion success] call to method Assert | Assert.cs:10:9:10:31 | [assertion success] call to method Assert | | Assert.cs:14:10:14:11 | enter M2 | Assert.cs:14:10:14:11 | enter M2 | +| Assert.cs:14:10:14:11 | exit M2 | Assert.cs:14:10:14:11 | enter M2 | +| Assert.cs:14:10:14:11 | exit M2 | Assert.cs:14:10:14:11 | exit M2 | +| Assert.cs:14:10:14:11 | exit M2 | Assert.cs:16:16:16:32 | String s = ... | +| Assert.cs:14:10:14:11 | exit M2 | Assert.cs:16:24:16:27 | null | +| Assert.cs:14:10:14:11 | exit M2 | Assert.cs:16:31:16:32 | "" | +| Assert.cs:14:10:14:11 | exit M2 | Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | +| Assert.cs:14:10:14:11 | exit M2 | Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | | Assert.cs:16:16:16:32 | String s = ... | Assert.cs:14:10:14:11 | enter M2 | | Assert.cs:16:16:16:32 | String s = ... | Assert.cs:16:16:16:32 | String s = ... | | Assert.cs:16:16:16:32 | String s = ... | Assert.cs:16:24:16:27 | null | | Assert.cs:16:16:16:32 | String s = ... | Assert.cs:16:31:16:32 | "" | | Assert.cs:16:24:16:27 | null | Assert.cs:16:24:16:27 | null | | Assert.cs:16:31:16:32 | "" | Assert.cs:16:31:16:32 | "" | +| Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | +| Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | | Assert.cs:21:10:21:11 | enter M3 | Assert.cs:21:10:21:11 | enter M3 | +| Assert.cs:21:10:21:11 | exit M3 | Assert.cs:21:10:21:11 | enter M3 | +| Assert.cs:21:10:21:11 | exit M3 | Assert.cs:21:10:21:11 | exit M3 | +| Assert.cs:21:10:21:11 | exit M3 | Assert.cs:23:16:23:32 | String s = ... | +| Assert.cs:21:10:21:11 | exit M3 | Assert.cs:23:24:23:27 | null | +| Assert.cs:21:10:21:11 | exit M3 | Assert.cs:23:31:23:32 | "" | +| Assert.cs:21:10:21:11 | exit M3 | Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | +| Assert.cs:21:10:21:11 | exit M3 | Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | | Assert.cs:23:16:23:32 | String s = ... | Assert.cs:21:10:21:11 | enter M3 | | Assert.cs:23:16:23:32 | String s = ... | Assert.cs:23:16:23:32 | String s = ... | | Assert.cs:23:16:23:32 | String s = ... | Assert.cs:23:24:23:27 | null | | Assert.cs:23:16:23:32 | String s = ... | Assert.cs:23:31:23:32 | "" | | Assert.cs:23:24:23:27 | null | Assert.cs:23:24:23:27 | null | | Assert.cs:23:31:23:32 | "" | Assert.cs:23:31:23:32 | "" | +| Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | +| Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | | Assert.cs:28:10:28:11 | enter M4 | Assert.cs:28:10:28:11 | enter M4 | +| Assert.cs:28:10:28:11 | exit M4 | Assert.cs:28:10:28:11 | enter M4 | +| Assert.cs:28:10:28:11 | exit M4 | Assert.cs:28:10:28:11 | exit M4 | +| Assert.cs:28:10:28:11 | exit M4 | Assert.cs:30:16:30:32 | String s = ... | +| Assert.cs:28:10:28:11 | exit M4 | Assert.cs:30:24:30:27 | null | +| Assert.cs:28:10:28:11 | exit M4 | Assert.cs:30:31:30:32 | "" | +| Assert.cs:28:10:28:11 | exit M4 | Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | +| Assert.cs:28:10:28:11 | exit M4 | Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | | Assert.cs:30:16:30:32 | String s = ... | Assert.cs:28:10:28:11 | enter M4 | | Assert.cs:30:16:30:32 | String s = ... | Assert.cs:30:16:30:32 | String s = ... | | Assert.cs:30:16:30:32 | String s = ... | Assert.cs:30:24:30:27 | null | | Assert.cs:30:16:30:32 | String s = ... | Assert.cs:30:31:30:32 | "" | | Assert.cs:30:24:30:27 | null | Assert.cs:30:24:30:27 | null | | Assert.cs:30:31:30:32 | "" | Assert.cs:30:31:30:32 | "" | +| Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | +| Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | | Assert.cs:35:10:35:11 | enter M5 | Assert.cs:35:10:35:11 | enter M5 | +| Assert.cs:35:10:35:11 | exit M5 | Assert.cs:35:10:35:11 | enter M5 | +| Assert.cs:35:10:35:11 | exit M5 | Assert.cs:35:10:35:11 | exit M5 | +| Assert.cs:35:10:35:11 | exit M5 | Assert.cs:37:16:37:32 | String s = ... | +| Assert.cs:35:10:35:11 | exit M5 | Assert.cs:37:24:37:27 | null | +| Assert.cs:35:10:35:11 | exit M5 | Assert.cs:37:31:37:32 | "" | +| Assert.cs:35:10:35:11 | exit M5 | Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | +| Assert.cs:35:10:35:11 | exit M5 | Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | | Assert.cs:37:16:37:32 | String s = ... | Assert.cs:35:10:35:11 | enter M5 | | Assert.cs:37:16:37:32 | String s = ... | Assert.cs:37:16:37:32 | String s = ... | | Assert.cs:37:16:37:32 | String s = ... | Assert.cs:37:24:37:27 | null | | Assert.cs:37:16:37:32 | String s = ... | Assert.cs:37:31:37:32 | "" | | Assert.cs:37:24:37:27 | null | Assert.cs:37:24:37:27 | null | | Assert.cs:37:31:37:32 | "" | Assert.cs:37:31:37:32 | "" | +| Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | +| Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | | Assert.cs:42:10:42:11 | enter M6 | Assert.cs:42:10:42:11 | enter M6 | +| Assert.cs:42:10:42:11 | exit M6 | Assert.cs:42:10:42:11 | enter M6 | +| Assert.cs:42:10:42:11 | exit M6 | Assert.cs:42:10:42:11 | exit M6 | +| Assert.cs:42:10:42:11 | exit M6 | Assert.cs:44:16:44:32 | String s = ... | +| Assert.cs:42:10:42:11 | exit M6 | Assert.cs:44:24:44:27 | null | +| Assert.cs:42:10:42:11 | exit M6 | Assert.cs:44:31:44:32 | "" | +| Assert.cs:42:10:42:11 | exit M6 | Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | +| Assert.cs:42:10:42:11 | exit M6 | Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | | Assert.cs:44:16:44:32 | String s = ... | Assert.cs:42:10:42:11 | enter M6 | | Assert.cs:44:16:44:32 | String s = ... | Assert.cs:44:16:44:32 | String s = ... | | Assert.cs:44:16:44:32 | String s = ... | Assert.cs:44:24:44:27 | null | | Assert.cs:44:16:44:32 | String s = ... | Assert.cs:44:31:44:32 | "" | | Assert.cs:44:24:44:27 | null | Assert.cs:44:24:44:27 | null | | Assert.cs:44:31:44:32 | "" | Assert.cs:44:31:44:32 | "" | +| Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | +| Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | | Assert.cs:49:10:49:11 | enter M7 | Assert.cs:49:10:49:11 | enter M7 | +| Assert.cs:49:10:49:11 | exit M7 | Assert.cs:49:10:49:11 | enter M7 | +| Assert.cs:49:10:49:11 | exit M7 | Assert.cs:49:10:49:11 | exit M7 | +| Assert.cs:49:10:49:11 | exit M7 | Assert.cs:51:16:51:32 | String s = ... | +| Assert.cs:49:10:49:11 | exit M7 | Assert.cs:51:24:51:27 | null | +| Assert.cs:49:10:49:11 | exit M7 | Assert.cs:51:31:51:32 | "" | +| Assert.cs:49:10:49:11 | exit M7 | Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | +| Assert.cs:49:10:49:11 | exit M7 | Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | | Assert.cs:51:16:51:32 | String s = ... | Assert.cs:49:10:49:11 | enter M7 | | Assert.cs:51:16:51:32 | String s = ... | Assert.cs:51:16:51:32 | String s = ... | | Assert.cs:51:16:51:32 | String s = ... | Assert.cs:51:24:51:27 | null | | Assert.cs:51:16:51:32 | String s = ... | Assert.cs:51:31:51:32 | "" | | Assert.cs:51:24:51:27 | null | Assert.cs:51:24:51:27 | null | | Assert.cs:51:31:51:32 | "" | Assert.cs:51:31:51:32 | "" | +| Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | +| Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | | Assert.cs:56:10:56:11 | enter M8 | Assert.cs:56:10:56:11 | enter M8 | -| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:56:10:56:11 | enter M8 | -| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:58:16:58:32 | String s = ... | -| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:58:24:58:27 | null | -| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:58:31:58:32 | "" | -| Assert.cs:58:24:58:27 | null | Assert.cs:58:24:58:27 | null | -| Assert.cs:58:31:58:32 | "" | Assert.cs:58:31:58:32 | "" | -| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:56:10:56:11 | enter M8 | -| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:58:16:58:32 | String s = ... | -| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:58:24:58:27 | null | -| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:58:31:58:32 | "" | -| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:59:9:59:37 | call to method IsTrue | -| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:59:36:59:36 | access to parameter b | -| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:59:36:59:36 | access to parameter b | +| Assert.cs:56:10:56:11 | exit M8 | Assert.cs:56:10:56:11 | enter M8 | +| Assert.cs:56:10:56:11 | exit M8 | Assert.cs:56:10:56:11 | exit M8 | +| Assert.cs:56:10:56:11 | exit M8 | Assert.cs:58:24:58:27 | [b (line 56): true] null | +| Assert.cs:56:10:56:11 | exit M8 | Assert.cs:58:31:58:32 | [b (line 56): false] "" | +| Assert.cs:56:10:56:11 | exit M8 | Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | +| Assert.cs:56:10:56:11 | exit M8 | Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | +| Assert.cs:56:10:56:11 | exit M8 | Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | +| Assert.cs:58:24:58:27 | [b (line 56): true] null | Assert.cs:58:24:58:27 | [b (line 56): true] null | +| Assert.cs:58:31:58:32 | [b (line 56): false] "" | Assert.cs:58:31:58:32 | [b (line 56): false] "" | +| Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | Assert.cs:58:31:58:32 | [b (line 56): false] "" | +| Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | +| Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | +| Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | +| Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | | Assert.cs:63:10:63:11 | enter M9 | Assert.cs:63:10:63:11 | enter M9 | -| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:63:10:63:11 | enter M9 | -| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:65:16:65:32 | String s = ... | -| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:65:24:65:27 | null | -| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:65:31:65:32 | "" | -| Assert.cs:65:24:65:27 | null | Assert.cs:65:24:65:27 | null | -| Assert.cs:65:31:65:32 | "" | Assert.cs:65:31:65:32 | "" | -| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:63:10:63:11 | enter M9 | -| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:65:16:65:32 | String s = ... | -| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:65:24:65:27 | null | -| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:65:31:65:32 | "" | -| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:66:9:66:38 | call to method IsFalse | -| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:66:37:66:37 | access to parameter b | -| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:66:37:66:37 | access to parameter b | +| Assert.cs:63:10:63:11 | exit M9 | Assert.cs:63:10:63:11 | enter M9 | +| Assert.cs:63:10:63:11 | exit M9 | Assert.cs:63:10:63:11 | exit M9 | +| Assert.cs:63:10:63:11 | exit M9 | Assert.cs:65:24:65:27 | [b (line 63): true] null | +| Assert.cs:63:10:63:11 | exit M9 | Assert.cs:65:31:65:32 | [b (line 63): false] "" | +| Assert.cs:63:10:63:11 | exit M9 | Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | +| Assert.cs:63:10:63:11 | exit M9 | Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | +| Assert.cs:63:10:63:11 | exit M9 | Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | +| Assert.cs:65:24:65:27 | [b (line 63): true] null | Assert.cs:65:24:65:27 | [b (line 63): true] null | +| Assert.cs:65:31:65:32 | [b (line 63): false] "" | Assert.cs:65:31:65:32 | [b (line 63): false] "" | +| Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | Assert.cs:65:24:65:27 | [b (line 63): true] null | +| Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | +| Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | +| Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | +| Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | | Assert.cs:70:10:70:12 | enter M10 | Assert.cs:70:10:70:12 | enter M10 | -| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:70:10:70:12 | enter M10 | -| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:72:16:72:32 | String s = ... | -| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:72:24:72:27 | null | -| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:72:31:72:32 | "" | -| Assert.cs:72:24:72:27 | null | Assert.cs:72:24:72:27 | null | -| Assert.cs:72:31:72:32 | "" | Assert.cs:72:31:72:32 | "" | -| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:70:10:70:12 | enter M10 | -| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:72:16:72:32 | String s = ... | -| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:72:24:72:27 | null | -| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:72:31:72:32 | "" | -| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:73:9:73:37 | call to method IsTrue | -| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:73:36:73:36 | access to parameter b | -| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:73:36:73:36 | access to parameter b | +| Assert.cs:70:10:70:12 | exit M10 | Assert.cs:70:10:70:12 | enter M10 | +| Assert.cs:70:10:70:12 | exit M10 | Assert.cs:70:10:70:12 | exit M10 | +| Assert.cs:70:10:70:12 | exit M10 | Assert.cs:72:24:72:27 | [b (line 70): true] null | +| Assert.cs:70:10:70:12 | exit M10 | Assert.cs:72:31:72:32 | [b (line 70): false] "" | +| Assert.cs:70:10:70:12 | exit M10 | Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | +| Assert.cs:70:10:70:12 | exit M10 | Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | +| Assert.cs:70:10:70:12 | exit M10 | Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | +| Assert.cs:72:24:72:27 | [b (line 70): true] null | Assert.cs:72:24:72:27 | [b (line 70): true] null | +| Assert.cs:72:31:72:32 | [b (line 70): false] "" | Assert.cs:72:31:72:32 | [b (line 70): false] "" | +| Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | Assert.cs:72:31:72:32 | [b (line 70): false] "" | +| Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | +| Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | +| Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | +| Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | | Assert.cs:77:10:77:12 | enter M11 | Assert.cs:77:10:77:12 | enter M11 | -| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:77:10:77:12 | enter M11 | -| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:79:16:79:32 | String s = ... | -| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:79:24:79:27 | null | -| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:79:31:79:32 | "" | -| Assert.cs:79:24:79:27 | null | Assert.cs:79:24:79:27 | null | -| Assert.cs:79:31:79:32 | "" | Assert.cs:79:31:79:32 | "" | -| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:77:10:77:12 | enter M11 | -| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:79:16:79:32 | String s = ... | -| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:79:24:79:27 | null | -| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:79:31:79:32 | "" | -| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:80:9:80:38 | call to method IsFalse | -| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:80:37:80:37 | access to parameter b | -| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:80:37:80:37 | access to parameter b | +| Assert.cs:77:10:77:12 | exit M11 | Assert.cs:77:10:77:12 | enter M11 | +| Assert.cs:77:10:77:12 | exit M11 | Assert.cs:77:10:77:12 | exit M11 | +| Assert.cs:77:10:77:12 | exit M11 | Assert.cs:79:24:79:27 | [b (line 77): true] null | +| Assert.cs:77:10:77:12 | exit M11 | Assert.cs:79:31:79:32 | [b (line 77): false] "" | +| Assert.cs:77:10:77:12 | exit M11 | Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | +| Assert.cs:77:10:77:12 | exit M11 | Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | +| Assert.cs:77:10:77:12 | exit M11 | Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | +| Assert.cs:79:24:79:27 | [b (line 77): true] null | Assert.cs:79:24:79:27 | [b (line 77): true] null | +| Assert.cs:79:31:79:32 | [b (line 77): false] "" | Assert.cs:79:31:79:32 | [b (line 77): false] "" | +| Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | Assert.cs:79:24:79:27 | [b (line 77): true] null | +| Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | +| Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | +| Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | +| Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | | Assert.cs:84:10:84:12 | enter M12 | Assert.cs:84:10:84:12 | enter M12 | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:84:10:84:12 | enter M12 | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:84:10:84:12 | exit M12 | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:86:24:86:27 | [b (line 84): true] null | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:86:31:86:32 | [b (line 84): false] "" | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:119:37:119:38 | [b (line 84): true] !... | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:127:37:127:38 | [b (line 84): true] !... | | Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:86:24:86:27 | [b (line 84): true] null | | Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:86:31:86:32 | [b (line 84): false] "" | -| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:86:31:86:32 | [b (line 84): false] "" | -| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | -| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:86:24:86:27 | [b (line 84): true] null | -| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | -| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | +| Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | +| Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | +| Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | +| Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | +| Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | +| Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | +| Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | +| Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | +| Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | +| Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | -| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:86:31:86:32 | [b (line 84): false] "" | -| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | -| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | -| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:119:37:119:38 | [b (line 84): false] !... | -| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:86:24:86:27 | [b (line 84): true] null | -| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | -| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | -| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | -| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:119:37:119:38 | [b (line 84): true] !... | -| Assert.cs:119:37:119:38 | [b (line 84): false] !... | Assert.cs:119:37:119:38 | [b (line 84): false] !... | +| Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | | Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:119:37:119:38 | [b (line 84): true] !... | -| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:86:31:86:32 | [b (line 84): false] "" | -| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | -| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | -| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:119:37:119:38 | [b (line 84): false] !... | -| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | -| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:86:24:86:27 | [b (line 84): true] null | -| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | -| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | -| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | -| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:119:37:119:38 | [b (line 84): true] !... | -| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | -| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | -| Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | +| Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:84:10:84:12 | enter M12 | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:86:24:86:27 | [b (line 84): true] null | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:86:31:86:32 | [b (line 84): false] "" | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:119:37:119:38 | [b (line 84): false] !... | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:119:37:119:38 | [b (line 84): true] !... | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:126:9:126:25 | ... = ... | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:84:10:84:12 | enter M12 | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:86:24:86:27 | [b (line 84): true] null | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:86:31:86:32 | [b (line 84): false] "" | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:119:37:119:38 | [b (line 84): false] !... | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:119:37:119:38 | [b (line 84): true] !... | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:126:9:126:25 | ... = ... | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:127:9:127:39 | call to method IsFalse | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:127:37:127:38 | !... | -| Assert.cs:127:37:127:38 | !... | Assert.cs:127:37:127:38 | !... | +| Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | +| Assert.cs:127:37:127:38 | [b (line 84): true] !... | Assert.cs:127:37:127:38 | [b (line 84): true] !... | | Assignments.cs:3:10:3:10 | enter M | Assignments.cs:3:10:3:10 | enter M | | Assignments.cs:14:18:14:35 | enter (...) => ... | Assignments.cs:14:18:14:35 | enter (...) => ... | | Assignments.cs:17:40:17:40 | enter + | Assignments.cs:17:40:17:40 | enter + | @@ -10514,6 +10887,12 @@ postBlockDominance | ExitMethods.cs:119:17:119:32 | enter FailingAssertion | ExitMethods.cs:119:17:119:32 | enter FailingAssertion | | ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | | ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:10:131:20 | enter AssertFalse | +| ExitMethods.cs:131:10:131:20 | exit AssertFalse | ExitMethods.cs:131:10:131:20 | enter AssertFalse | +| ExitMethods.cs:131:10:131:20 | exit AssertFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse | +| ExitMethods.cs:131:10:131:20 | exit AssertFalse | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | +| ExitMethods.cs:131:10:131:20 | exit AssertFalse | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | +| ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | +| ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | | ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:5:23:5:29 | enter ToInt32 | | Extensions.cs:10:24:10:29 | enter ToBool | Extensions.cs:10:24:10:29 | enter ToBool | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected index aa8ad433674..e3db27fb573 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected @@ -334,7 +334,8 @@ nodeEnclosing | Assert.cs:9:20:9:32 | ... ? ... : ... | Assert.cs:7:10:7:11 | M1 | | Assert.cs:9:24:9:27 | null | Assert.cs:7:10:7:11 | M1 | | Assert.cs:9:31:9:32 | "" | Assert.cs:7:10:7:11 | M1 | -| Assert.cs:10:9:10:31 | call to method Assert | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:10:9:10:31 | [assertion success] call to method Assert | Assert.cs:7:10:7:11 | M1 | | Assert.cs:10:9:10:32 | ...; | Assert.cs:7:10:7:11 | M1 | | Assert.cs:10:22:10:22 | access to local variable s | Assert.cs:7:10:7:11 | M1 | | Assert.cs:10:22:10:30 | ... != ... | Assert.cs:7:10:7:11 | M1 | @@ -352,7 +353,8 @@ nodeEnclosing | Assert.cs:16:20:16:32 | ... ? ... : ... | Assert.cs:14:10:14:11 | M2 | | Assert.cs:16:24:16:27 | null | Assert.cs:14:10:14:11 | M2 | | Assert.cs:16:31:16:32 | "" | Assert.cs:14:10:14:11 | M2 | -| Assert.cs:17:9:17:24 | call to method IsNull | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | Assert.cs:14:10:14:11 | M2 | | Assert.cs:17:9:17:25 | ...; | Assert.cs:14:10:14:11 | M2 | | Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:14:10:14:11 | M2 | | Assert.cs:18:9:18:35 | call to method WriteLine | Assert.cs:14:10:14:11 | M2 | @@ -368,7 +370,8 @@ nodeEnclosing | Assert.cs:23:20:23:32 | ... ? ... : ... | Assert.cs:21:10:21:11 | M3 | | Assert.cs:23:24:23:27 | null | Assert.cs:21:10:21:11 | M3 | | Assert.cs:23:31:23:32 | "" | Assert.cs:21:10:21:11 | M3 | -| Assert.cs:24:9:24:27 | call to method IsNotNull | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | Assert.cs:21:10:21:11 | M3 | | Assert.cs:24:9:24:28 | ...; | Assert.cs:21:10:21:11 | M3 | | Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:21:10:21:11 | M3 | | Assert.cs:25:9:25:35 | call to method WriteLine | Assert.cs:21:10:21:11 | M3 | @@ -384,7 +387,8 @@ nodeEnclosing | Assert.cs:30:20:30:32 | ... ? ... : ... | Assert.cs:28:10:28:11 | M4 | | Assert.cs:30:24:30:27 | null | Assert.cs:28:10:28:11 | M4 | | Assert.cs:30:31:30:32 | "" | Assert.cs:28:10:28:11 | M4 | -| Assert.cs:31:9:31:32 | call to method IsTrue | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | Assert.cs:28:10:28:11 | M4 | | Assert.cs:31:9:31:33 | ...; | Assert.cs:28:10:28:11 | M4 | | Assert.cs:31:23:31:23 | access to local variable s | Assert.cs:28:10:28:11 | M4 | | Assert.cs:31:23:31:31 | ... == ... | Assert.cs:28:10:28:11 | M4 | @@ -402,7 +406,8 @@ nodeEnclosing | Assert.cs:37:20:37:32 | ... ? ... : ... | Assert.cs:35:10:35:11 | M5 | | Assert.cs:37:24:37:27 | null | Assert.cs:35:10:35:11 | M5 | | Assert.cs:37:31:37:32 | "" | Assert.cs:35:10:35:11 | M5 | -| Assert.cs:38:9:38:32 | call to method IsTrue | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | Assert.cs:35:10:35:11 | M5 | | Assert.cs:38:9:38:33 | ...; | Assert.cs:35:10:35:11 | M5 | | Assert.cs:38:23:38:23 | access to local variable s | Assert.cs:35:10:35:11 | M5 | | Assert.cs:38:23:38:31 | ... != ... | Assert.cs:35:10:35:11 | M5 | @@ -420,7 +425,8 @@ nodeEnclosing | Assert.cs:44:20:44:32 | ... ? ... : ... | Assert.cs:42:10:42:11 | M6 | | Assert.cs:44:24:44:27 | null | Assert.cs:42:10:42:11 | M6 | | Assert.cs:44:31:44:32 | "" | Assert.cs:42:10:42:11 | M6 | -| Assert.cs:45:9:45:33 | call to method IsFalse | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | Assert.cs:42:10:42:11 | M6 | | Assert.cs:45:9:45:34 | ...; | Assert.cs:42:10:42:11 | M6 | | Assert.cs:45:24:45:24 | access to local variable s | Assert.cs:42:10:42:11 | M6 | | Assert.cs:45:24:45:32 | ... != ... | Assert.cs:42:10:42:11 | M6 | @@ -438,7 +444,8 @@ nodeEnclosing | Assert.cs:51:20:51:32 | ... ? ... : ... | Assert.cs:49:10:49:11 | M7 | | Assert.cs:51:24:51:27 | null | Assert.cs:49:10:49:11 | M7 | | Assert.cs:51:31:51:32 | "" | Assert.cs:49:10:49:11 | M7 | -| Assert.cs:52:9:52:33 | call to method IsFalse | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | Assert.cs:49:10:49:11 | M7 | | Assert.cs:52:9:52:34 | ...; | Assert.cs:49:10:49:11 | M7 | | Assert.cs:52:24:52:24 | access to local variable s | Assert.cs:49:10:49:11 | M7 | | Assert.cs:52:24:52:32 | ... == ... | Assert.cs:49:10:49:11 | M7 | @@ -451,18 +458,26 @@ nodeEnclosing | Assert.cs:56:10:56:11 | exit M8 | Assert.cs:56:10:56:11 | M8 | | Assert.cs:57:5:61:5 | {...} | Assert.cs:56:10:56:11 | M8 | | Assert.cs:58:9:58:33 | ... ...; | Assert.cs:56:10:56:11 | M8 | -| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:58:16:58:32 | [b (line 56): false] String s = ... | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:58:16:58:32 | [b (line 56): true] String s = ... | Assert.cs:56:10:56:11 | M8 | | Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:56:10:56:11 | M8 | | Assert.cs:58:20:58:32 | ... ? ... : ... | Assert.cs:56:10:56:11 | M8 | -| Assert.cs:58:24:58:27 | null | Assert.cs:56:10:56:11 | M8 | -| Assert.cs:58:31:58:32 | "" | Assert.cs:56:10:56:11 | M8 | -| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:56:10:56:11 | M8 | -| Assert.cs:59:9:59:38 | ...; | Assert.cs:56:10:56:11 | M8 | -| Assert.cs:59:23:59:23 | access to local variable s | Assert.cs:56:10:56:11 | M8 | -| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:56:10:56:11 | M8 | -| Assert.cs:59:23:59:36 | ... && ... | Assert.cs:56:10:56:11 | M8 | -| Assert.cs:59:28:59:31 | null | Assert.cs:56:10:56:11 | M8 | -| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:58:24:58:27 | [b (line 56): true] null | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:58:31:58:32 | [b (line 56): false] "" | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:9:59:37 | [assertion success] call to method IsTrue | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:9:59:38 | [b (line 56): false] ...; | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:9:59:38 | [b (line 56): true] ...; | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:23:59:23 | [b (line 56): false] access to local variable s | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:23:59:23 | [b (line 56): true] access to local variable s | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:23:59:31 | [b (line 56): false] ... != ... | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:23:59:31 | [b (line 56): true] ... != ... | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:23:59:36 | [b (line 56): false] ... && ... | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:23:59:36 | [b (line 56): true] ... && ... | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:28:59:31 | [b (line 56): false] null | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:28:59:31 | [b (line 56): true] null | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | Assert.cs:56:10:56:11 | M8 | | Assert.cs:60:9:60:35 | call to method WriteLine | Assert.cs:56:10:56:11 | M8 | | Assert.cs:60:9:60:36 | ...; | Assert.cs:56:10:56:11 | M8 | | Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:56:10:56:11 | M8 | @@ -471,18 +486,26 @@ nodeEnclosing | Assert.cs:63:10:63:11 | exit M9 | Assert.cs:63:10:63:11 | M9 | | Assert.cs:64:5:68:5 | {...} | Assert.cs:63:10:63:11 | M9 | | Assert.cs:65:9:65:33 | ... ...; | Assert.cs:63:10:63:11 | M9 | -| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:65:16:65:32 | [b (line 63): false] String s = ... | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:65:16:65:32 | [b (line 63): true] String s = ... | Assert.cs:63:10:63:11 | M9 | | Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:63:10:63:11 | M9 | | Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:63:10:63:11 | M9 | -| Assert.cs:65:24:65:27 | null | Assert.cs:63:10:63:11 | M9 | -| Assert.cs:65:31:65:32 | "" | Assert.cs:63:10:63:11 | M9 | -| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:63:10:63:11 | M9 | -| Assert.cs:66:9:66:39 | ...; | Assert.cs:63:10:63:11 | M9 | -| Assert.cs:66:24:66:24 | access to local variable s | Assert.cs:63:10:63:11 | M9 | -| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:63:10:63:11 | M9 | -| Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:63:10:63:11 | M9 | -| Assert.cs:66:29:66:32 | null | Assert.cs:63:10:63:11 | M9 | -| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:65:24:65:27 | [b (line 63): true] null | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:65:31:65:32 | [b (line 63): false] "" | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:9:66:38 | [assertion success] call to method IsFalse | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:9:66:39 | [b (line 63): false] ...; | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:9:66:39 | [b (line 63): true] ...; | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:24:66:24 | [b (line 63): false] access to local variable s | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:24:66:24 | [b (line 63): true] access to local variable s | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:24:66:32 | [b (line 63): false] ... == ... | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:24:66:32 | [b (line 63): true] ... == ... | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:24:66:37 | [b (line 63): false] ... \|\| ... | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:24:66:37 | [b (line 63): true] ... \|\| ... | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:29:66:32 | [b (line 63): false] null | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:29:66:32 | [b (line 63): true] null | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | Assert.cs:63:10:63:11 | M9 | | Assert.cs:67:9:67:35 | call to method WriteLine | Assert.cs:63:10:63:11 | M9 | | Assert.cs:67:9:67:36 | ...; | Assert.cs:63:10:63:11 | M9 | | Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:63:10:63:11 | M9 | @@ -491,18 +514,26 @@ nodeEnclosing | Assert.cs:70:10:70:12 | exit M10 | Assert.cs:70:10:70:12 | M10 | | Assert.cs:71:5:75:5 | {...} | Assert.cs:70:10:70:12 | M10 | | Assert.cs:72:9:72:33 | ... ...; | Assert.cs:70:10:70:12 | M10 | -| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:72:16:72:32 | [b (line 70): false] String s = ... | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:72:16:72:32 | [b (line 70): true] String s = ... | Assert.cs:70:10:70:12 | M10 | | Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:70:10:70:12 | M10 | | Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:70:10:70:12 | M10 | -| Assert.cs:72:24:72:27 | null | Assert.cs:70:10:70:12 | M10 | -| Assert.cs:72:31:72:32 | "" | Assert.cs:70:10:70:12 | M10 | -| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:70:10:70:12 | M10 | -| Assert.cs:73:9:73:38 | ...; | Assert.cs:70:10:70:12 | M10 | -| Assert.cs:73:23:73:23 | access to local variable s | Assert.cs:70:10:70:12 | M10 | -| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:70:10:70:12 | M10 | -| Assert.cs:73:23:73:36 | ... && ... | Assert.cs:70:10:70:12 | M10 | -| Assert.cs:73:28:73:31 | null | Assert.cs:70:10:70:12 | M10 | -| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:72:24:72:27 | [b (line 70): true] null | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:72:31:72:32 | [b (line 70): false] "" | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:9:73:37 | [assertion success] call to method IsTrue | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:9:73:38 | [b (line 70): false] ...; | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:9:73:38 | [b (line 70): true] ...; | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:23:73:23 | [b (line 70): false] access to local variable s | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:23:73:23 | [b (line 70): true] access to local variable s | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:23:73:31 | [b (line 70): false] ... == ... | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:23:73:31 | [b (line 70): true] ... == ... | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:23:73:36 | [b (line 70): false] ... && ... | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:23:73:36 | [b (line 70): true] ... && ... | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:28:73:31 | [b (line 70): false] null | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:28:73:31 | [b (line 70): true] null | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | Assert.cs:70:10:70:12 | M10 | | Assert.cs:74:9:74:35 | call to method WriteLine | Assert.cs:70:10:70:12 | M10 | | Assert.cs:74:9:74:36 | ...; | Assert.cs:70:10:70:12 | M10 | | Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:70:10:70:12 | M10 | @@ -511,18 +542,26 @@ nodeEnclosing | Assert.cs:77:10:77:12 | exit M11 | Assert.cs:77:10:77:12 | M11 | | Assert.cs:78:5:82:5 | {...} | Assert.cs:77:10:77:12 | M11 | | Assert.cs:79:9:79:33 | ... ...; | Assert.cs:77:10:77:12 | M11 | -| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:79:16:79:32 | [b (line 77): false] String s = ... | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:79:16:79:32 | [b (line 77): true] String s = ... | Assert.cs:77:10:77:12 | M11 | | Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:77:10:77:12 | M11 | | Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:77:10:77:12 | M11 | -| Assert.cs:79:24:79:27 | null | Assert.cs:77:10:77:12 | M11 | -| Assert.cs:79:31:79:32 | "" | Assert.cs:77:10:77:12 | M11 | -| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:77:10:77:12 | M11 | -| Assert.cs:80:9:80:39 | ...; | Assert.cs:77:10:77:12 | M11 | -| Assert.cs:80:24:80:24 | access to local variable s | Assert.cs:77:10:77:12 | M11 | -| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:77:10:77:12 | M11 | -| Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:77:10:77:12 | M11 | -| Assert.cs:80:29:80:32 | null | Assert.cs:77:10:77:12 | M11 | -| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:79:24:79:27 | [b (line 77): true] null | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:79:31:79:32 | [b (line 77): false] "" | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:9:80:38 | [assertion success] call to method IsFalse | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:9:80:39 | [b (line 77): false] ...; | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:9:80:39 | [b (line 77): true] ...; | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:24:80:24 | [b (line 77): false] access to local variable s | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:24:80:24 | [b (line 77): true] access to local variable s | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:24:80:32 | [b (line 77): false] ... != ... | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:24:80:32 | [b (line 77): true] ... != ... | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:24:80:37 | [b (line 77): false] ... \|\| ... | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:24:80:37 | [b (line 77): true] ... \|\| ... | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:29:80:32 | [b (line 77): false] null | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:29:80:32 | [b (line 77): true] null | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | Assert.cs:77:10:77:12 | M11 | | Assert.cs:81:9:81:35 | call to method WriteLine | Assert.cs:77:10:77:12 | M11 | | Assert.cs:81:9:81:36 | ...; | Assert.cs:77:10:77:12 | M11 | | Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:77:10:77:12 | M11 | @@ -537,8 +576,10 @@ nodeEnclosing | Assert.cs:86:20:86:32 | ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | | Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:87:9:87:31 | [b (line 84): false] call to method Assert | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:87:9:87:31 | [b (line 84): true] call to method Assert | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:84:10:84:12 | M12 | | Assert.cs:87:9:87:32 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:87:9:87:32 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:87:22:87:22 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | @@ -565,8 +606,10 @@ nodeEnclosing | Assert.cs:90:13:90:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:90:17:90:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | | Assert.cs:90:24:90:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:91:9:91:24 | [b (line 84): false] call to method IsNull | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:91:9:91:24 | [b (line 84): true] call to method IsNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:84:10:84:12 | M12 | | Assert.cs:91:9:91:25 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:91:9:91:25 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | @@ -589,8 +632,10 @@ nodeEnclosing | Assert.cs:94:13:94:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:94:17:94:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | | Assert.cs:94:24:94:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:95:9:95:27 | [b (line 84): false] call to method IsNotNull | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:95:9:95:27 | [b (line 84): true] call to method IsNotNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:84:10:84:12 | M12 | | Assert.cs:95:9:95:28 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:95:9:95:28 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | @@ -613,8 +658,10 @@ nodeEnclosing | Assert.cs:98:13:98:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:98:17:98:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | | Assert.cs:98:24:98:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:99:9:99:32 | [b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:99:9:99:32 | [b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | | Assert.cs:99:9:99:33 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:99:9:99:33 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:99:23:99:23 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | @@ -641,8 +688,10 @@ nodeEnclosing | Assert.cs:102:13:102:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:102:17:102:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | | Assert.cs:102:24:102:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:103:9:103:32 | [b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:103:9:103:32 | [b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | | Assert.cs:103:9:103:33 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:103:9:103:33 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:103:23:103:23 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | @@ -669,8 +718,10 @@ nodeEnclosing | Assert.cs:106:13:106:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:106:17:106:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | | Assert.cs:106:24:106:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:107:9:107:33 | [b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:107:9:107:33 | [b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | | Assert.cs:107:9:107:34 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:107:9:107:34 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:107:24:107:24 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | @@ -697,8 +748,10 @@ nodeEnclosing | Assert.cs:110:13:110:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:110:17:110:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | | Assert.cs:110:24:110:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:111:9:111:33 | [b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:111:9:111:33 | [b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | | Assert.cs:111:9:111:34 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:111:9:111:34 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:111:24:111:24 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | @@ -725,8 +778,9 @@ nodeEnclosing | Assert.cs:114:13:114:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:114:17:114:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | | Assert.cs:114:24:114:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:9:115:37 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | | Assert.cs:115:9:115:38 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:115:9:115:38 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | @@ -739,97 +793,59 @@ nodeEnclosing | Assert.cs:115:28:115:31 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:116:9:116:35 | [b (line 84): false] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | | Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:116:9:116:36 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:116:9:116:36 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:116:27:116:27 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | | Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:116:27:116:34 | [b (line 84): false] access to property Length | Assert.cs:84:10:84:12 | M12 | | Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:118:9:118:25 | [b (line 84): false] ... = ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:118:9:118:26 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:118:9:118:26 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | | Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:118:13:118:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:118:17:118:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:118:24:118:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:119:9:119:40 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:9:119:39 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | | Assert.cs:119:9:119:40 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:119:24:119:24 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | | Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:119:24:119:38 | [b (line 84): false] ... \|\| ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:119:24:119:38 | [b (line 84): true] ... \|\| ... | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:119:29:119:32 | [b (line 84): false] null | Assert.cs:84:10:84:12 | M12 | | Assert.cs:119:29:119:32 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:119:37:119:38 | [b (line 84): false] !... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:119:38:119:38 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | | Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:120:9:120:35 | [b (line 84): false] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | | Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:120:9:120:36 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:120:9:120:36 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:120:27:120:27 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | | Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:120:27:120:34 | [b (line 84): false] access to property Length | Assert.cs:84:10:84:12 | M12 | | Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:122:9:122:25 | [b (line 84): false] ... = ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:122:9:122:26 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:122:9:122:26 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | | Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:122:13:122:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:122:17:122:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:122:24:122:25 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:123:9:123:38 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:9:123:37 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | | Assert.cs:123:9:123:38 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:123:23:123:23 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | | Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:123:23:123:36 | [b (line 84): false] ... && ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:123:23:123:36 | [b (line 84): true] ... && ... | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:123:28:123:31 | [b (line 84): false] null | Assert.cs:84:10:84:12 | M12 | | Assert.cs:123:28:123:31 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:124:9:124:35 | [b (line 84): false] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | | Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:124:9:124:36 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:124:9:124:36 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:124:27:124:27 | [b (line 84): false] access to local variable s | Assert.cs:84:10:84:12 | M12 | | Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:124:27:124:34 | [b (line 84): false] access to property Length | Assert.cs:84:10:84:12 | M12 | | Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:126:9:126:26 | [b (line 84): false] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:126:9:126:25 | [b (line 84): true] ... = ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:126:9:126:26 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | | Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:126:13:126:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | | Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:126:17:126:20 | null | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:126:24:126:25 | "" | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:127:9:127:40 | ...; | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:127:24:127:24 | access to local variable s | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:127:24:127:38 | ... \|\| ... | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:127:29:127:32 | null | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:127:37:127:38 | !... | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:127:38:127:38 | access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:126:17:126:20 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:9:127:39 | [assertion success] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:9:127:40 | [b (line 84): true] ...; | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:24:127:24 | [b (line 84): true] access to local variable s | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:24:127:32 | [b (line 84): true] ... != ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:24:127:38 | [b (line 84): true] ... \|\| ... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:29:127:32 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:37:127:38 | [b (line 84): true] !... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:38:127:38 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | | Assert.cs:128:9:128:35 | call to method WriteLine | Assert.cs:84:10:84:12 | M12 | | Assert.cs:128:9:128:36 | ...; | Assert.cs:84:10:84:12 | M12 | | Assert.cs:128:27:128:27 | access to local variable s | Assert.cs:84:10:84:12 | M12 | @@ -1589,7 +1605,7 @@ nodeEnclosing | ExitMethods.cs:119:17:119:32 | enter FailingAssertion | ExitMethods.cs:119:17:119:32 | FailingAssertion | | ExitMethods.cs:119:17:119:32 | exit FailingAssertion | ExitMethods.cs:119:17:119:32 | FailingAssertion | | ExitMethods.cs:120:5:123:5 | {...} | ExitMethods.cs:119:17:119:32 | FailingAssertion | -| ExitMethods.cs:121:9:121:28 | call to method IsTrue | ExitMethods.cs:119:17:119:32 | FailingAssertion | +| ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:119:17:119:32 | FailingAssertion | | ExitMethods.cs:121:9:121:29 | ...; | ExitMethods.cs:119:17:119:32 | FailingAssertion | | ExitMethods.cs:121:23:121:27 | false | ExitMethods.cs:119:17:119:32 | FailingAssertion | | ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | ExitMethods.cs:125:17:125:33 | FailingAssertion2 | @@ -1600,12 +1616,13 @@ nodeEnclosing | ExitMethods.cs:127:9:127:27 | ...; | ExitMethods.cs:125:17:125:33 | FailingAssertion2 | | ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:10:131:20 | AssertFalse | | ExitMethods.cs:131:10:131:20 | exit AssertFalse | ExitMethods.cs:131:10:131:20 | AssertFalse | -| ExitMethods.cs:131:33:131:49 | call to method IsFalse | ExitMethods.cs:131:10:131:20 | AssertFalse | +| ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:131:10:131:20 | AssertFalse | +| ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | ExitMethods.cs:131:10:131:20 | AssertFalse | | ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:10:131:20 | AssertFalse | | ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | | ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | | ExitMethods.cs:134:5:137:5 | {...} | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | -| ExitMethods.cs:135:9:135:25 | call to method AssertFalse | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | +| ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | | ExitMethods.cs:135:9:135:25 | this access | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | | ExitMethods.cs:135:9:135:26 | ...; | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | | ExitMethods.cs:135:21:135:24 | true | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | @@ -4145,75 +4162,124 @@ blockEnclosing | ArrayCreation.cs:7:11:7:12 | enter M3 | ArrayCreation.cs:7:11:7:12 | M3 | | ArrayCreation.cs:9:12:9:13 | enter M4 | ArrayCreation.cs:9:12:9:13 | M4 | | Assert.cs:7:10:7:11 | enter M1 | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:7:10:7:11 | exit M1 | Assert.cs:7:10:7:11 | M1 | | Assert.cs:9:16:9:32 | String s = ... | Assert.cs:7:10:7:11 | M1 | | Assert.cs:9:24:9:27 | null | Assert.cs:7:10:7:11 | M1 | | Assert.cs:9:31:9:32 | "" | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | Assert.cs:7:10:7:11 | M1 | +| Assert.cs:10:9:10:31 | [assertion success] call to method Assert | Assert.cs:7:10:7:11 | M1 | | Assert.cs:14:10:14:11 | enter M2 | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:14:10:14:11 | exit M2 | Assert.cs:14:10:14:11 | M2 | | Assert.cs:16:16:16:32 | String s = ... | Assert.cs:14:10:14:11 | M2 | | Assert.cs:16:24:16:27 | null | Assert.cs:14:10:14:11 | M2 | | Assert.cs:16:31:16:32 | "" | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | Assert.cs:14:10:14:11 | M2 | +| Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | Assert.cs:14:10:14:11 | M2 | | Assert.cs:21:10:21:11 | enter M3 | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:21:10:21:11 | exit M3 | Assert.cs:21:10:21:11 | M3 | | Assert.cs:23:16:23:32 | String s = ... | Assert.cs:21:10:21:11 | M3 | | Assert.cs:23:24:23:27 | null | Assert.cs:21:10:21:11 | M3 | | Assert.cs:23:31:23:32 | "" | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | Assert.cs:21:10:21:11 | M3 | +| Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | Assert.cs:21:10:21:11 | M3 | | Assert.cs:28:10:28:11 | enter M4 | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:28:10:28:11 | exit M4 | Assert.cs:28:10:28:11 | M4 | | Assert.cs:30:16:30:32 | String s = ... | Assert.cs:28:10:28:11 | M4 | | Assert.cs:30:24:30:27 | null | Assert.cs:28:10:28:11 | M4 | | Assert.cs:30:31:30:32 | "" | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | Assert.cs:28:10:28:11 | M4 | +| Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | Assert.cs:28:10:28:11 | M4 | | Assert.cs:35:10:35:11 | enter M5 | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:35:10:35:11 | exit M5 | Assert.cs:35:10:35:11 | M5 | | Assert.cs:37:16:37:32 | String s = ... | Assert.cs:35:10:35:11 | M5 | | Assert.cs:37:24:37:27 | null | Assert.cs:35:10:35:11 | M5 | | Assert.cs:37:31:37:32 | "" | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | Assert.cs:35:10:35:11 | M5 | +| Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | Assert.cs:35:10:35:11 | M5 | | Assert.cs:42:10:42:11 | enter M6 | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:42:10:42:11 | exit M6 | Assert.cs:42:10:42:11 | M6 | | Assert.cs:44:16:44:32 | String s = ... | Assert.cs:42:10:42:11 | M6 | | Assert.cs:44:24:44:27 | null | Assert.cs:42:10:42:11 | M6 | | Assert.cs:44:31:44:32 | "" | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | Assert.cs:42:10:42:11 | M6 | +| Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | Assert.cs:42:10:42:11 | M6 | | Assert.cs:49:10:49:11 | enter M7 | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:49:10:49:11 | exit M7 | Assert.cs:49:10:49:11 | M7 | | Assert.cs:51:16:51:32 | String s = ... | Assert.cs:49:10:49:11 | M7 | | Assert.cs:51:24:51:27 | null | Assert.cs:49:10:49:11 | M7 | | Assert.cs:51:31:51:32 | "" | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | Assert.cs:49:10:49:11 | M7 | +| Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | Assert.cs:49:10:49:11 | M7 | | Assert.cs:56:10:56:11 | enter M8 | Assert.cs:56:10:56:11 | M8 | -| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:56:10:56:11 | M8 | -| Assert.cs:58:24:58:27 | null | Assert.cs:56:10:56:11 | M8 | -| Assert.cs:58:31:58:32 | "" | Assert.cs:56:10:56:11 | M8 | -| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:56:10:56:11 | M8 | -| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:56:10:56:11 | exit M8 | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:58:24:58:27 | [b (line 56): true] null | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:58:31:58:32 | [b (line 56): false] "" | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | Assert.cs:56:10:56:11 | M8 | +| Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | Assert.cs:56:10:56:11 | M8 | | Assert.cs:63:10:63:11 | enter M9 | Assert.cs:63:10:63:11 | M9 | -| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:63:10:63:11 | M9 | -| Assert.cs:65:24:65:27 | null | Assert.cs:63:10:63:11 | M9 | -| Assert.cs:65:31:65:32 | "" | Assert.cs:63:10:63:11 | M9 | -| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:63:10:63:11 | M9 | -| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:63:10:63:11 | exit M9 | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:65:24:65:27 | [b (line 63): true] null | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:65:31:65:32 | [b (line 63): false] "" | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | Assert.cs:63:10:63:11 | M9 | +| Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | Assert.cs:63:10:63:11 | M9 | | Assert.cs:70:10:70:12 | enter M10 | Assert.cs:70:10:70:12 | M10 | -| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:70:10:70:12 | M10 | -| Assert.cs:72:24:72:27 | null | Assert.cs:70:10:70:12 | M10 | -| Assert.cs:72:31:72:32 | "" | Assert.cs:70:10:70:12 | M10 | -| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:70:10:70:12 | M10 | -| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:70:10:70:12 | exit M10 | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:72:24:72:27 | [b (line 70): true] null | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:72:31:72:32 | [b (line 70): false] "" | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | Assert.cs:70:10:70:12 | M10 | +| Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | Assert.cs:70:10:70:12 | M10 | | Assert.cs:77:10:77:12 | enter M11 | Assert.cs:77:10:77:12 | M11 | -| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:77:10:77:12 | M11 | -| Assert.cs:79:24:79:27 | null | Assert.cs:77:10:77:12 | M11 | -| Assert.cs:79:31:79:32 | "" | Assert.cs:77:10:77:12 | M11 | -| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:77:10:77:12 | M11 | -| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:77:10:77:12 | exit M11 | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:79:24:79:27 | [b (line 77): true] null | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:79:31:79:32 | [b (line 77): false] "" | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | Assert.cs:77:10:77:12 | M11 | +| Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | Assert.cs:77:10:77:12 | M11 | | Assert.cs:84:10:84:12 | enter M12 | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:84:10:84:12 | exit M12 | Assert.cs:84:10:84:12 | M12 | | Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:84:10:84:12 | M12 | | Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:119:37:119:38 | [b (line 84): false] !... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | | Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | M12 | | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:84:10:84:12 | M12 | -| Assert.cs:127:37:127:38 | !... | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | Assert.cs:84:10:84:12 | M12 | +| Assert.cs:127:37:127:38 | [b (line 84): true] !... | Assert.cs:84:10:84:12 | M12 | | Assignments.cs:3:10:3:10 | enter M | Assignments.cs:3:10:3:10 | M | | Assignments.cs:14:18:14:35 | enter (...) => ... | Assignments.cs:14:18:14:35 | (...) => ... | | Assignments.cs:17:40:17:40 | enter + | Assignments.cs:17:40:17:40 | + | @@ -4404,6 +4470,9 @@ blockEnclosing | ExitMethods.cs:119:17:119:32 | enter FailingAssertion | ExitMethods.cs:119:17:119:32 | FailingAssertion | | ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | ExitMethods.cs:125:17:125:33 | FailingAssertion2 | | ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:10:131:20 | AssertFalse | +| ExitMethods.cs:131:10:131:20 | exit AssertFalse | ExitMethods.cs:131:10:131:20 | AssertFalse | +| ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:131:10:131:20 | AssertFalse | +| ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | ExitMethods.cs:131:10:131:20 | AssertFalse | | ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | ExitMethods.cs:133:17:133:33 | FailingAssertion3 | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:5:23:5:29 | ToInt32 | | Extensions.cs:10:24:10:29 | enter ToBool | Extensions.cs:10:24:10:29 | ToBool | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index 0b700ae4848..f076ed04df5 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -307,6 +307,7 @@ | ArrayCreation.cs:9:43:9:50 | { ..., ... } | ArrayCreation.cs:9:43:9:50 | { ..., ... } | normal | | ArrayCreation.cs:9:45:9:45 | 2 | ArrayCreation.cs:9:45:9:45 | 2 | normal | | ArrayCreation.cs:9:48:9:48 | 3 | ArrayCreation.cs:9:48:9:48 | 3 | normal | +| Assert.cs:8:5:12:5 | {...} | Assert.cs:10:9:10:31 | call to method Assert | exit | | Assert.cs:8:5:12:5 | {...} | Assert.cs:11:9:11:35 | call to method WriteLine | normal | | Assert.cs:9:9:9:33 | ... ...; | Assert.cs:9:16:9:32 | String s = ... | normal | | Assert.cs:9:16:9:32 | String s = ... | Assert.cs:9:16:9:32 | String s = ... | normal | @@ -316,15 +317,19 @@ | Assert.cs:9:20:9:32 | ... ? ... : ... | Assert.cs:9:31:9:32 | "" | normal | | Assert.cs:9:24:9:27 | null | Assert.cs:9:24:9:27 | null | normal | | Assert.cs:9:31:9:32 | "" | Assert.cs:9:31:9:32 | "" | normal | +| Assert.cs:10:9:10:31 | call to method Assert | Assert.cs:10:9:10:31 | call to method Assert | exit | | Assert.cs:10:9:10:31 | call to method Assert | Assert.cs:10:9:10:31 | call to method Assert | normal | +| Assert.cs:10:9:10:32 | ...; | Assert.cs:10:9:10:31 | call to method Assert | exit | | Assert.cs:10:9:10:32 | ...; | Assert.cs:10:9:10:31 | call to method Assert | normal | | Assert.cs:10:22:10:22 | access to local variable s | Assert.cs:10:22:10:22 | access to local variable s | normal | -| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:22:10:30 | ... != ... | normal | +| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:22:10:30 | ... != ... | false | +| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:22:10:30 | ... != ... | true | | Assert.cs:10:27:10:30 | null | Assert.cs:10:27:10:30 | null | normal | | Assert.cs:11:9:11:35 | call to method WriteLine | Assert.cs:11:9:11:35 | call to method WriteLine | normal | | Assert.cs:11:9:11:36 | ...; | Assert.cs:11:9:11:35 | call to method WriteLine | normal | | Assert.cs:11:27:11:27 | access to local variable s | Assert.cs:11:27:11:27 | access to local variable s | normal | | Assert.cs:11:27:11:34 | access to property Length | Assert.cs:11:27:11:34 | access to property Length | normal | +| Assert.cs:15:5:19:5 | {...} | Assert.cs:17:9:17:24 | call to method IsNull | throw(AssertFailedException) | | Assert.cs:15:5:19:5 | {...} | Assert.cs:18:9:18:35 | call to method WriteLine | normal | | Assert.cs:16:9:16:33 | ... ...; | Assert.cs:16:16:16:32 | String s = ... | normal | | Assert.cs:16:16:16:32 | String s = ... | Assert.cs:16:16:16:32 | String s = ... | normal | @@ -335,12 +340,16 @@ | Assert.cs:16:24:16:27 | null | Assert.cs:16:24:16:27 | null | normal | | Assert.cs:16:31:16:32 | "" | Assert.cs:16:31:16:32 | "" | normal | | Assert.cs:17:9:17:24 | call to method IsNull | Assert.cs:17:9:17:24 | call to method IsNull | normal | +| Assert.cs:17:9:17:24 | call to method IsNull | Assert.cs:17:9:17:24 | call to method IsNull | throw(AssertFailedException) | | Assert.cs:17:9:17:25 | ...; | Assert.cs:17:9:17:24 | call to method IsNull | normal | -| Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:17:23:17:23 | access to local variable s | normal | +| Assert.cs:17:9:17:25 | ...; | Assert.cs:17:9:17:24 | call to method IsNull | throw(AssertFailedException) | +| Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:17:23:17:23 | access to local variable s | non-null | +| Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:17:23:17:23 | access to local variable s | null | | Assert.cs:18:9:18:35 | call to method WriteLine | Assert.cs:18:9:18:35 | call to method WriteLine | normal | | Assert.cs:18:9:18:36 | ...; | Assert.cs:18:9:18:35 | call to method WriteLine | normal | | Assert.cs:18:27:18:27 | access to local variable s | Assert.cs:18:27:18:27 | access to local variable s | normal | | Assert.cs:18:27:18:34 | access to property Length | Assert.cs:18:27:18:34 | access to property Length | normal | +| Assert.cs:22:5:26:5 | {...} | Assert.cs:24:9:24:27 | call to method IsNotNull | throw(AssertFailedException) | | Assert.cs:22:5:26:5 | {...} | Assert.cs:25:9:25:35 | call to method WriteLine | normal | | Assert.cs:23:9:23:33 | ... ...; | Assert.cs:23:16:23:32 | String s = ... | normal | | Assert.cs:23:16:23:32 | String s = ... | Assert.cs:23:16:23:32 | String s = ... | normal | @@ -351,12 +360,16 @@ | Assert.cs:23:24:23:27 | null | Assert.cs:23:24:23:27 | null | normal | | Assert.cs:23:31:23:32 | "" | Assert.cs:23:31:23:32 | "" | normal | | Assert.cs:24:9:24:27 | call to method IsNotNull | Assert.cs:24:9:24:27 | call to method IsNotNull | normal | +| Assert.cs:24:9:24:27 | call to method IsNotNull | Assert.cs:24:9:24:27 | call to method IsNotNull | throw(AssertFailedException) | | Assert.cs:24:9:24:28 | ...; | Assert.cs:24:9:24:27 | call to method IsNotNull | normal | -| Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:24:26:24:26 | access to local variable s | normal | +| Assert.cs:24:9:24:28 | ...; | Assert.cs:24:9:24:27 | call to method IsNotNull | throw(AssertFailedException) | +| Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:24:26:24:26 | access to local variable s | non-null | +| Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:24:26:24:26 | access to local variable s | null | | Assert.cs:25:9:25:35 | call to method WriteLine | Assert.cs:25:9:25:35 | call to method WriteLine | normal | | Assert.cs:25:9:25:36 | ...; | Assert.cs:25:9:25:35 | call to method WriteLine | normal | | Assert.cs:25:27:25:27 | access to local variable s | Assert.cs:25:27:25:27 | access to local variable s | normal | | Assert.cs:25:27:25:34 | access to property Length | Assert.cs:25:27:25:34 | access to property Length | normal | +| Assert.cs:29:5:33:5 | {...} | Assert.cs:31:9:31:32 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:29:5:33:5 | {...} | Assert.cs:32:9:32:35 | call to method WriteLine | normal | | Assert.cs:30:9:30:33 | ... ...; | Assert.cs:30:16:30:32 | String s = ... | normal | | Assert.cs:30:16:30:32 | String s = ... | Assert.cs:30:16:30:32 | String s = ... | normal | @@ -367,14 +380,18 @@ | Assert.cs:30:24:30:27 | null | Assert.cs:30:24:30:27 | null | normal | | Assert.cs:30:31:30:32 | "" | Assert.cs:30:31:30:32 | "" | normal | | Assert.cs:31:9:31:32 | call to method IsTrue | Assert.cs:31:9:31:32 | call to method IsTrue | normal | +| Assert.cs:31:9:31:32 | call to method IsTrue | Assert.cs:31:9:31:32 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:31:9:31:33 | ...; | Assert.cs:31:9:31:32 | call to method IsTrue | normal | +| Assert.cs:31:9:31:33 | ...; | Assert.cs:31:9:31:32 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:31:23:31:23 | access to local variable s | Assert.cs:31:23:31:23 | access to local variable s | normal | -| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:23:31:31 | ... == ... | normal | +| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:23:31:31 | ... == ... | false | +| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:23:31:31 | ... == ... | true | | Assert.cs:31:28:31:31 | null | Assert.cs:31:28:31:31 | null | normal | | Assert.cs:32:9:32:35 | call to method WriteLine | Assert.cs:32:9:32:35 | call to method WriteLine | normal | | Assert.cs:32:9:32:36 | ...; | Assert.cs:32:9:32:35 | call to method WriteLine | normal | | Assert.cs:32:27:32:27 | access to local variable s | Assert.cs:32:27:32:27 | access to local variable s | normal | | Assert.cs:32:27:32:34 | access to property Length | Assert.cs:32:27:32:34 | access to property Length | normal | +| Assert.cs:36:5:40:5 | {...} | Assert.cs:38:9:38:32 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:36:5:40:5 | {...} | Assert.cs:39:9:39:35 | call to method WriteLine | normal | | Assert.cs:37:9:37:33 | ... ...; | Assert.cs:37:16:37:32 | String s = ... | normal | | Assert.cs:37:16:37:32 | String s = ... | Assert.cs:37:16:37:32 | String s = ... | normal | @@ -385,14 +402,18 @@ | Assert.cs:37:24:37:27 | null | Assert.cs:37:24:37:27 | null | normal | | Assert.cs:37:31:37:32 | "" | Assert.cs:37:31:37:32 | "" | normal | | Assert.cs:38:9:38:32 | call to method IsTrue | Assert.cs:38:9:38:32 | call to method IsTrue | normal | +| Assert.cs:38:9:38:32 | call to method IsTrue | Assert.cs:38:9:38:32 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:38:9:38:33 | ...; | Assert.cs:38:9:38:32 | call to method IsTrue | normal | +| Assert.cs:38:9:38:33 | ...; | Assert.cs:38:9:38:32 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:38:23:38:23 | access to local variable s | Assert.cs:38:23:38:23 | access to local variable s | normal | -| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:23:38:31 | ... != ... | normal | +| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:23:38:31 | ... != ... | false | +| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:23:38:31 | ... != ... | true | | Assert.cs:38:28:38:31 | null | Assert.cs:38:28:38:31 | null | normal | | Assert.cs:39:9:39:35 | call to method WriteLine | Assert.cs:39:9:39:35 | call to method WriteLine | normal | | Assert.cs:39:9:39:36 | ...; | Assert.cs:39:9:39:35 | call to method WriteLine | normal | | Assert.cs:39:27:39:27 | access to local variable s | Assert.cs:39:27:39:27 | access to local variable s | normal | | Assert.cs:39:27:39:34 | access to property Length | Assert.cs:39:27:39:34 | access to property Length | normal | +| Assert.cs:43:5:47:5 | {...} | Assert.cs:45:9:45:33 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:43:5:47:5 | {...} | Assert.cs:46:9:46:35 | call to method WriteLine | normal | | Assert.cs:44:9:44:33 | ... ...; | Assert.cs:44:16:44:32 | String s = ... | normal | | Assert.cs:44:16:44:32 | String s = ... | Assert.cs:44:16:44:32 | String s = ... | normal | @@ -403,14 +424,18 @@ | Assert.cs:44:24:44:27 | null | Assert.cs:44:24:44:27 | null | normal | | Assert.cs:44:31:44:32 | "" | Assert.cs:44:31:44:32 | "" | normal | | Assert.cs:45:9:45:33 | call to method IsFalse | Assert.cs:45:9:45:33 | call to method IsFalse | normal | +| Assert.cs:45:9:45:33 | call to method IsFalse | Assert.cs:45:9:45:33 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:45:9:45:34 | ...; | Assert.cs:45:9:45:33 | call to method IsFalse | normal | +| Assert.cs:45:9:45:34 | ...; | Assert.cs:45:9:45:33 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:45:24:45:24 | access to local variable s | Assert.cs:45:24:45:24 | access to local variable s | normal | -| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:24:45:32 | ... != ... | normal | +| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:24:45:32 | ... != ... | false | +| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:24:45:32 | ... != ... | true | | Assert.cs:45:29:45:32 | null | Assert.cs:45:29:45:32 | null | normal | | Assert.cs:46:9:46:35 | call to method WriteLine | Assert.cs:46:9:46:35 | call to method WriteLine | normal | | Assert.cs:46:9:46:36 | ...; | Assert.cs:46:9:46:35 | call to method WriteLine | normal | | Assert.cs:46:27:46:27 | access to local variable s | Assert.cs:46:27:46:27 | access to local variable s | normal | | Assert.cs:46:27:46:34 | access to property Length | Assert.cs:46:27:46:34 | access to property Length | normal | +| Assert.cs:50:5:54:5 | {...} | Assert.cs:52:9:52:33 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:50:5:54:5 | {...} | Assert.cs:53:9:53:35 | call to method WriteLine | normal | | Assert.cs:51:9:51:33 | ... ...; | Assert.cs:51:16:51:32 | String s = ... | normal | | Assert.cs:51:16:51:32 | String s = ... | Assert.cs:51:16:51:32 | String s = ... | normal | @@ -421,14 +446,18 @@ | Assert.cs:51:24:51:27 | null | Assert.cs:51:24:51:27 | null | normal | | Assert.cs:51:31:51:32 | "" | Assert.cs:51:31:51:32 | "" | normal | | Assert.cs:52:9:52:33 | call to method IsFalse | Assert.cs:52:9:52:33 | call to method IsFalse | normal | +| Assert.cs:52:9:52:33 | call to method IsFalse | Assert.cs:52:9:52:33 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:52:9:52:34 | ...; | Assert.cs:52:9:52:33 | call to method IsFalse | normal | +| Assert.cs:52:9:52:34 | ...; | Assert.cs:52:9:52:33 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:52:24:52:24 | access to local variable s | Assert.cs:52:24:52:24 | access to local variable s | normal | -| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:24:52:32 | ... == ... | normal | +| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:24:52:32 | ... == ... | false | +| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:24:52:32 | ... == ... | true | | Assert.cs:52:29:52:32 | null | Assert.cs:52:29:52:32 | null | normal | | Assert.cs:53:9:53:35 | call to method WriteLine | Assert.cs:53:9:53:35 | call to method WriteLine | normal | | Assert.cs:53:9:53:36 | ...; | Assert.cs:53:9:53:35 | call to method WriteLine | normal | | Assert.cs:53:27:53:27 | access to local variable s | Assert.cs:53:27:53:27 | access to local variable s | normal | | Assert.cs:53:27:53:34 | access to property Length | Assert.cs:53:27:53:34 | access to property Length | normal | +| Assert.cs:57:5:61:5 | {...} | Assert.cs:59:9:59:37 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:57:5:61:5 | {...} | Assert.cs:60:9:60:35 | call to method WriteLine | normal | | Assert.cs:58:9:58:33 | ... ...; | Assert.cs:58:16:58:32 | String s = ... | normal | | Assert.cs:58:16:58:32 | String s = ... | Assert.cs:58:16:58:32 | String s = ... | normal | @@ -439,18 +468,23 @@ | Assert.cs:58:24:58:27 | null | Assert.cs:58:24:58:27 | null | normal | | Assert.cs:58:31:58:32 | "" | Assert.cs:58:31:58:32 | "" | normal | | Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:59:9:59:37 | call to method IsTrue | normal | +| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:59:9:59:37 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:59:9:59:38 | ...; | Assert.cs:59:9:59:37 | call to method IsTrue | normal | +| Assert.cs:59:9:59:38 | ...; | Assert.cs:59:9:59:37 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:59:23:59:23 | access to local variable s | Assert.cs:59:23:59:23 | access to local variable s | normal | | Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:23:59:31 | ... != ... | false | | Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:23:59:31 | ... != ... | true | | Assert.cs:59:23:59:36 | ... && ... | Assert.cs:59:23:59:31 | ... != ... | false | -| Assert.cs:59:23:59:36 | ... && ... | Assert.cs:59:36:59:36 | access to parameter b | normal | +| Assert.cs:59:23:59:36 | ... && ... | Assert.cs:59:36:59:36 | access to parameter b | false | +| Assert.cs:59:23:59:36 | ... && ... | Assert.cs:59:36:59:36 | access to parameter b | true | | Assert.cs:59:28:59:31 | null | Assert.cs:59:28:59:31 | null | normal | -| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:59:36:59:36 | access to parameter b | normal | +| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:59:36:59:36 | access to parameter b | false | +| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:59:36:59:36 | access to parameter b | true | | Assert.cs:60:9:60:35 | call to method WriteLine | Assert.cs:60:9:60:35 | call to method WriteLine | normal | | Assert.cs:60:9:60:36 | ...; | Assert.cs:60:9:60:35 | call to method WriteLine | normal | | Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:60:27:60:27 | access to local variable s | normal | | Assert.cs:60:27:60:34 | access to property Length | Assert.cs:60:27:60:34 | access to property Length | normal | +| Assert.cs:64:5:68:5 | {...} | Assert.cs:66:9:66:38 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:64:5:68:5 | {...} | Assert.cs:67:9:67:35 | call to method WriteLine | normal | | Assert.cs:65:9:65:33 | ... ...; | Assert.cs:65:16:65:32 | String s = ... | normal | | Assert.cs:65:16:65:32 | String s = ... | Assert.cs:65:16:65:32 | String s = ... | normal | @@ -461,18 +495,23 @@ | Assert.cs:65:24:65:27 | null | Assert.cs:65:24:65:27 | null | normal | | Assert.cs:65:31:65:32 | "" | Assert.cs:65:31:65:32 | "" | normal | | Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:66:9:66:38 | call to method IsFalse | normal | +| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:66:9:66:38 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:66:9:66:39 | ...; | Assert.cs:66:9:66:38 | call to method IsFalse | normal | +| Assert.cs:66:9:66:39 | ...; | Assert.cs:66:9:66:38 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:66:24:66:24 | access to local variable s | Assert.cs:66:24:66:24 | access to local variable s | normal | | Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:24:66:32 | ... == ... | false | | Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:24:66:32 | ... == ... | true | | Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:66:24:66:32 | ... == ... | true | -| Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:66:37:66:37 | access to parameter b | normal | +| Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:66:37:66:37 | access to parameter b | false | +| Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:66:37:66:37 | access to parameter b | true | | Assert.cs:66:29:66:32 | null | Assert.cs:66:29:66:32 | null | normal | -| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:66:37:66:37 | access to parameter b | normal | +| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:66:37:66:37 | access to parameter b | false | +| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:66:37:66:37 | access to parameter b | true | | Assert.cs:67:9:67:35 | call to method WriteLine | Assert.cs:67:9:67:35 | call to method WriteLine | normal | | Assert.cs:67:9:67:36 | ...; | Assert.cs:67:9:67:35 | call to method WriteLine | normal | | Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:67:27:67:27 | access to local variable s | normal | | Assert.cs:67:27:67:34 | access to property Length | Assert.cs:67:27:67:34 | access to property Length | normal | +| Assert.cs:71:5:75:5 | {...} | Assert.cs:73:9:73:37 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:71:5:75:5 | {...} | Assert.cs:74:9:74:35 | call to method WriteLine | normal | | Assert.cs:72:9:72:33 | ... ...; | Assert.cs:72:16:72:32 | String s = ... | normal | | Assert.cs:72:16:72:32 | String s = ... | Assert.cs:72:16:72:32 | String s = ... | normal | @@ -483,18 +522,23 @@ | Assert.cs:72:24:72:27 | null | Assert.cs:72:24:72:27 | null | normal | | Assert.cs:72:31:72:32 | "" | Assert.cs:72:31:72:32 | "" | normal | | Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:73:9:73:37 | call to method IsTrue | normal | +| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:73:9:73:37 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:73:9:73:38 | ...; | Assert.cs:73:9:73:37 | call to method IsTrue | normal | +| Assert.cs:73:9:73:38 | ...; | Assert.cs:73:9:73:37 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:73:23:73:23 | access to local variable s | Assert.cs:73:23:73:23 | access to local variable s | normal | | Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:23:73:31 | ... == ... | false | | Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:23:73:31 | ... == ... | true | | Assert.cs:73:23:73:36 | ... && ... | Assert.cs:73:23:73:31 | ... == ... | false | -| Assert.cs:73:23:73:36 | ... && ... | Assert.cs:73:36:73:36 | access to parameter b | normal | +| Assert.cs:73:23:73:36 | ... && ... | Assert.cs:73:36:73:36 | access to parameter b | false | +| Assert.cs:73:23:73:36 | ... && ... | Assert.cs:73:36:73:36 | access to parameter b | true | | Assert.cs:73:28:73:31 | null | Assert.cs:73:28:73:31 | null | normal | -| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:73:36:73:36 | access to parameter b | normal | +| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:73:36:73:36 | access to parameter b | false | +| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:73:36:73:36 | access to parameter b | true | | Assert.cs:74:9:74:35 | call to method WriteLine | Assert.cs:74:9:74:35 | call to method WriteLine | normal | | Assert.cs:74:9:74:36 | ...; | Assert.cs:74:9:74:35 | call to method WriteLine | normal | | Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:74:27:74:27 | access to local variable s | normal | | Assert.cs:74:27:74:34 | access to property Length | Assert.cs:74:27:74:34 | access to property Length | normal | +| Assert.cs:78:5:82:5 | {...} | Assert.cs:80:9:80:38 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:78:5:82:5 | {...} | Assert.cs:81:9:81:35 | call to method WriteLine | normal | | Assert.cs:79:9:79:33 | ... ...; | Assert.cs:79:16:79:32 | String s = ... | normal | | Assert.cs:79:16:79:32 | String s = ... | Assert.cs:79:16:79:32 | String s = ... | normal | @@ -505,18 +549,33 @@ | Assert.cs:79:24:79:27 | null | Assert.cs:79:24:79:27 | null | normal | | Assert.cs:79:31:79:32 | "" | Assert.cs:79:31:79:32 | "" | normal | | Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:80:9:80:38 | call to method IsFalse | normal | +| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:80:9:80:38 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:80:9:80:39 | ...; | Assert.cs:80:9:80:38 | call to method IsFalse | normal | +| Assert.cs:80:9:80:39 | ...; | Assert.cs:80:9:80:38 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:80:24:80:24 | access to local variable s | Assert.cs:80:24:80:24 | access to local variable s | normal | | Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:24:80:32 | ... != ... | false | | Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:24:80:32 | ... != ... | true | | Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:24:80:32 | ... != ... | true | -| Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:37:80:37 | access to parameter b | normal | +| Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:37:80:37 | access to parameter b | false | +| Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:37:80:37 | access to parameter b | true | | Assert.cs:80:29:80:32 | null | Assert.cs:80:29:80:32 | null | normal | -| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:80:37:80:37 | access to parameter b | normal | +| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:80:37:80:37 | access to parameter b | false | +| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:80:37:80:37 | access to parameter b | true | | Assert.cs:81:9:81:35 | call to method WriteLine | Assert.cs:81:9:81:35 | call to method WriteLine | normal | | Assert.cs:81:9:81:36 | ...; | Assert.cs:81:9:81:35 | call to method WriteLine | normal | | Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:81:27:81:27 | access to local variable s | normal | | Assert.cs:81:27:81:34 | access to property Length | Assert.cs:81:27:81:34 | access to property Length | normal | +| Assert.cs:85:5:129:5 | {...} | Assert.cs:87:9:87:31 | call to method Assert | exit | +| Assert.cs:85:5:129:5 | {...} | Assert.cs:91:9:91:24 | call to method IsNull | throw(AssertFailedException) | +| Assert.cs:85:5:129:5 | {...} | Assert.cs:95:9:95:27 | call to method IsNotNull | throw(AssertFailedException) | +| Assert.cs:85:5:129:5 | {...} | Assert.cs:99:9:99:32 | call to method IsTrue | throw(AssertFailedException) | +| Assert.cs:85:5:129:5 | {...} | Assert.cs:103:9:103:32 | call to method IsTrue | throw(AssertFailedException) | +| Assert.cs:85:5:129:5 | {...} | Assert.cs:107:9:107:33 | call to method IsFalse | throw(AssertFailedException) | +| Assert.cs:85:5:129:5 | {...} | Assert.cs:111:9:111:33 | call to method IsFalse | throw(AssertFailedException) | +| Assert.cs:85:5:129:5 | {...} | Assert.cs:115:9:115:37 | call to method IsTrue | throw(AssertFailedException) | +| Assert.cs:85:5:129:5 | {...} | Assert.cs:119:9:119:39 | call to method IsFalse | throw(AssertFailedException) | +| Assert.cs:85:5:129:5 | {...} | Assert.cs:123:9:123:37 | call to method IsTrue | throw(AssertFailedException) | +| Assert.cs:85:5:129:5 | {...} | Assert.cs:127:9:127:39 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:85:5:129:5 | {...} | Assert.cs:128:9:128:35 | call to method WriteLine | normal | | Assert.cs:86:9:86:33 | ... ...; | Assert.cs:86:16:86:32 | String s = ... | normal | | Assert.cs:86:16:86:32 | String s = ... | Assert.cs:86:16:86:32 | String s = ... | normal | @@ -526,10 +585,13 @@ | Assert.cs:86:20:86:32 | ... ? ... : ... | Assert.cs:86:31:86:32 | "" | normal | | Assert.cs:86:24:86:27 | null | Assert.cs:86:24:86:27 | null | normal | | Assert.cs:86:31:86:32 | "" | Assert.cs:86:31:86:32 | "" | normal | +| Assert.cs:87:9:87:31 | call to method Assert | Assert.cs:87:9:87:31 | call to method Assert | exit | | Assert.cs:87:9:87:31 | call to method Assert | Assert.cs:87:9:87:31 | call to method Assert | normal | +| Assert.cs:87:9:87:32 | ...; | Assert.cs:87:9:87:31 | call to method Assert | exit | | Assert.cs:87:9:87:32 | ...; | Assert.cs:87:9:87:31 | call to method Assert | normal | | Assert.cs:87:22:87:22 | access to local variable s | Assert.cs:87:22:87:22 | access to local variable s | normal | -| Assert.cs:87:22:87:30 | ... != ... | Assert.cs:87:22:87:30 | ... != ... | normal | +| Assert.cs:87:22:87:30 | ... != ... | Assert.cs:87:22:87:30 | ... != ... | false | +| Assert.cs:87:22:87:30 | ... != ... | Assert.cs:87:22:87:30 | ... != ... | true | | Assert.cs:87:27:87:30 | null | Assert.cs:87:27:87:30 | null | normal | | Assert.cs:88:9:88:35 | call to method WriteLine | Assert.cs:88:9:88:35 | call to method WriteLine | normal | | Assert.cs:88:9:88:36 | ...; | Assert.cs:88:9:88:35 | call to method WriteLine | normal | @@ -544,8 +606,11 @@ | Assert.cs:90:17:90:20 | null | Assert.cs:90:17:90:20 | null | normal | | Assert.cs:90:24:90:25 | "" | Assert.cs:90:24:90:25 | "" | normal | | Assert.cs:91:9:91:24 | call to method IsNull | Assert.cs:91:9:91:24 | call to method IsNull | normal | +| Assert.cs:91:9:91:24 | call to method IsNull | Assert.cs:91:9:91:24 | call to method IsNull | throw(AssertFailedException) | | Assert.cs:91:9:91:25 | ...; | Assert.cs:91:9:91:24 | call to method IsNull | normal | -| Assert.cs:91:23:91:23 | access to local variable s | Assert.cs:91:23:91:23 | access to local variable s | normal | +| Assert.cs:91:9:91:25 | ...; | Assert.cs:91:9:91:24 | call to method IsNull | throw(AssertFailedException) | +| Assert.cs:91:23:91:23 | access to local variable s | Assert.cs:91:23:91:23 | access to local variable s | non-null | +| Assert.cs:91:23:91:23 | access to local variable s | Assert.cs:91:23:91:23 | access to local variable s | null | | Assert.cs:92:9:92:35 | call to method WriteLine | Assert.cs:92:9:92:35 | call to method WriteLine | normal | | Assert.cs:92:9:92:36 | ...; | Assert.cs:92:9:92:35 | call to method WriteLine | normal | | Assert.cs:92:27:92:27 | access to local variable s | Assert.cs:92:27:92:27 | access to local variable s | normal | @@ -559,8 +624,11 @@ | Assert.cs:94:17:94:20 | null | Assert.cs:94:17:94:20 | null | normal | | Assert.cs:94:24:94:25 | "" | Assert.cs:94:24:94:25 | "" | normal | | Assert.cs:95:9:95:27 | call to method IsNotNull | Assert.cs:95:9:95:27 | call to method IsNotNull | normal | +| Assert.cs:95:9:95:27 | call to method IsNotNull | Assert.cs:95:9:95:27 | call to method IsNotNull | throw(AssertFailedException) | | Assert.cs:95:9:95:28 | ...; | Assert.cs:95:9:95:27 | call to method IsNotNull | normal | -| Assert.cs:95:26:95:26 | access to local variable s | Assert.cs:95:26:95:26 | access to local variable s | normal | +| Assert.cs:95:9:95:28 | ...; | Assert.cs:95:9:95:27 | call to method IsNotNull | throw(AssertFailedException) | +| Assert.cs:95:26:95:26 | access to local variable s | Assert.cs:95:26:95:26 | access to local variable s | non-null | +| Assert.cs:95:26:95:26 | access to local variable s | Assert.cs:95:26:95:26 | access to local variable s | null | | Assert.cs:96:9:96:35 | call to method WriteLine | Assert.cs:96:9:96:35 | call to method WriteLine | normal | | Assert.cs:96:9:96:36 | ...; | Assert.cs:96:9:96:35 | call to method WriteLine | normal | | Assert.cs:96:27:96:27 | access to local variable s | Assert.cs:96:27:96:27 | access to local variable s | normal | @@ -574,9 +642,12 @@ | Assert.cs:98:17:98:20 | null | Assert.cs:98:17:98:20 | null | normal | | Assert.cs:98:24:98:25 | "" | Assert.cs:98:24:98:25 | "" | normal | | Assert.cs:99:9:99:32 | call to method IsTrue | Assert.cs:99:9:99:32 | call to method IsTrue | normal | +| Assert.cs:99:9:99:32 | call to method IsTrue | Assert.cs:99:9:99:32 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:99:9:99:33 | ...; | Assert.cs:99:9:99:32 | call to method IsTrue | normal | +| Assert.cs:99:9:99:33 | ...; | Assert.cs:99:9:99:32 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:99:23:99:23 | access to local variable s | Assert.cs:99:23:99:23 | access to local variable s | normal | -| Assert.cs:99:23:99:31 | ... == ... | Assert.cs:99:23:99:31 | ... == ... | normal | +| Assert.cs:99:23:99:31 | ... == ... | Assert.cs:99:23:99:31 | ... == ... | false | +| Assert.cs:99:23:99:31 | ... == ... | Assert.cs:99:23:99:31 | ... == ... | true | | Assert.cs:99:28:99:31 | null | Assert.cs:99:28:99:31 | null | normal | | Assert.cs:100:9:100:35 | call to method WriteLine | Assert.cs:100:9:100:35 | call to method WriteLine | normal | | Assert.cs:100:9:100:36 | ...; | Assert.cs:100:9:100:35 | call to method WriteLine | normal | @@ -591,9 +662,12 @@ | Assert.cs:102:17:102:20 | null | Assert.cs:102:17:102:20 | null | normal | | Assert.cs:102:24:102:25 | "" | Assert.cs:102:24:102:25 | "" | normal | | Assert.cs:103:9:103:32 | call to method IsTrue | Assert.cs:103:9:103:32 | call to method IsTrue | normal | +| Assert.cs:103:9:103:32 | call to method IsTrue | Assert.cs:103:9:103:32 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:103:9:103:33 | ...; | Assert.cs:103:9:103:32 | call to method IsTrue | normal | +| Assert.cs:103:9:103:33 | ...; | Assert.cs:103:9:103:32 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:103:23:103:23 | access to local variable s | Assert.cs:103:23:103:23 | access to local variable s | normal | -| Assert.cs:103:23:103:31 | ... != ... | Assert.cs:103:23:103:31 | ... != ... | normal | +| Assert.cs:103:23:103:31 | ... != ... | Assert.cs:103:23:103:31 | ... != ... | false | +| Assert.cs:103:23:103:31 | ... != ... | Assert.cs:103:23:103:31 | ... != ... | true | | Assert.cs:103:28:103:31 | null | Assert.cs:103:28:103:31 | null | normal | | Assert.cs:104:9:104:35 | call to method WriteLine | Assert.cs:104:9:104:35 | call to method WriteLine | normal | | Assert.cs:104:9:104:36 | ...; | Assert.cs:104:9:104:35 | call to method WriteLine | normal | @@ -608,9 +682,12 @@ | Assert.cs:106:17:106:20 | null | Assert.cs:106:17:106:20 | null | normal | | Assert.cs:106:24:106:25 | "" | Assert.cs:106:24:106:25 | "" | normal | | Assert.cs:107:9:107:33 | call to method IsFalse | Assert.cs:107:9:107:33 | call to method IsFalse | normal | +| Assert.cs:107:9:107:33 | call to method IsFalse | Assert.cs:107:9:107:33 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:107:9:107:34 | ...; | Assert.cs:107:9:107:33 | call to method IsFalse | normal | +| Assert.cs:107:9:107:34 | ...; | Assert.cs:107:9:107:33 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:107:24:107:24 | access to local variable s | Assert.cs:107:24:107:24 | access to local variable s | normal | -| Assert.cs:107:24:107:32 | ... != ... | Assert.cs:107:24:107:32 | ... != ... | normal | +| Assert.cs:107:24:107:32 | ... != ... | Assert.cs:107:24:107:32 | ... != ... | false | +| Assert.cs:107:24:107:32 | ... != ... | Assert.cs:107:24:107:32 | ... != ... | true | | Assert.cs:107:29:107:32 | null | Assert.cs:107:29:107:32 | null | normal | | Assert.cs:108:9:108:35 | call to method WriteLine | Assert.cs:108:9:108:35 | call to method WriteLine | normal | | Assert.cs:108:9:108:36 | ...; | Assert.cs:108:9:108:35 | call to method WriteLine | normal | @@ -625,9 +702,12 @@ | Assert.cs:110:17:110:20 | null | Assert.cs:110:17:110:20 | null | normal | | Assert.cs:110:24:110:25 | "" | Assert.cs:110:24:110:25 | "" | normal | | Assert.cs:111:9:111:33 | call to method IsFalse | Assert.cs:111:9:111:33 | call to method IsFalse | normal | +| Assert.cs:111:9:111:33 | call to method IsFalse | Assert.cs:111:9:111:33 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:111:9:111:34 | ...; | Assert.cs:111:9:111:33 | call to method IsFalse | normal | +| Assert.cs:111:9:111:34 | ...; | Assert.cs:111:9:111:33 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:111:24:111:24 | access to local variable s | Assert.cs:111:24:111:24 | access to local variable s | normal | -| Assert.cs:111:24:111:32 | ... == ... | Assert.cs:111:24:111:32 | ... == ... | normal | +| Assert.cs:111:24:111:32 | ... == ... | Assert.cs:111:24:111:32 | ... == ... | false | +| Assert.cs:111:24:111:32 | ... == ... | Assert.cs:111:24:111:32 | ... == ... | true | | Assert.cs:111:29:111:32 | null | Assert.cs:111:29:111:32 | null | normal | | Assert.cs:112:9:112:35 | call to method WriteLine | Assert.cs:112:9:112:35 | call to method WriteLine | normal | | Assert.cs:112:9:112:36 | ...; | Assert.cs:112:9:112:35 | call to method WriteLine | normal | @@ -642,14 +722,18 @@ | Assert.cs:114:17:114:20 | null | Assert.cs:114:17:114:20 | null | normal | | Assert.cs:114:24:114:25 | "" | Assert.cs:114:24:114:25 | "" | normal | | Assert.cs:115:9:115:37 | call to method IsTrue | Assert.cs:115:9:115:37 | call to method IsTrue | normal | +| Assert.cs:115:9:115:37 | call to method IsTrue | Assert.cs:115:9:115:37 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:115:9:115:38 | ...; | Assert.cs:115:9:115:37 | call to method IsTrue | normal | +| Assert.cs:115:9:115:38 | ...; | Assert.cs:115:9:115:37 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:115:23:115:23 | access to local variable s | Assert.cs:115:23:115:23 | access to local variable s | normal | | Assert.cs:115:23:115:31 | ... != ... | Assert.cs:115:23:115:31 | ... != ... | false | | Assert.cs:115:23:115:31 | ... != ... | Assert.cs:115:23:115:31 | ... != ... | true | | Assert.cs:115:23:115:36 | ... && ... | Assert.cs:115:23:115:31 | ... != ... | false | -| Assert.cs:115:23:115:36 | ... && ... | Assert.cs:115:36:115:36 | access to parameter b | normal | +| Assert.cs:115:23:115:36 | ... && ... | Assert.cs:115:36:115:36 | access to parameter b | false | +| Assert.cs:115:23:115:36 | ... && ... | Assert.cs:115:36:115:36 | access to parameter b | true | | Assert.cs:115:28:115:31 | null | Assert.cs:115:28:115:31 | null | normal | -| Assert.cs:115:36:115:36 | access to parameter b | Assert.cs:115:36:115:36 | access to parameter b | normal | +| Assert.cs:115:36:115:36 | access to parameter b | Assert.cs:115:36:115:36 | access to parameter b | false | +| Assert.cs:115:36:115:36 | access to parameter b | Assert.cs:115:36:115:36 | access to parameter b | true | | Assert.cs:116:9:116:35 | call to method WriteLine | Assert.cs:116:9:116:35 | call to method WriteLine | normal | | Assert.cs:116:9:116:36 | ...; | Assert.cs:116:9:116:35 | call to method WriteLine | normal | | Assert.cs:116:27:116:27 | access to local variable s | Assert.cs:116:27:116:27 | access to local variable s | normal | @@ -663,15 +747,20 @@ | Assert.cs:118:17:118:20 | null | Assert.cs:118:17:118:20 | null | normal | | Assert.cs:118:24:118:25 | "" | Assert.cs:118:24:118:25 | "" | normal | | Assert.cs:119:9:119:39 | call to method IsFalse | Assert.cs:119:9:119:39 | call to method IsFalse | normal | +| Assert.cs:119:9:119:39 | call to method IsFalse | Assert.cs:119:9:119:39 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:119:9:119:40 | ...; | Assert.cs:119:9:119:39 | call to method IsFalse | normal | +| Assert.cs:119:9:119:40 | ...; | Assert.cs:119:9:119:39 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:119:24:119:24 | access to local variable s | Assert.cs:119:24:119:24 | access to local variable s | normal | | Assert.cs:119:24:119:32 | ... == ... | Assert.cs:119:24:119:32 | ... == ... | false | | Assert.cs:119:24:119:32 | ... == ... | Assert.cs:119:24:119:32 | ... == ... | true | | Assert.cs:119:24:119:38 | ... \|\| ... | Assert.cs:119:24:119:32 | ... == ... | true | -| Assert.cs:119:24:119:38 | ... \|\| ... | Assert.cs:119:38:119:38 | access to parameter b | normal | +| Assert.cs:119:24:119:38 | ... \|\| ... | Assert.cs:119:38:119:38 | access to parameter b | false [true] | +| Assert.cs:119:24:119:38 | ... \|\| ... | Assert.cs:119:38:119:38 | access to parameter b | true [false] | | Assert.cs:119:29:119:32 | null | Assert.cs:119:29:119:32 | null | normal | -| Assert.cs:119:37:119:38 | !... | Assert.cs:119:38:119:38 | access to parameter b | normal | -| Assert.cs:119:38:119:38 | access to parameter b | Assert.cs:119:38:119:38 | access to parameter b | normal | +| Assert.cs:119:37:119:38 | !... | Assert.cs:119:38:119:38 | access to parameter b | false [true] | +| Assert.cs:119:37:119:38 | !... | Assert.cs:119:38:119:38 | access to parameter b | true [false] | +| Assert.cs:119:38:119:38 | access to parameter b | Assert.cs:119:38:119:38 | access to parameter b | false | +| Assert.cs:119:38:119:38 | access to parameter b | Assert.cs:119:38:119:38 | access to parameter b | true | | Assert.cs:120:9:120:35 | call to method WriteLine | Assert.cs:120:9:120:35 | call to method WriteLine | normal | | Assert.cs:120:9:120:36 | ...; | Assert.cs:120:9:120:35 | call to method WriteLine | normal | | Assert.cs:120:27:120:27 | access to local variable s | Assert.cs:120:27:120:27 | access to local variable s | normal | @@ -685,14 +774,18 @@ | Assert.cs:122:17:122:20 | null | Assert.cs:122:17:122:20 | null | normal | | Assert.cs:122:24:122:25 | "" | Assert.cs:122:24:122:25 | "" | normal | | Assert.cs:123:9:123:37 | call to method IsTrue | Assert.cs:123:9:123:37 | call to method IsTrue | normal | +| Assert.cs:123:9:123:37 | call to method IsTrue | Assert.cs:123:9:123:37 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:123:9:123:38 | ...; | Assert.cs:123:9:123:37 | call to method IsTrue | normal | +| Assert.cs:123:9:123:38 | ...; | Assert.cs:123:9:123:37 | call to method IsTrue | throw(AssertFailedException) | | Assert.cs:123:23:123:23 | access to local variable s | Assert.cs:123:23:123:23 | access to local variable s | normal | | Assert.cs:123:23:123:31 | ... == ... | Assert.cs:123:23:123:31 | ... == ... | false | | Assert.cs:123:23:123:31 | ... == ... | Assert.cs:123:23:123:31 | ... == ... | true | | Assert.cs:123:23:123:36 | ... && ... | Assert.cs:123:23:123:31 | ... == ... | false | -| Assert.cs:123:23:123:36 | ... && ... | Assert.cs:123:36:123:36 | access to parameter b | normal | +| Assert.cs:123:23:123:36 | ... && ... | Assert.cs:123:36:123:36 | access to parameter b | false | +| Assert.cs:123:23:123:36 | ... && ... | Assert.cs:123:36:123:36 | access to parameter b | true | | Assert.cs:123:28:123:31 | null | Assert.cs:123:28:123:31 | null | normal | -| Assert.cs:123:36:123:36 | access to parameter b | Assert.cs:123:36:123:36 | access to parameter b | normal | +| Assert.cs:123:36:123:36 | access to parameter b | Assert.cs:123:36:123:36 | access to parameter b | false | +| Assert.cs:123:36:123:36 | access to parameter b | Assert.cs:123:36:123:36 | access to parameter b | true | | Assert.cs:124:9:124:35 | call to method WriteLine | Assert.cs:124:9:124:35 | call to method WriteLine | normal | | Assert.cs:124:9:124:36 | ...; | Assert.cs:124:9:124:35 | call to method WriteLine | normal | | Assert.cs:124:27:124:27 | access to local variable s | Assert.cs:124:27:124:27 | access to local variable s | normal | @@ -706,15 +799,20 @@ | Assert.cs:126:17:126:20 | null | Assert.cs:126:17:126:20 | null | normal | | Assert.cs:126:24:126:25 | "" | Assert.cs:126:24:126:25 | "" | normal | | Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:127:9:127:39 | call to method IsFalse | normal | +| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:127:9:127:39 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:127:9:127:40 | ...; | Assert.cs:127:9:127:39 | call to method IsFalse | normal | +| Assert.cs:127:9:127:40 | ...; | Assert.cs:127:9:127:39 | call to method IsFalse | throw(AssertFailedException) | | Assert.cs:127:24:127:24 | access to local variable s | Assert.cs:127:24:127:24 | access to local variable s | normal | | Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:24:127:32 | ... != ... | false | | Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:24:127:32 | ... != ... | true | | Assert.cs:127:24:127:38 | ... \|\| ... | Assert.cs:127:24:127:32 | ... != ... | true | -| Assert.cs:127:24:127:38 | ... \|\| ... | Assert.cs:127:38:127:38 | access to parameter b | normal | +| Assert.cs:127:24:127:38 | ... \|\| ... | Assert.cs:127:38:127:38 | access to parameter b | false [true] | +| Assert.cs:127:24:127:38 | ... \|\| ... | Assert.cs:127:38:127:38 | access to parameter b | true [false] | | Assert.cs:127:29:127:32 | null | Assert.cs:127:29:127:32 | null | normal | -| Assert.cs:127:37:127:38 | !... | Assert.cs:127:38:127:38 | access to parameter b | normal | -| Assert.cs:127:38:127:38 | access to parameter b | Assert.cs:127:38:127:38 | access to parameter b | normal | +| Assert.cs:127:37:127:38 | !... | Assert.cs:127:38:127:38 | access to parameter b | false [true] | +| Assert.cs:127:37:127:38 | !... | Assert.cs:127:38:127:38 | access to parameter b | true [false] | +| Assert.cs:127:38:127:38 | access to parameter b | Assert.cs:127:38:127:38 | access to parameter b | false | +| Assert.cs:127:38:127:38 | access to parameter b | Assert.cs:127:38:127:38 | access to parameter b | true | | Assert.cs:128:9:128:35 | call to method WriteLine | Assert.cs:128:9:128:35 | call to method WriteLine | normal | | Assert.cs:128:9:128:36 | ...; | Assert.cs:128:9:128:35 | call to method WriteLine | normal | | Assert.cs:128:27:128:27 | access to local variable s | Assert.cs:128:27:128:27 | access to local variable s | normal | @@ -1477,7 +1575,7 @@ | ExitMethods.cs:120:5:123:5 | {...} | ExitMethods.cs:122:13:122:17 | Int32 x = ... | normal | | ExitMethods.cs:121:9:121:28 | call to method IsTrue | ExitMethods.cs:121:9:121:28 | call to method IsTrue | throw(AssertFailedException) | | ExitMethods.cs:121:9:121:29 | ...; | ExitMethods.cs:121:9:121:28 | call to method IsTrue | throw(AssertFailedException) | -| ExitMethods.cs:121:23:121:27 | false | ExitMethods.cs:121:23:121:27 | false | normal | +| ExitMethods.cs:121:23:121:27 | false | ExitMethods.cs:121:23:121:27 | false | false | | ExitMethods.cs:122:9:122:18 | ... ...; | ExitMethods.cs:122:13:122:17 | Int32 x = ... | normal | | ExitMethods.cs:122:13:122:17 | Int32 x = ... | ExitMethods.cs:122:13:122:17 | Int32 x = ... | normal | | ExitMethods.cs:122:17:122:17 | 0 | ExitMethods.cs:122:17:122:17 | 0 | normal | @@ -1490,13 +1588,15 @@ | ExitMethods.cs:128:13:128:17 | Int32 x = ... | ExitMethods.cs:128:13:128:17 | Int32 x = ... | normal | | ExitMethods.cs:128:17:128:17 | 0 | ExitMethods.cs:128:17:128:17 | 0 | normal | | ExitMethods.cs:131:33:131:49 | call to method IsFalse | ExitMethods.cs:131:33:131:49 | call to method IsFalse | normal | -| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:48:131:48 | access to parameter b | normal | +| ExitMethods.cs:131:33:131:49 | call to method IsFalse | ExitMethods.cs:131:33:131:49 | call to method IsFalse | throw(AssertFailedException) | +| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:48:131:48 | access to parameter b | false | +| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:48:131:48 | access to parameter b | true | | ExitMethods.cs:134:5:137:5 | {...} | ExitMethods.cs:135:9:135:25 | call to method AssertFalse | throw(AssertFailedException) | | ExitMethods.cs:134:5:137:5 | {...} | ExitMethods.cs:136:13:136:17 | Int32 x = ... | normal | | ExitMethods.cs:135:9:135:25 | call to method AssertFalse | ExitMethods.cs:135:9:135:25 | call to method AssertFalse | throw(AssertFailedException) | | ExitMethods.cs:135:9:135:25 | this access | ExitMethods.cs:135:9:135:25 | this access | normal | | ExitMethods.cs:135:9:135:26 | ...; | ExitMethods.cs:135:9:135:25 | call to method AssertFalse | throw(AssertFailedException) | -| ExitMethods.cs:135:21:135:24 | true | ExitMethods.cs:135:21:135:24 | true | normal | +| ExitMethods.cs:135:21:135:24 | true | ExitMethods.cs:135:21:135:24 | true | true | | ExitMethods.cs:136:9:136:18 | ... ...; | ExitMethods.cs:136:13:136:17 | Int32 x = ... | normal | | ExitMethods.cs:136:13:136:17 | Int32 x = ... | ExitMethods.cs:136:13:136:17 | Int32 x = ... | normal | | ExitMethods.cs:136:17:136:17 | 0 | ExitMethods.cs:136:17:136:17 | 0 | normal | diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 9348a4103ed..d7d2fa43285 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -316,10 +316,12 @@ | Assert.cs:9:20:9:32 | ... ? ... : ... | Assert.cs:9:20:9:20 | access to parameter b | semmle.label | successor | | Assert.cs:9:24:9:27 | null | Assert.cs:9:16:9:32 | String s = ... | semmle.label | successor | | Assert.cs:9:31:9:32 | "" | Assert.cs:9:16:9:32 | String s = ... | semmle.label | successor | -| Assert.cs:10:9:10:31 | call to method Assert | Assert.cs:11:9:11:36 | ...; | semmle.label | successor | +| Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | Assert.cs:7:10:7:11 | exit M1 | semmle.label | exit | +| Assert.cs:10:9:10:31 | [assertion success] call to method Assert | Assert.cs:11:9:11:36 | ...; | semmle.label | successor | | Assert.cs:10:9:10:32 | ...; | Assert.cs:10:22:10:22 | access to local variable s | semmle.label | successor | | Assert.cs:10:22:10:22 | access to local variable s | Assert.cs:10:27:10:30 | null | semmle.label | successor | -| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:9:10:31 | call to method Assert | semmle.label | successor | +| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | semmle.label | false | +| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:9:10:31 | [assertion success] call to method Assert | semmle.label | true | | Assert.cs:10:27:10:30 | null | Assert.cs:10:22:10:30 | ... != ... | semmle.label | successor | | Assert.cs:11:9:11:35 | call to method WriteLine | Assert.cs:7:10:7:11 | exit M1 | semmle.label | successor | | Assert.cs:11:9:11:36 | ...; | Assert.cs:11:27:11:27 | access to local variable s | semmle.label | successor | @@ -334,9 +336,11 @@ | Assert.cs:16:20:16:32 | ... ? ... : ... | Assert.cs:16:20:16:20 | access to parameter b | semmle.label | successor | | Assert.cs:16:24:16:27 | null | Assert.cs:16:16:16:32 | String s = ... | semmle.label | successor | | Assert.cs:16:31:16:32 | "" | Assert.cs:16:16:16:32 | String s = ... | semmle.label | successor | -| Assert.cs:17:9:17:24 | call to method IsNull | Assert.cs:18:9:18:36 | ...; | semmle.label | successor | +| Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | Assert.cs:14:10:14:11 | exit M2 | semmle.label | exception(AssertFailedException) | +| Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | Assert.cs:18:9:18:36 | ...; | semmle.label | successor | | Assert.cs:17:9:17:25 | ...; | Assert.cs:17:23:17:23 | access to local variable s | semmle.label | successor | -| Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:17:9:17:24 | call to method IsNull | semmle.label | successor | +| Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | semmle.label | non-null | +| Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | semmle.label | null | | Assert.cs:18:9:18:35 | call to method WriteLine | Assert.cs:14:10:14:11 | exit M2 | semmle.label | successor | | Assert.cs:18:9:18:36 | ...; | Assert.cs:18:27:18:27 | access to local variable s | semmle.label | successor | | Assert.cs:18:27:18:27 | access to local variable s | Assert.cs:18:27:18:34 | access to property Length | semmle.label | successor | @@ -350,9 +354,11 @@ | Assert.cs:23:20:23:32 | ... ? ... : ... | Assert.cs:23:20:23:20 | access to parameter b | semmle.label | successor | | Assert.cs:23:24:23:27 | null | Assert.cs:23:16:23:32 | String s = ... | semmle.label | successor | | Assert.cs:23:31:23:32 | "" | Assert.cs:23:16:23:32 | String s = ... | semmle.label | successor | -| Assert.cs:24:9:24:27 | call to method IsNotNull | Assert.cs:25:9:25:36 | ...; | semmle.label | successor | +| Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | Assert.cs:21:10:21:11 | exit M3 | semmle.label | exception(AssertFailedException) | +| Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | Assert.cs:25:9:25:36 | ...; | semmle.label | successor | | Assert.cs:24:9:24:28 | ...; | Assert.cs:24:26:24:26 | access to local variable s | semmle.label | successor | -| Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:24:9:24:27 | call to method IsNotNull | semmle.label | successor | +| Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | semmle.label | null | +| Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | semmle.label | non-null | | Assert.cs:25:9:25:35 | call to method WriteLine | Assert.cs:21:10:21:11 | exit M3 | semmle.label | successor | | Assert.cs:25:9:25:36 | ...; | Assert.cs:25:27:25:27 | access to local variable s | semmle.label | successor | | Assert.cs:25:27:25:27 | access to local variable s | Assert.cs:25:27:25:34 | access to property Length | semmle.label | successor | @@ -366,10 +372,12 @@ | Assert.cs:30:20:30:32 | ... ? ... : ... | Assert.cs:30:20:30:20 | access to parameter b | semmle.label | successor | | Assert.cs:30:24:30:27 | null | Assert.cs:30:16:30:32 | String s = ... | semmle.label | successor | | Assert.cs:30:31:30:32 | "" | Assert.cs:30:16:30:32 | String s = ... | semmle.label | successor | -| Assert.cs:31:9:31:32 | call to method IsTrue | Assert.cs:32:9:32:36 | ...; | semmle.label | successor | +| Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | Assert.cs:28:10:28:11 | exit M4 | semmle.label | exception(AssertFailedException) | +| Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | Assert.cs:32:9:32:36 | ...; | semmle.label | successor | | Assert.cs:31:9:31:33 | ...; | Assert.cs:31:23:31:23 | access to local variable s | semmle.label | successor | | Assert.cs:31:23:31:23 | access to local variable s | Assert.cs:31:28:31:31 | null | semmle.label | successor | -| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:9:31:32 | call to method IsTrue | semmle.label | successor | +| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | semmle.label | false | +| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | semmle.label | true | | Assert.cs:31:28:31:31 | null | Assert.cs:31:23:31:31 | ... == ... | semmle.label | successor | | Assert.cs:32:9:32:35 | call to method WriteLine | Assert.cs:28:10:28:11 | exit M4 | semmle.label | successor | | Assert.cs:32:9:32:36 | ...; | Assert.cs:32:27:32:27 | access to local variable s | semmle.label | successor | @@ -384,10 +392,12 @@ | Assert.cs:37:20:37:32 | ... ? ... : ... | Assert.cs:37:20:37:20 | access to parameter b | semmle.label | successor | | Assert.cs:37:24:37:27 | null | Assert.cs:37:16:37:32 | String s = ... | semmle.label | successor | | Assert.cs:37:31:37:32 | "" | Assert.cs:37:16:37:32 | String s = ... | semmle.label | successor | -| Assert.cs:38:9:38:32 | call to method IsTrue | Assert.cs:39:9:39:36 | ...; | semmle.label | successor | +| Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | Assert.cs:35:10:35:11 | exit M5 | semmle.label | exception(AssertFailedException) | +| Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | Assert.cs:39:9:39:36 | ...; | semmle.label | successor | | Assert.cs:38:9:38:33 | ...; | Assert.cs:38:23:38:23 | access to local variable s | semmle.label | successor | | Assert.cs:38:23:38:23 | access to local variable s | Assert.cs:38:28:38:31 | null | semmle.label | successor | -| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:9:38:32 | call to method IsTrue | semmle.label | successor | +| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | semmle.label | false | +| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | semmle.label | true | | Assert.cs:38:28:38:31 | null | Assert.cs:38:23:38:31 | ... != ... | semmle.label | successor | | Assert.cs:39:9:39:35 | call to method WriteLine | Assert.cs:35:10:35:11 | exit M5 | semmle.label | successor | | Assert.cs:39:9:39:36 | ...; | Assert.cs:39:27:39:27 | access to local variable s | semmle.label | successor | @@ -402,10 +412,12 @@ | Assert.cs:44:20:44:32 | ... ? ... : ... | Assert.cs:44:20:44:20 | access to parameter b | semmle.label | successor | | Assert.cs:44:24:44:27 | null | Assert.cs:44:16:44:32 | String s = ... | semmle.label | successor | | Assert.cs:44:31:44:32 | "" | Assert.cs:44:16:44:32 | String s = ... | semmle.label | successor | -| Assert.cs:45:9:45:33 | call to method IsFalse | Assert.cs:46:9:46:36 | ...; | semmle.label | successor | +| Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | Assert.cs:42:10:42:11 | exit M6 | semmle.label | exception(AssertFailedException) | +| Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | Assert.cs:46:9:46:36 | ...; | semmle.label | successor | | Assert.cs:45:9:45:34 | ...; | Assert.cs:45:24:45:24 | access to local variable s | semmle.label | successor | | Assert.cs:45:24:45:24 | access to local variable s | Assert.cs:45:29:45:32 | null | semmle.label | successor | -| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:9:45:33 | call to method IsFalse | semmle.label | successor | +| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | semmle.label | true | +| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | semmle.label | false | | Assert.cs:45:29:45:32 | null | Assert.cs:45:24:45:32 | ... != ... | semmle.label | successor | | Assert.cs:46:9:46:35 | call to method WriteLine | Assert.cs:42:10:42:11 | exit M6 | semmle.label | successor | | Assert.cs:46:9:46:36 | ...; | Assert.cs:46:27:46:27 | access to local variable s | semmle.label | successor | @@ -420,10 +432,12 @@ | Assert.cs:51:20:51:32 | ... ? ... : ... | Assert.cs:51:20:51:20 | access to parameter b | semmle.label | successor | | Assert.cs:51:24:51:27 | null | Assert.cs:51:16:51:32 | String s = ... | semmle.label | successor | | Assert.cs:51:31:51:32 | "" | Assert.cs:51:16:51:32 | String s = ... | semmle.label | successor | -| Assert.cs:52:9:52:33 | call to method IsFalse | Assert.cs:53:9:53:36 | ...; | semmle.label | successor | +| Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | Assert.cs:49:10:49:11 | exit M7 | semmle.label | exception(AssertFailedException) | +| Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | Assert.cs:53:9:53:36 | ...; | semmle.label | successor | | Assert.cs:52:9:52:34 | ...; | Assert.cs:52:24:52:24 | access to local variable s | semmle.label | successor | | Assert.cs:52:24:52:24 | access to local variable s | Assert.cs:52:29:52:32 | null | semmle.label | successor | -| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:9:52:33 | call to method IsFalse | semmle.label | successor | +| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | semmle.label | true | +| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | semmle.label | false | | Assert.cs:52:29:52:32 | null | Assert.cs:52:24:52:32 | ... == ... | semmle.label | successor | | Assert.cs:53:9:53:35 | call to method WriteLine | Assert.cs:49:10:49:11 | exit M7 | semmle.label | successor | | Assert.cs:53:9:53:36 | ...; | Assert.cs:53:27:53:27 | access to local variable s | semmle.label | successor | @@ -432,20 +446,29 @@ | Assert.cs:56:10:56:11 | enter M8 | Assert.cs:57:5:61:5 | {...} | semmle.label | successor | | Assert.cs:57:5:61:5 | {...} | Assert.cs:58:9:58:33 | ... ...; | semmle.label | successor | | Assert.cs:58:9:58:33 | ... ...; | Assert.cs:58:20:58:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:58:16:58:32 | String s = ... | Assert.cs:59:9:59:38 | ...; | semmle.label | successor | -| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:24:58:27 | null | semmle.label | true | -| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:31:58:32 | "" | semmle.label | false | +| Assert.cs:58:16:58:32 | [b (line 56): false] String s = ... | Assert.cs:59:9:59:38 | [b (line 56): false] ...; | semmle.label | successor | +| Assert.cs:58:16:58:32 | [b (line 56): true] String s = ... | Assert.cs:59:9:59:38 | [b (line 56): true] ...; | semmle.label | successor | +| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:24:58:27 | [b (line 56): true] null | semmle.label | true | +| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:31:58:32 | [b (line 56): false] "" | semmle.label | false | | Assert.cs:58:20:58:32 | ... ? ... : ... | Assert.cs:58:20:58:20 | access to parameter b | semmle.label | successor | -| Assert.cs:58:24:58:27 | null | Assert.cs:58:16:58:32 | String s = ... | semmle.label | successor | -| Assert.cs:58:31:58:32 | "" | Assert.cs:58:16:58:32 | String s = ... | semmle.label | successor | -| Assert.cs:59:9:59:37 | call to method IsTrue | Assert.cs:60:9:60:36 | ...; | semmle.label | successor | -| Assert.cs:59:9:59:38 | ...; | Assert.cs:59:23:59:36 | ... && ... | semmle.label | successor | -| Assert.cs:59:23:59:23 | access to local variable s | Assert.cs:59:28:59:31 | null | semmle.label | successor | -| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:9:59:37 | call to method IsTrue | semmle.label | false | -| Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:36:59:36 | access to parameter b | semmle.label | true | -| Assert.cs:59:23:59:36 | ... && ... | Assert.cs:59:23:59:23 | access to local variable s | semmle.label | successor | -| Assert.cs:59:28:59:31 | null | Assert.cs:59:23:59:31 | ... != ... | semmle.label | successor | -| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:59:9:59:37 | call to method IsTrue | semmle.label | successor | +| Assert.cs:58:24:58:27 | [b (line 56): true] null | Assert.cs:58:16:58:32 | [b (line 56): true] String s = ... | semmle.label | successor | +| Assert.cs:58:31:58:32 | [b (line 56): false] "" | Assert.cs:58:16:58:32 | [b (line 56): false] String s = ... | semmle.label | successor | +| Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | Assert.cs:56:10:56:11 | exit M8 | semmle.label | exception(AssertFailedException) | +| Assert.cs:59:9:59:37 | [assertion success] call to method IsTrue | Assert.cs:60:9:60:36 | ...; | semmle.label | successor | +| Assert.cs:59:9:59:38 | [b (line 56): false] ...; | Assert.cs:59:23:59:36 | [b (line 56): false] ... && ... | semmle.label | successor | +| Assert.cs:59:9:59:38 | [b (line 56): true] ...; | Assert.cs:59:23:59:36 | [b (line 56): true] ... && ... | semmle.label | successor | +| Assert.cs:59:23:59:23 | [b (line 56): false] access to local variable s | Assert.cs:59:28:59:31 | [b (line 56): false] null | semmle.label | successor | +| Assert.cs:59:23:59:23 | [b (line 56): true] access to local variable s | Assert.cs:59:28:59:31 | [b (line 56): true] null | semmle.label | successor | +| Assert.cs:59:23:59:31 | [b (line 56): false] ... != ... | Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | semmle.label | false | +| Assert.cs:59:23:59:31 | [b (line 56): false] ... != ... | Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | semmle.label | true | +| Assert.cs:59:23:59:31 | [b (line 56): true] ... != ... | Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | semmle.label | false | +| Assert.cs:59:23:59:31 | [b (line 56): true] ... != ... | Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | semmle.label | true | +| Assert.cs:59:23:59:36 | [b (line 56): false] ... && ... | Assert.cs:59:23:59:23 | [b (line 56): false] access to local variable s | semmle.label | successor | +| Assert.cs:59:23:59:36 | [b (line 56): true] ... && ... | Assert.cs:59:23:59:23 | [b (line 56): true] access to local variable s | semmle.label | successor | +| Assert.cs:59:28:59:31 | [b (line 56): false] null | Assert.cs:59:23:59:31 | [b (line 56): false] ... != ... | semmle.label | successor | +| Assert.cs:59:28:59:31 | [b (line 56): true] null | Assert.cs:59:23:59:31 | [b (line 56): true] ... != ... | semmle.label | successor | +| Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | semmle.label | false | +| Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | Assert.cs:59:9:59:37 | [assertion success] call to method IsTrue | semmle.label | true | | Assert.cs:60:9:60:35 | call to method WriteLine | Assert.cs:56:10:56:11 | exit M8 | semmle.label | successor | | Assert.cs:60:9:60:36 | ...; | Assert.cs:60:27:60:27 | access to local variable s | semmle.label | successor | | Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:60:27:60:34 | access to property Length | semmle.label | successor | @@ -453,20 +476,29 @@ | Assert.cs:63:10:63:11 | enter M9 | Assert.cs:64:5:68:5 | {...} | semmle.label | successor | | Assert.cs:64:5:68:5 | {...} | Assert.cs:65:9:65:33 | ... ...; | semmle.label | successor | | Assert.cs:65:9:65:33 | ... ...; | Assert.cs:65:20:65:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:65:16:65:32 | String s = ... | Assert.cs:66:9:66:39 | ...; | semmle.label | successor | -| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:24:65:27 | null | semmle.label | true | -| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:31:65:32 | "" | semmle.label | false | +| Assert.cs:65:16:65:32 | [b (line 63): false] String s = ... | Assert.cs:66:9:66:39 | [b (line 63): false] ...; | semmle.label | successor | +| Assert.cs:65:16:65:32 | [b (line 63): true] String s = ... | Assert.cs:66:9:66:39 | [b (line 63): true] ...; | semmle.label | successor | +| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:24:65:27 | [b (line 63): true] null | semmle.label | true | +| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:31:65:32 | [b (line 63): false] "" | semmle.label | false | | Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:65:20:65:20 | access to parameter b | semmle.label | successor | -| Assert.cs:65:24:65:27 | null | Assert.cs:65:16:65:32 | String s = ... | semmle.label | successor | -| Assert.cs:65:31:65:32 | "" | Assert.cs:65:16:65:32 | String s = ... | semmle.label | successor | -| Assert.cs:66:9:66:38 | call to method IsFalse | Assert.cs:67:9:67:36 | ...; | semmle.label | successor | -| Assert.cs:66:9:66:39 | ...; | Assert.cs:66:24:66:37 | ... \|\| ... | semmle.label | successor | -| Assert.cs:66:24:66:24 | access to local variable s | Assert.cs:66:29:66:32 | null | semmle.label | successor | -| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:9:66:38 | call to method IsFalse | semmle.label | true | -| Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:37:66:37 | access to parameter b | semmle.label | false | -| Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:66:24:66:24 | access to local variable s | semmle.label | successor | -| Assert.cs:66:29:66:32 | null | Assert.cs:66:24:66:32 | ... == ... | semmle.label | successor | -| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:66:9:66:38 | call to method IsFalse | semmle.label | successor | +| Assert.cs:65:24:65:27 | [b (line 63): true] null | Assert.cs:65:16:65:32 | [b (line 63): true] String s = ... | semmle.label | successor | +| Assert.cs:65:31:65:32 | [b (line 63): false] "" | Assert.cs:65:16:65:32 | [b (line 63): false] String s = ... | semmle.label | successor | +| Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | Assert.cs:63:10:63:11 | exit M9 | semmle.label | exception(AssertFailedException) | +| Assert.cs:66:9:66:38 | [assertion success] call to method IsFalse | Assert.cs:67:9:67:36 | ...; | semmle.label | successor | +| Assert.cs:66:9:66:39 | [b (line 63): false] ...; | Assert.cs:66:24:66:37 | [b (line 63): false] ... \|\| ... | semmle.label | successor | +| Assert.cs:66:9:66:39 | [b (line 63): true] ...; | Assert.cs:66:24:66:37 | [b (line 63): true] ... \|\| ... | semmle.label | successor | +| Assert.cs:66:24:66:24 | [b (line 63): false] access to local variable s | Assert.cs:66:29:66:32 | [b (line 63): false] null | semmle.label | successor | +| Assert.cs:66:24:66:24 | [b (line 63): true] access to local variable s | Assert.cs:66:29:66:32 | [b (line 63): true] null | semmle.label | successor | +| Assert.cs:66:24:66:32 | [b (line 63): false] ... == ... | Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | semmle.label | true | +| Assert.cs:66:24:66:32 | [b (line 63): false] ... == ... | Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | semmle.label | false | +| Assert.cs:66:24:66:32 | [b (line 63): true] ... == ... | Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | semmle.label | true | +| Assert.cs:66:24:66:32 | [b (line 63): true] ... == ... | Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | semmle.label | false | +| Assert.cs:66:24:66:37 | [b (line 63): false] ... \|\| ... | Assert.cs:66:24:66:24 | [b (line 63): false] access to local variable s | semmle.label | successor | +| Assert.cs:66:24:66:37 | [b (line 63): true] ... \|\| ... | Assert.cs:66:24:66:24 | [b (line 63): true] access to local variable s | semmle.label | successor | +| Assert.cs:66:29:66:32 | [b (line 63): false] null | Assert.cs:66:24:66:32 | [b (line 63): false] ... == ... | semmle.label | successor | +| Assert.cs:66:29:66:32 | [b (line 63): true] null | Assert.cs:66:24:66:32 | [b (line 63): true] ... == ... | semmle.label | successor | +| Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | Assert.cs:66:9:66:38 | [assertion success] call to method IsFalse | semmle.label | false | +| Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | semmle.label | true | | Assert.cs:67:9:67:35 | call to method WriteLine | Assert.cs:63:10:63:11 | exit M9 | semmle.label | successor | | Assert.cs:67:9:67:36 | ...; | Assert.cs:67:27:67:27 | access to local variable s | semmle.label | successor | | Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:67:27:67:34 | access to property Length | semmle.label | successor | @@ -474,20 +506,29 @@ | Assert.cs:70:10:70:12 | enter M10 | Assert.cs:71:5:75:5 | {...} | semmle.label | successor | | Assert.cs:71:5:75:5 | {...} | Assert.cs:72:9:72:33 | ... ...; | semmle.label | successor | | Assert.cs:72:9:72:33 | ... ...; | Assert.cs:72:20:72:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:72:16:72:32 | String s = ... | Assert.cs:73:9:73:38 | ...; | semmle.label | successor | -| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:24:72:27 | null | semmle.label | true | -| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:31:72:32 | "" | semmle.label | false | +| Assert.cs:72:16:72:32 | [b (line 70): false] String s = ... | Assert.cs:73:9:73:38 | [b (line 70): false] ...; | semmle.label | successor | +| Assert.cs:72:16:72:32 | [b (line 70): true] String s = ... | Assert.cs:73:9:73:38 | [b (line 70): true] ...; | semmle.label | successor | +| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:24:72:27 | [b (line 70): true] null | semmle.label | true | +| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:31:72:32 | [b (line 70): false] "" | semmle.label | false | | Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:72:20:72:20 | access to parameter b | semmle.label | successor | -| Assert.cs:72:24:72:27 | null | Assert.cs:72:16:72:32 | String s = ... | semmle.label | successor | -| Assert.cs:72:31:72:32 | "" | Assert.cs:72:16:72:32 | String s = ... | semmle.label | successor | -| Assert.cs:73:9:73:37 | call to method IsTrue | Assert.cs:74:9:74:36 | ...; | semmle.label | successor | -| Assert.cs:73:9:73:38 | ...; | Assert.cs:73:23:73:36 | ... && ... | semmle.label | successor | -| Assert.cs:73:23:73:23 | access to local variable s | Assert.cs:73:28:73:31 | null | semmle.label | successor | -| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:9:73:37 | call to method IsTrue | semmle.label | false | -| Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:36:73:36 | access to parameter b | semmle.label | true | -| Assert.cs:73:23:73:36 | ... && ... | Assert.cs:73:23:73:23 | access to local variable s | semmle.label | successor | -| Assert.cs:73:28:73:31 | null | Assert.cs:73:23:73:31 | ... == ... | semmle.label | successor | -| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:73:9:73:37 | call to method IsTrue | semmle.label | successor | +| Assert.cs:72:24:72:27 | [b (line 70): true] null | Assert.cs:72:16:72:32 | [b (line 70): true] String s = ... | semmle.label | successor | +| Assert.cs:72:31:72:32 | [b (line 70): false] "" | Assert.cs:72:16:72:32 | [b (line 70): false] String s = ... | semmle.label | successor | +| Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | Assert.cs:70:10:70:12 | exit M10 | semmle.label | exception(AssertFailedException) | +| Assert.cs:73:9:73:37 | [assertion success] call to method IsTrue | Assert.cs:74:9:74:36 | ...; | semmle.label | successor | +| Assert.cs:73:9:73:38 | [b (line 70): false] ...; | Assert.cs:73:23:73:36 | [b (line 70): false] ... && ... | semmle.label | successor | +| Assert.cs:73:9:73:38 | [b (line 70): true] ...; | Assert.cs:73:23:73:36 | [b (line 70): true] ... && ... | semmle.label | successor | +| Assert.cs:73:23:73:23 | [b (line 70): false] access to local variable s | Assert.cs:73:28:73:31 | [b (line 70): false] null | semmle.label | successor | +| Assert.cs:73:23:73:23 | [b (line 70): true] access to local variable s | Assert.cs:73:28:73:31 | [b (line 70): true] null | semmle.label | successor | +| Assert.cs:73:23:73:31 | [b (line 70): false] ... == ... | Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | semmle.label | false | +| Assert.cs:73:23:73:31 | [b (line 70): false] ... == ... | Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | semmle.label | true | +| Assert.cs:73:23:73:31 | [b (line 70): true] ... == ... | Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | semmle.label | false | +| Assert.cs:73:23:73:31 | [b (line 70): true] ... == ... | Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | semmle.label | true | +| Assert.cs:73:23:73:36 | [b (line 70): false] ... && ... | Assert.cs:73:23:73:23 | [b (line 70): false] access to local variable s | semmle.label | successor | +| Assert.cs:73:23:73:36 | [b (line 70): true] ... && ... | Assert.cs:73:23:73:23 | [b (line 70): true] access to local variable s | semmle.label | successor | +| Assert.cs:73:28:73:31 | [b (line 70): false] null | Assert.cs:73:23:73:31 | [b (line 70): false] ... == ... | semmle.label | successor | +| Assert.cs:73:28:73:31 | [b (line 70): true] null | Assert.cs:73:23:73:31 | [b (line 70): true] ... == ... | semmle.label | successor | +| Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | semmle.label | false | +| Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | Assert.cs:73:9:73:37 | [assertion success] call to method IsTrue | semmle.label | true | | Assert.cs:74:9:74:35 | call to method WriteLine | Assert.cs:70:10:70:12 | exit M10 | semmle.label | successor | | Assert.cs:74:9:74:36 | ...; | Assert.cs:74:27:74:27 | access to local variable s | semmle.label | successor | | Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:74:27:74:34 | access to property Length | semmle.label | successor | @@ -495,20 +536,29 @@ | Assert.cs:77:10:77:12 | enter M11 | Assert.cs:78:5:82:5 | {...} | semmle.label | successor | | Assert.cs:78:5:82:5 | {...} | Assert.cs:79:9:79:33 | ... ...; | semmle.label | successor | | Assert.cs:79:9:79:33 | ... ...; | Assert.cs:79:20:79:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:79:16:79:32 | String s = ... | Assert.cs:80:9:80:39 | ...; | semmle.label | successor | -| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:24:79:27 | null | semmle.label | true | -| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:31:79:32 | "" | semmle.label | false | +| Assert.cs:79:16:79:32 | [b (line 77): false] String s = ... | Assert.cs:80:9:80:39 | [b (line 77): false] ...; | semmle.label | successor | +| Assert.cs:79:16:79:32 | [b (line 77): true] String s = ... | Assert.cs:80:9:80:39 | [b (line 77): true] ...; | semmle.label | successor | +| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:24:79:27 | [b (line 77): true] null | semmle.label | true | +| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:31:79:32 | [b (line 77): false] "" | semmle.label | false | | Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:79:20:79:20 | access to parameter b | semmle.label | successor | -| Assert.cs:79:24:79:27 | null | Assert.cs:79:16:79:32 | String s = ... | semmle.label | successor | -| Assert.cs:79:31:79:32 | "" | Assert.cs:79:16:79:32 | String s = ... | semmle.label | successor | -| Assert.cs:80:9:80:38 | call to method IsFalse | Assert.cs:81:9:81:36 | ...; | semmle.label | successor | -| Assert.cs:80:9:80:39 | ...; | Assert.cs:80:24:80:37 | ... \|\| ... | semmle.label | successor | -| Assert.cs:80:24:80:24 | access to local variable s | Assert.cs:80:29:80:32 | null | semmle.label | successor | -| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:9:80:38 | call to method IsFalse | semmle.label | true | -| Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:37:80:37 | access to parameter b | semmle.label | false | -| Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:24:80:24 | access to local variable s | semmle.label | successor | -| Assert.cs:80:29:80:32 | null | Assert.cs:80:24:80:32 | ... != ... | semmle.label | successor | -| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:80:9:80:38 | call to method IsFalse | semmle.label | successor | +| Assert.cs:79:24:79:27 | [b (line 77): true] null | Assert.cs:79:16:79:32 | [b (line 77): true] String s = ... | semmle.label | successor | +| Assert.cs:79:31:79:32 | [b (line 77): false] "" | Assert.cs:79:16:79:32 | [b (line 77): false] String s = ... | semmle.label | successor | +| Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | Assert.cs:77:10:77:12 | exit M11 | semmle.label | exception(AssertFailedException) | +| Assert.cs:80:9:80:38 | [assertion success] call to method IsFalse | Assert.cs:81:9:81:36 | ...; | semmle.label | successor | +| Assert.cs:80:9:80:39 | [b (line 77): false] ...; | Assert.cs:80:24:80:37 | [b (line 77): false] ... \|\| ... | semmle.label | successor | +| Assert.cs:80:9:80:39 | [b (line 77): true] ...; | Assert.cs:80:24:80:37 | [b (line 77): true] ... \|\| ... | semmle.label | successor | +| Assert.cs:80:24:80:24 | [b (line 77): false] access to local variable s | Assert.cs:80:29:80:32 | [b (line 77): false] null | semmle.label | successor | +| Assert.cs:80:24:80:24 | [b (line 77): true] access to local variable s | Assert.cs:80:29:80:32 | [b (line 77): true] null | semmle.label | successor | +| Assert.cs:80:24:80:32 | [b (line 77): false] ... != ... | Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | semmle.label | true | +| Assert.cs:80:24:80:32 | [b (line 77): false] ... != ... | Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | semmle.label | false | +| Assert.cs:80:24:80:32 | [b (line 77): true] ... != ... | Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | semmle.label | true | +| Assert.cs:80:24:80:32 | [b (line 77): true] ... != ... | Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | semmle.label | false | +| Assert.cs:80:24:80:37 | [b (line 77): false] ... \|\| ... | Assert.cs:80:24:80:24 | [b (line 77): false] access to local variable s | semmle.label | successor | +| Assert.cs:80:24:80:37 | [b (line 77): true] ... \|\| ... | Assert.cs:80:24:80:24 | [b (line 77): true] access to local variable s | semmle.label | successor | +| Assert.cs:80:29:80:32 | [b (line 77): false] null | Assert.cs:80:24:80:32 | [b (line 77): false] ... != ... | semmle.label | successor | +| Assert.cs:80:29:80:32 | [b (line 77): true] null | Assert.cs:80:24:80:32 | [b (line 77): true] ... != ... | semmle.label | successor | +| Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | Assert.cs:80:9:80:38 | [assertion success] call to method IsFalse | semmle.label | false | +| Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | semmle.label | true | | Assert.cs:81:9:81:35 | call to method WriteLine | Assert.cs:77:10:77:12 | exit M11 | semmle.label | successor | | Assert.cs:81:9:81:36 | ...; | Assert.cs:81:27:81:27 | access to local variable s | semmle.label | successor | | Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:81:27:81:34 | access to property Length | semmle.label | successor | @@ -523,14 +573,18 @@ | Assert.cs:86:20:86:32 | ... ? ... : ... | Assert.cs:86:20:86:20 | access to parameter b | semmle.label | successor | | Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:86:16:86:32 | [b (line 84): true] String s = ... | semmle.label | successor | | Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:86:16:86:32 | [b (line 84): false] String s = ... | semmle.label | successor | -| Assert.cs:87:9:87:31 | [b (line 84): false] call to method Assert | Assert.cs:88:9:88:36 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:87:9:87:31 | [b (line 84): true] call to method Assert | Assert.cs:88:9:88:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exit | +| Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exit | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:88:9:88:36 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:88:9:88:36 | [b (line 84): true] ...; | semmle.label | successor | | Assert.cs:87:9:87:32 | [b (line 84): false] ...; | Assert.cs:87:22:87:22 | [b (line 84): false] access to local variable s | semmle.label | successor | | Assert.cs:87:9:87:32 | [b (line 84): true] ...; | Assert.cs:87:22:87:22 | [b (line 84): true] access to local variable s | semmle.label | successor | | Assert.cs:87:22:87:22 | [b (line 84): false] access to local variable s | Assert.cs:87:27:87:30 | [b (line 84): false] null | semmle.label | successor | | Assert.cs:87:22:87:22 | [b (line 84): true] access to local variable s | Assert.cs:87:27:87:30 | [b (line 84): true] null | semmle.label | successor | -| Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | Assert.cs:87:9:87:31 | [b (line 84): false] call to method Assert | semmle.label | successor | -| Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | Assert.cs:87:9:87:31 | [b (line 84): true] call to method Assert | semmle.label | successor | +| Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | semmle.label | false | +| Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | semmle.label | true | +| Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | semmle.label | false | +| Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | semmle.label | true | | Assert.cs:87:27:87:30 | [b (line 84): false] null | Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | semmle.label | successor | | Assert.cs:87:27:87:30 | [b (line 84): true] null | Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | semmle.label | successor | | Assert.cs:88:9:88:35 | [b (line 84): false] call to method WriteLine | Assert.cs:90:9:90:26 | [b (line 84): false] ...; | semmle.label | successor | @@ -551,12 +605,16 @@ | Assert.cs:90:13:90:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:90:13:90:13 | [b (line 84): true] access to parameter b | semmle.label | successor | | Assert.cs:90:17:90:20 | [b (line 84): true] null | Assert.cs:90:9:90:25 | [b (line 84): true] ... = ... | semmle.label | successor | | Assert.cs:90:24:90:25 | [b (line 84): false] "" | Assert.cs:90:9:90:25 | [b (line 84): false] ... = ... | semmle.label | successor | -| Assert.cs:91:9:91:24 | [b (line 84): false] call to method IsNull | Assert.cs:92:9:92:36 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:91:9:91:24 | [b (line 84): true] call to method IsNull | Assert.cs:92:9:92:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exception(AssertFailedException) | +| Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exception(AssertFailedException) | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:92:9:92:36 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:92:9:92:36 | [b (line 84): true] ...; | semmle.label | successor | | Assert.cs:91:9:91:25 | [b (line 84): false] ...; | Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | semmle.label | successor | | Assert.cs:91:9:91:25 | [b (line 84): true] ...; | Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | Assert.cs:91:9:91:24 | [b (line 84): false] call to method IsNull | semmle.label | successor | -| Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | Assert.cs:91:9:91:24 | [b (line 84): true] call to method IsNull | semmle.label | successor | +| Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | semmle.label | non-null | +| Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | semmle.label | null | +| Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | semmle.label | non-null | +| Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | semmle.label | null | | Assert.cs:92:9:92:35 | [b (line 84): false] call to method WriteLine | Assert.cs:94:9:94:26 | [b (line 84): false] ...; | semmle.label | successor | | Assert.cs:92:9:92:35 | [b (line 84): true] call to method WriteLine | Assert.cs:94:9:94:26 | [b (line 84): true] ...; | semmle.label | successor | | Assert.cs:92:9:92:36 | [b (line 84): false] ...; | Assert.cs:92:27:92:27 | [b (line 84): false] access to local variable s | semmle.label | successor | @@ -575,12 +633,16 @@ | Assert.cs:94:13:94:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:94:13:94:13 | [b (line 84): true] access to parameter b | semmle.label | successor | | Assert.cs:94:17:94:20 | [b (line 84): true] null | Assert.cs:94:9:94:25 | [b (line 84): true] ... = ... | semmle.label | successor | | Assert.cs:94:24:94:25 | [b (line 84): false] "" | Assert.cs:94:9:94:25 | [b (line 84): false] ... = ... | semmle.label | successor | -| Assert.cs:95:9:95:27 | [b (line 84): false] call to method IsNotNull | Assert.cs:96:9:96:36 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:95:9:95:27 | [b (line 84): true] call to method IsNotNull | Assert.cs:96:9:96:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exception(AssertFailedException) | +| Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exception(AssertFailedException) | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:96:9:96:36 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:96:9:96:36 | [b (line 84): true] ...; | semmle.label | successor | | Assert.cs:95:9:95:28 | [b (line 84): false] ...; | Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | semmle.label | successor | | Assert.cs:95:9:95:28 | [b (line 84): true] ...; | Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | Assert.cs:95:9:95:27 | [b (line 84): false] call to method IsNotNull | semmle.label | successor | -| Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | Assert.cs:95:9:95:27 | [b (line 84): true] call to method IsNotNull | semmle.label | successor | +| Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | semmle.label | null | +| Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | semmle.label | non-null | +| Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | semmle.label | null | +| Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | semmle.label | non-null | | Assert.cs:96:9:96:35 | [b (line 84): false] call to method WriteLine | Assert.cs:98:9:98:26 | [b (line 84): false] ...; | semmle.label | successor | | Assert.cs:96:9:96:35 | [b (line 84): true] call to method WriteLine | Assert.cs:98:9:98:26 | [b (line 84): true] ...; | semmle.label | successor | | Assert.cs:96:9:96:36 | [b (line 84): false] ...; | Assert.cs:96:27:96:27 | [b (line 84): false] access to local variable s | semmle.label | successor | @@ -599,14 +661,18 @@ | Assert.cs:98:13:98:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:98:13:98:13 | [b (line 84): true] access to parameter b | semmle.label | successor | | Assert.cs:98:17:98:20 | [b (line 84): true] null | Assert.cs:98:9:98:25 | [b (line 84): true] ... = ... | semmle.label | successor | | Assert.cs:98:24:98:25 | [b (line 84): false] "" | Assert.cs:98:9:98:25 | [b (line 84): false] ... = ... | semmle.label | successor | -| Assert.cs:99:9:99:32 | [b (line 84): false] call to method IsTrue | Assert.cs:100:9:100:36 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:99:9:99:32 | [b (line 84): true] call to method IsTrue | Assert.cs:100:9:100:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exception(AssertFailedException) | +| Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exception(AssertFailedException) | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:100:9:100:36 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:100:9:100:36 | [b (line 84): true] ...; | semmle.label | successor | | Assert.cs:99:9:99:33 | [b (line 84): false] ...; | Assert.cs:99:23:99:23 | [b (line 84): false] access to local variable s | semmle.label | successor | | Assert.cs:99:9:99:33 | [b (line 84): true] ...; | Assert.cs:99:23:99:23 | [b (line 84): true] access to local variable s | semmle.label | successor | | Assert.cs:99:23:99:23 | [b (line 84): false] access to local variable s | Assert.cs:99:28:99:31 | [b (line 84): false] null | semmle.label | successor | | Assert.cs:99:23:99:23 | [b (line 84): true] access to local variable s | Assert.cs:99:28:99:31 | [b (line 84): true] null | semmle.label | successor | -| Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | Assert.cs:99:9:99:32 | [b (line 84): false] call to method IsTrue | semmle.label | successor | -| Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | Assert.cs:99:9:99:32 | [b (line 84): true] call to method IsTrue | semmle.label | successor | +| Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | semmle.label | false | +| Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | semmle.label | true | +| Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | semmle.label | false | +| Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | semmle.label | true | | Assert.cs:99:28:99:31 | [b (line 84): false] null | Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | semmle.label | successor | | Assert.cs:99:28:99:31 | [b (line 84): true] null | Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | semmle.label | successor | | Assert.cs:100:9:100:35 | [b (line 84): false] call to method WriteLine | Assert.cs:102:9:102:26 | [b (line 84): false] ...; | semmle.label | successor | @@ -627,14 +693,18 @@ | Assert.cs:102:13:102:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:102:13:102:13 | [b (line 84): true] access to parameter b | semmle.label | successor | | Assert.cs:102:17:102:20 | [b (line 84): true] null | Assert.cs:102:9:102:25 | [b (line 84): true] ... = ... | semmle.label | successor | | Assert.cs:102:24:102:25 | [b (line 84): false] "" | Assert.cs:102:9:102:25 | [b (line 84): false] ... = ... | semmle.label | successor | -| Assert.cs:103:9:103:32 | [b (line 84): false] call to method IsTrue | Assert.cs:104:9:104:36 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:103:9:103:32 | [b (line 84): true] call to method IsTrue | Assert.cs:104:9:104:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exception(AssertFailedException) | +| Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exception(AssertFailedException) | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:104:9:104:36 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:104:9:104:36 | [b (line 84): true] ...; | semmle.label | successor | | Assert.cs:103:9:103:33 | [b (line 84): false] ...; | Assert.cs:103:23:103:23 | [b (line 84): false] access to local variable s | semmle.label | successor | | Assert.cs:103:9:103:33 | [b (line 84): true] ...; | Assert.cs:103:23:103:23 | [b (line 84): true] access to local variable s | semmle.label | successor | | Assert.cs:103:23:103:23 | [b (line 84): false] access to local variable s | Assert.cs:103:28:103:31 | [b (line 84): false] null | semmle.label | successor | | Assert.cs:103:23:103:23 | [b (line 84): true] access to local variable s | Assert.cs:103:28:103:31 | [b (line 84): true] null | semmle.label | successor | -| Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | Assert.cs:103:9:103:32 | [b (line 84): false] call to method IsTrue | semmle.label | successor | -| Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | Assert.cs:103:9:103:32 | [b (line 84): true] call to method IsTrue | semmle.label | successor | +| Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | semmle.label | false | +| Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | semmle.label | true | +| Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | semmle.label | false | +| Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | semmle.label | true | | Assert.cs:103:28:103:31 | [b (line 84): false] null | Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | semmle.label | successor | | Assert.cs:103:28:103:31 | [b (line 84): true] null | Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | semmle.label | successor | | Assert.cs:104:9:104:35 | [b (line 84): false] call to method WriteLine | Assert.cs:106:9:106:26 | [b (line 84): false] ...; | semmle.label | successor | @@ -655,14 +725,18 @@ | Assert.cs:106:13:106:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:106:13:106:13 | [b (line 84): true] access to parameter b | semmle.label | successor | | Assert.cs:106:17:106:20 | [b (line 84): true] null | Assert.cs:106:9:106:25 | [b (line 84): true] ... = ... | semmle.label | successor | | Assert.cs:106:24:106:25 | [b (line 84): false] "" | Assert.cs:106:9:106:25 | [b (line 84): false] ... = ... | semmle.label | successor | -| Assert.cs:107:9:107:33 | [b (line 84): false] call to method IsFalse | Assert.cs:108:9:108:36 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:107:9:107:33 | [b (line 84): true] call to method IsFalse | Assert.cs:108:9:108:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exception(AssertFailedException) | +| Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exception(AssertFailedException) | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:108:9:108:36 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:108:9:108:36 | [b (line 84): true] ...; | semmle.label | successor | | Assert.cs:107:9:107:34 | [b (line 84): false] ...; | Assert.cs:107:24:107:24 | [b (line 84): false] access to local variable s | semmle.label | successor | | Assert.cs:107:9:107:34 | [b (line 84): true] ...; | Assert.cs:107:24:107:24 | [b (line 84): true] access to local variable s | semmle.label | successor | | Assert.cs:107:24:107:24 | [b (line 84): false] access to local variable s | Assert.cs:107:29:107:32 | [b (line 84): false] null | semmle.label | successor | | Assert.cs:107:24:107:24 | [b (line 84): true] access to local variable s | Assert.cs:107:29:107:32 | [b (line 84): true] null | semmle.label | successor | -| Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | Assert.cs:107:9:107:33 | [b (line 84): false] call to method IsFalse | semmle.label | successor | -| Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | Assert.cs:107:9:107:33 | [b (line 84): true] call to method IsFalse | semmle.label | successor | +| Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | semmle.label | true | +| Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | semmle.label | false | +| Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | semmle.label | true | +| Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | semmle.label | false | | Assert.cs:107:29:107:32 | [b (line 84): false] null | Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | semmle.label | successor | | Assert.cs:107:29:107:32 | [b (line 84): true] null | Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | semmle.label | successor | | Assert.cs:108:9:108:35 | [b (line 84): false] call to method WriteLine | Assert.cs:110:9:110:26 | [b (line 84): false] ...; | semmle.label | successor | @@ -683,14 +757,18 @@ | Assert.cs:110:13:110:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:110:13:110:13 | [b (line 84): true] access to parameter b | semmle.label | successor | | Assert.cs:110:17:110:20 | [b (line 84): true] null | Assert.cs:110:9:110:25 | [b (line 84): true] ... = ... | semmle.label | successor | | Assert.cs:110:24:110:25 | [b (line 84): false] "" | Assert.cs:110:9:110:25 | [b (line 84): false] ... = ... | semmle.label | successor | -| Assert.cs:111:9:111:33 | [b (line 84): false] call to method IsFalse | Assert.cs:112:9:112:36 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:111:9:111:33 | [b (line 84): true] call to method IsFalse | Assert.cs:112:9:112:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exception(AssertFailedException) | +| Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exception(AssertFailedException) | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:112:9:112:36 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:112:9:112:36 | [b (line 84): true] ...; | semmle.label | successor | | Assert.cs:111:9:111:34 | [b (line 84): false] ...; | Assert.cs:111:24:111:24 | [b (line 84): false] access to local variable s | semmle.label | successor | | Assert.cs:111:9:111:34 | [b (line 84): true] ...; | Assert.cs:111:24:111:24 | [b (line 84): true] access to local variable s | semmle.label | successor | | Assert.cs:111:24:111:24 | [b (line 84): false] access to local variable s | Assert.cs:111:29:111:32 | [b (line 84): false] null | semmle.label | successor | | Assert.cs:111:24:111:24 | [b (line 84): true] access to local variable s | Assert.cs:111:29:111:32 | [b (line 84): true] null | semmle.label | successor | -| Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | Assert.cs:111:9:111:33 | [b (line 84): false] call to method IsFalse | semmle.label | successor | -| Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | Assert.cs:111:9:111:33 | [b (line 84): true] call to method IsFalse | semmle.label | successor | +| Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | semmle.label | true | +| Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | semmle.label | false | +| Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | semmle.label | true | +| Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | semmle.label | false | | Assert.cs:111:29:111:32 | [b (line 84): false] null | Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | semmle.label | successor | | Assert.cs:111:29:111:32 | [b (line 84): true] null | Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | semmle.label | successor | | Assert.cs:112:9:112:35 | [b (line 84): false] call to method WriteLine | Assert.cs:114:9:114:26 | [b (line 84): false] ...; | semmle.label | successor | @@ -711,118 +789,79 @@ | Assert.cs:114:13:114:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:114:13:114:13 | [b (line 84): true] access to parameter b | semmle.label | successor | | Assert.cs:114:17:114:20 | [b (line 84): true] null | Assert.cs:114:9:114:25 | [b (line 84): true] ... = ... | semmle.label | successor | | Assert.cs:114:24:114:25 | [b (line 84): false] "" | Assert.cs:114:9:114:25 | [b (line 84): false] ... = ... | semmle.label | successor | -| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | Assert.cs:116:9:116:36 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | Assert.cs:116:9:116:36 | [b (line 84): true] ...; | semmle.label | successor | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exception(AssertFailedException) | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exception(AssertFailedException) | +| Assert.cs:115:9:115:37 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:116:9:116:36 | [b (line 84): true] ...; | semmle.label | successor | | Assert.cs:115:9:115:38 | [b (line 84): false] ...; | Assert.cs:115:23:115:36 | [b (line 84): false] ... && ... | semmle.label | successor | | Assert.cs:115:9:115:38 | [b (line 84): true] ...; | Assert.cs:115:23:115:36 | [b (line 84): true] ... && ... | semmle.label | successor | | Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | Assert.cs:115:28:115:31 | [b (line 84): false] null | semmle.label | successor | | Assert.cs:115:23:115:23 | [b (line 84): true] access to local variable s | Assert.cs:115:28:115:31 | [b (line 84): true] null | semmle.label | successor | -| Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | semmle.label | false | +| Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | semmle.label | false | | Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | semmle.label | true | -| Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | semmle.label | false | +| Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | semmle.label | false | | Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | semmle.label | true | | Assert.cs:115:23:115:36 | [b (line 84): false] ... && ... | Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | semmle.label | successor | | Assert.cs:115:23:115:36 | [b (line 84): true] ... && ... | Assert.cs:115:23:115:23 | [b (line 84): true] access to local variable s | semmle.label | successor | | Assert.cs:115:28:115:31 | [b (line 84): false] null | Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | semmle.label | successor | | Assert.cs:115:28:115:31 | [b (line 84): true] null | Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | semmle.label | successor | -| Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | semmle.label | successor | -| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | semmle.label | successor | -| Assert.cs:116:9:116:35 | [b (line 84): false] call to method WriteLine | Assert.cs:118:9:118:26 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | semmle.label | false | +| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:115:9:115:37 | [assertion success, b (line 84): true] call to method IsTrue | semmle.label | true | | Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | Assert.cs:118:9:118:26 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:116:9:116:36 | [b (line 84): false] ...; | Assert.cs:116:27:116:27 | [b (line 84): false] access to local variable s | semmle.label | successor | | Assert.cs:116:9:116:36 | [b (line 84): true] ...; | Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:116:27:116:27 | [b (line 84): false] access to local variable s | Assert.cs:116:27:116:34 | [b (line 84): false] access to property Length | semmle.label | successor | | Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | semmle.label | successor | -| Assert.cs:116:27:116:34 | [b (line 84): false] access to property Length | Assert.cs:116:9:116:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | | Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | -| Assert.cs:118:9:118:25 | [b (line 84): false] ... = ... | Assert.cs:119:9:119:40 | [b (line 84): false] ...; | semmle.label | successor | | Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | Assert.cs:119:9:119:40 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:118:9:118:26 | [b (line 84): false] ...; | Assert.cs:118:13:118:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | | Assert.cs:118:9:118:26 | [b (line 84): true] ...; | Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | Assert.cs:118:24:118:25 | [b (line 84): false] "" | semmle.label | false | | Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | Assert.cs:118:17:118:20 | [b (line 84): true] null | semmle.label | true | -| Assert.cs:118:13:118:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | semmle.label | successor | | Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | semmle.label | successor | | Assert.cs:118:17:118:20 | [b (line 84): true] null | Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | semmle.label | successor | -| Assert.cs:118:24:118:25 | [b (line 84): false] "" | Assert.cs:118:9:118:25 | [b (line 84): false] ... = ... | semmle.label | successor | -| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | Assert.cs:120:9:120:36 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | Assert.cs:120:9:120:36 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:119:9:119:40 | [b (line 84): false] ...; | Assert.cs:119:24:119:38 | [b (line 84): false] ... \|\| ... | semmle.label | successor | +| Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exception(AssertFailedException) | +| Assert.cs:119:9:119:39 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:120:9:120:36 | [b (line 84): true] ...; | semmle.label | successor | | Assert.cs:119:9:119:40 | [b (line 84): true] ...; | Assert.cs:119:24:119:38 | [b (line 84): true] ... \|\| ... | semmle.label | successor | -| Assert.cs:119:24:119:24 | [b (line 84): false] access to local variable s | Assert.cs:119:29:119:32 | [b (line 84): false] null | semmle.label | successor | | Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | Assert.cs:119:29:119:32 | [b (line 84): true] null | semmle.label | successor | -| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | semmle.label | true | -| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | Assert.cs:119:37:119:38 | [b (line 84): false] !... | semmle.label | false | -| Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | semmle.label | true | +| Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | semmle.label | true | | Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:37:119:38 | [b (line 84): true] !... | semmle.label | false | -| Assert.cs:119:24:119:38 | [b (line 84): false] ... \|\| ... | Assert.cs:119:24:119:24 | [b (line 84): false] access to local variable s | semmle.label | successor | | Assert.cs:119:24:119:38 | [b (line 84): true] ... \|\| ... | Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:119:29:119:32 | [b (line 84): false] null | Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | semmle.label | successor | | Assert.cs:119:29:119:32 | [b (line 84): true] null | Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | semmle.label | successor | -| Assert.cs:119:37:119:38 | [b (line 84): false] !... | Assert.cs:119:38:119:38 | [b (line 84): false] access to parameter b | semmle.label | successor | | Assert.cs:119:37:119:38 | [b (line 84): true] !... | Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | semmle.label | successor | -| Assert.cs:119:38:119:38 | [b (line 84): false] access to parameter b | Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | semmle.label | successor | -| Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | semmle.label | successor | -| Assert.cs:120:9:120:35 | [b (line 84): false] call to method WriteLine | Assert.cs:122:9:122:26 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | Assert.cs:119:9:119:39 | [assertion success, b (line 84): true] call to method IsFalse | semmle.label | true | | Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | Assert.cs:122:9:122:26 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:120:9:120:36 | [b (line 84): false] ...; | Assert.cs:120:27:120:27 | [b (line 84): false] access to local variable s | semmle.label | successor | | Assert.cs:120:9:120:36 | [b (line 84): true] ...; | Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:120:27:120:27 | [b (line 84): false] access to local variable s | Assert.cs:120:27:120:34 | [b (line 84): false] access to property Length | semmle.label | successor | | Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | semmle.label | successor | -| Assert.cs:120:27:120:34 | [b (line 84): false] access to property Length | Assert.cs:120:9:120:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | | Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | -| Assert.cs:122:9:122:25 | [b (line 84): false] ... = ... | Assert.cs:123:9:123:38 | [b (line 84): false] ...; | semmle.label | successor | | Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | Assert.cs:123:9:123:38 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:122:9:122:26 | [b (line 84): false] ...; | Assert.cs:122:13:122:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | | Assert.cs:122:9:122:26 | [b (line 84): true] ...; | Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | Assert.cs:122:24:122:25 | [b (line 84): false] "" | semmle.label | false | | Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | Assert.cs:122:17:122:20 | [b (line 84): true] null | semmle.label | true | -| Assert.cs:122:13:122:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | semmle.label | successor | | Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | semmle.label | successor | | Assert.cs:122:17:122:20 | [b (line 84): true] null | Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | semmle.label | successor | -| Assert.cs:122:24:122:25 | [b (line 84): false] "" | Assert.cs:122:9:122:25 | [b (line 84): false] ... = ... | semmle.label | successor | -| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | Assert.cs:124:9:124:36 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | Assert.cs:124:9:124:36 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:123:9:123:38 | [b (line 84): false] ...; | Assert.cs:123:23:123:36 | [b (line 84): false] ... && ... | semmle.label | successor | +| Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exception(AssertFailedException) | +| Assert.cs:123:9:123:37 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:124:9:124:36 | [b (line 84): true] ...; | semmle.label | successor | | Assert.cs:123:9:123:38 | [b (line 84): true] ...; | Assert.cs:123:23:123:36 | [b (line 84): true] ... && ... | semmle.label | successor | -| Assert.cs:123:23:123:23 | [b (line 84): false] access to local variable s | Assert.cs:123:28:123:31 | [b (line 84): false] null | semmle.label | successor | | Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | Assert.cs:123:28:123:31 | [b (line 84): true] null | semmle.label | successor | -| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | semmle.label | false | -| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | semmle.label | true | -| Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | semmle.label | false | +| Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | semmle.label | false | | Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | semmle.label | true | -| Assert.cs:123:23:123:36 | [b (line 84): false] ... && ... | Assert.cs:123:23:123:23 | [b (line 84): false] access to local variable s | semmle.label | successor | | Assert.cs:123:23:123:36 | [b (line 84): true] ... && ... | Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:123:28:123:31 | [b (line 84): false] null | Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | semmle.label | successor | | Assert.cs:123:28:123:31 | [b (line 84): true] null | Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | semmle.label | successor | -| Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | semmle.label | successor | -| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | semmle.label | successor | -| Assert.cs:124:9:124:35 | [b (line 84): false] call to method WriteLine | Assert.cs:126:9:126:26 | [b (line 84): false] ...; | semmle.label | successor | +| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:123:9:123:37 | [assertion success, b (line 84): true] call to method IsTrue | semmle.label | true | | Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | Assert.cs:126:9:126:26 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:124:9:124:36 | [b (line 84): false] ...; | Assert.cs:124:27:124:27 | [b (line 84): false] access to local variable s | semmle.label | successor | | Assert.cs:124:9:124:36 | [b (line 84): true] ...; | Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:124:27:124:27 | [b (line 84): false] access to local variable s | Assert.cs:124:27:124:34 | [b (line 84): false] access to property Length | semmle.label | successor | | Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | semmle.label | successor | -| Assert.cs:124:27:124:34 | [b (line 84): false] access to property Length | Assert.cs:124:9:124:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | | Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | -| Assert.cs:126:9:126:25 | ... = ... | Assert.cs:127:9:127:40 | ...; | semmle.label | successor | -| Assert.cs:126:9:126:26 | [b (line 84): false] ...; | Assert.cs:126:13:126:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | +| Assert.cs:126:9:126:25 | [b (line 84): true] ... = ... | Assert.cs:127:9:127:40 | [b (line 84): true] ...; | semmle.label | successor | | Assert.cs:126:9:126:26 | [b (line 84): true] ...; | Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | Assert.cs:126:24:126:25 | "" | semmle.label | false | -| Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | Assert.cs:126:17:126:20 | null | semmle.label | true | -| Assert.cs:126:13:126:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | semmle.label | successor | +| Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | Assert.cs:126:17:126:20 | [b (line 84): true] null | semmle.label | true | | Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | semmle.label | successor | -| Assert.cs:126:17:126:20 | null | Assert.cs:126:9:126:25 | ... = ... | semmle.label | successor | -| Assert.cs:126:24:126:25 | "" | Assert.cs:126:9:126:25 | ... = ... | semmle.label | successor | -| Assert.cs:127:9:127:39 | call to method IsFalse | Assert.cs:128:9:128:36 | ...; | semmle.label | successor | -| Assert.cs:127:9:127:40 | ...; | Assert.cs:127:24:127:38 | ... \|\| ... | semmle.label | successor | -| Assert.cs:127:24:127:24 | access to local variable s | Assert.cs:127:29:127:32 | null | semmle.label | successor | -| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:9:127:39 | call to method IsFalse | semmle.label | true | -| Assert.cs:127:24:127:32 | ... != ... | Assert.cs:127:37:127:38 | !... | semmle.label | false | -| Assert.cs:127:24:127:38 | ... \|\| ... | Assert.cs:127:24:127:24 | access to local variable s | semmle.label | successor | -| Assert.cs:127:29:127:32 | null | Assert.cs:127:24:127:32 | ... != ... | semmle.label | successor | -| Assert.cs:127:37:127:38 | !... | Assert.cs:127:38:127:38 | access to parameter b | semmle.label | successor | -| Assert.cs:127:38:127:38 | access to parameter b | Assert.cs:127:9:127:39 | call to method IsFalse | semmle.label | successor | +| Assert.cs:126:17:126:20 | [b (line 84): true] null | Assert.cs:126:9:126:25 | [b (line 84): true] ... = ... | semmle.label | successor | +| Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | Assert.cs:84:10:84:12 | exit M12 | semmle.label | exception(AssertFailedException) | +| Assert.cs:127:9:127:39 | [assertion success] call to method IsFalse | Assert.cs:128:9:128:36 | ...; | semmle.label | successor | +| Assert.cs:127:9:127:40 | [b (line 84): true] ...; | Assert.cs:127:24:127:38 | [b (line 84): true] ... \|\| ... | semmle.label | successor | +| Assert.cs:127:24:127:24 | [b (line 84): true] access to local variable s | Assert.cs:127:29:127:32 | [b (line 84): true] null | semmle.label | successor | +| Assert.cs:127:24:127:32 | [b (line 84): true] ... != ... | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | semmle.label | true | +| Assert.cs:127:24:127:32 | [b (line 84): true] ... != ... | Assert.cs:127:37:127:38 | [b (line 84): true] !... | semmle.label | false | +| Assert.cs:127:24:127:38 | [b (line 84): true] ... \|\| ... | Assert.cs:127:24:127:24 | [b (line 84): true] access to local variable s | semmle.label | successor | +| Assert.cs:127:29:127:32 | [b (line 84): true] null | Assert.cs:127:24:127:32 | [b (line 84): true] ... != ... | semmle.label | successor | +| Assert.cs:127:37:127:38 | [b (line 84): true] !... | Assert.cs:127:38:127:38 | [b (line 84): true] access to parameter b | semmle.label | successor | +| Assert.cs:127:38:127:38 | [b (line 84): true] access to parameter b | Assert.cs:127:9:127:39 | [assertion success] call to method IsFalse | semmle.label | true | | Assert.cs:128:9:128:35 | call to method WriteLine | Assert.cs:84:10:84:12 | exit M12 | semmle.label | successor | | Assert.cs:128:9:128:36 | ...; | Assert.cs:128:27:128:27 | access to local variable s | semmle.label | successor | | Assert.cs:128:27:128:27 | access to local variable s | Assert.cs:128:27:128:34 | access to property Length | semmle.label | successor | @@ -1598,23 +1637,25 @@ | ExitMethods.cs:116:38:116:38 | 1 | ExitMethods.cs:116:9:116:39 | return ...; | semmle.label | successor | | ExitMethods.cs:119:17:119:32 | enter FailingAssertion | ExitMethods.cs:120:5:123:5 | {...} | semmle.label | successor | | ExitMethods.cs:120:5:123:5 | {...} | ExitMethods.cs:121:9:121:29 | ...; | semmle.label | successor | -| ExitMethods.cs:121:9:121:28 | call to method IsTrue | ExitMethods.cs:119:17:119:32 | exit FailingAssertion | semmle.label | exception(AssertFailedException) | +| ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | ExitMethods.cs:119:17:119:32 | exit FailingAssertion | semmle.label | exception(AssertFailedException) | | ExitMethods.cs:121:9:121:29 | ...; | ExitMethods.cs:121:23:121:27 | false | semmle.label | successor | -| ExitMethods.cs:121:23:121:27 | false | ExitMethods.cs:121:9:121:28 | call to method IsTrue | semmle.label | successor | +| ExitMethods.cs:121:23:121:27 | false | ExitMethods.cs:121:9:121:28 | [assertion failure] call to method IsTrue | semmle.label | false | | ExitMethods.cs:125:17:125:33 | enter FailingAssertion2 | ExitMethods.cs:126:5:129:5 | {...} | semmle.label | successor | | ExitMethods.cs:126:5:129:5 | {...} | ExitMethods.cs:127:9:127:27 | ...; | semmle.label | successor | | ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | ExitMethods.cs:125:17:125:33 | exit FailingAssertion2 | semmle.label | exception(AssertFailedException) | | ExitMethods.cs:127:9:127:26 | this access | ExitMethods.cs:127:9:127:26 | call to method FailingAssertion | semmle.label | successor | | ExitMethods.cs:127:9:127:27 | ...; | ExitMethods.cs:127:9:127:26 | this access | semmle.label | successor | | ExitMethods.cs:131:10:131:20 | enter AssertFalse | ExitMethods.cs:131:48:131:48 | access to parameter b | semmle.label | successor | -| ExitMethods.cs:131:33:131:49 | call to method IsFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse | semmle.label | successor | -| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:33:131:49 | call to method IsFalse | semmle.label | successor | +| ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse | semmle.label | exception(AssertFailedException) | +| ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | ExitMethods.cs:131:10:131:20 | exit AssertFalse | semmle.label | successor | +| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:33:131:49 | [assertion failure] call to method IsFalse | semmle.label | true | +| ExitMethods.cs:131:48:131:48 | access to parameter b | ExitMethods.cs:131:33:131:49 | [assertion success] call to method IsFalse | semmle.label | false | | ExitMethods.cs:133:17:133:33 | enter FailingAssertion3 | ExitMethods.cs:134:5:137:5 | {...} | semmle.label | successor | | ExitMethods.cs:134:5:137:5 | {...} | ExitMethods.cs:135:9:135:26 | ...; | semmle.label | successor | -| ExitMethods.cs:135:9:135:25 | call to method AssertFalse | ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 | semmle.label | exception(AssertFailedException) | +| ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | ExitMethods.cs:133:17:133:33 | exit FailingAssertion3 | semmle.label | exception(AssertFailedException) | | ExitMethods.cs:135:9:135:25 | this access | ExitMethods.cs:135:21:135:24 | true | semmle.label | successor | | ExitMethods.cs:135:9:135:26 | ...; | ExitMethods.cs:135:9:135:25 | this access | semmle.label | successor | -| ExitMethods.cs:135:21:135:24 | true | ExitMethods.cs:135:9:135:25 | call to method AssertFalse | semmle.label | successor | +| ExitMethods.cs:135:21:135:24 | true | ExitMethods.cs:135:9:135:25 | [assertion failure] call to method AssertFalse | semmle.label | true | | Extensions.cs:5:23:5:29 | enter ToInt32 | Extensions.cs:6:5:8:5 | {...} | semmle.label | successor | | Extensions.cs:6:5:8:5 | {...} | Extensions.cs:7:28:7:28 | access to parameter s | semmle.label | successor | | Extensions.cs:7:9:7:30 | return ...; | Extensions.cs:5:23:5:29 | exit ToInt32 | semmle.label | return | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected index a25a60947bc..95370c57859 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected @@ -1,10 +1,76 @@ booleanNode +| Assert.cs:58:16:58:32 | [b (line 56): false] String s = ... | b (line 56): false | +| Assert.cs:58:16:58:32 | [b (line 56): true] String s = ... | b (line 56): true | +| Assert.cs:58:24:58:27 | [b (line 56): true] null | b (line 56): true | +| Assert.cs:58:31:58:32 | [b (line 56): false] "" | b (line 56): false | +| Assert.cs:59:9:59:38 | [b (line 56): false] ...; | b (line 56): false | +| Assert.cs:59:9:59:38 | [b (line 56): true] ...; | b (line 56): true | +| Assert.cs:59:23:59:23 | [b (line 56): false] access to local variable s | b (line 56): false | +| Assert.cs:59:23:59:23 | [b (line 56): true] access to local variable s | b (line 56): true | +| Assert.cs:59:23:59:31 | [b (line 56): false] ... != ... | b (line 56): false | +| Assert.cs:59:23:59:31 | [b (line 56): true] ... != ... | b (line 56): true | +| Assert.cs:59:23:59:36 | [b (line 56): false] ... && ... | b (line 56): false | +| Assert.cs:59:23:59:36 | [b (line 56): true] ... && ... | b (line 56): true | +| Assert.cs:59:28:59:31 | [b (line 56): false] null | b (line 56): false | +| Assert.cs:59:28:59:31 | [b (line 56): true] null | b (line 56): true | +| Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | b (line 56): false | +| Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | b (line 56): true | +| Assert.cs:65:16:65:32 | [b (line 63): false] String s = ... | b (line 63): false | +| Assert.cs:65:16:65:32 | [b (line 63): true] String s = ... | b (line 63): true | +| Assert.cs:65:24:65:27 | [b (line 63): true] null | b (line 63): true | +| Assert.cs:65:31:65:32 | [b (line 63): false] "" | b (line 63): false | +| Assert.cs:66:9:66:39 | [b (line 63): false] ...; | b (line 63): false | +| Assert.cs:66:9:66:39 | [b (line 63): true] ...; | b (line 63): true | +| Assert.cs:66:24:66:24 | [b (line 63): false] access to local variable s | b (line 63): false | +| Assert.cs:66:24:66:24 | [b (line 63): true] access to local variable s | b (line 63): true | +| Assert.cs:66:24:66:32 | [b (line 63): false] ... == ... | b (line 63): false | +| Assert.cs:66:24:66:32 | [b (line 63): true] ... == ... | b (line 63): true | +| Assert.cs:66:24:66:37 | [b (line 63): false] ... \|\| ... | b (line 63): false | +| Assert.cs:66:24:66:37 | [b (line 63): true] ... \|\| ... | b (line 63): true | +| Assert.cs:66:29:66:32 | [b (line 63): false] null | b (line 63): false | +| Assert.cs:66:29:66:32 | [b (line 63): true] null | b (line 63): true | +| Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | b (line 63): false | +| Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | b (line 63): true | +| Assert.cs:72:16:72:32 | [b (line 70): false] String s = ... | b (line 70): false | +| Assert.cs:72:16:72:32 | [b (line 70): true] String s = ... | b (line 70): true | +| Assert.cs:72:24:72:27 | [b (line 70): true] null | b (line 70): true | +| Assert.cs:72:31:72:32 | [b (line 70): false] "" | b (line 70): false | +| Assert.cs:73:9:73:38 | [b (line 70): false] ...; | b (line 70): false | +| Assert.cs:73:9:73:38 | [b (line 70): true] ...; | b (line 70): true | +| Assert.cs:73:23:73:23 | [b (line 70): false] access to local variable s | b (line 70): false | +| Assert.cs:73:23:73:23 | [b (line 70): true] access to local variable s | b (line 70): true | +| Assert.cs:73:23:73:31 | [b (line 70): false] ... == ... | b (line 70): false | +| Assert.cs:73:23:73:31 | [b (line 70): true] ... == ... | b (line 70): true | +| Assert.cs:73:23:73:36 | [b (line 70): false] ... && ... | b (line 70): false | +| Assert.cs:73:23:73:36 | [b (line 70): true] ... && ... | b (line 70): true | +| Assert.cs:73:28:73:31 | [b (line 70): false] null | b (line 70): false | +| Assert.cs:73:28:73:31 | [b (line 70): true] null | b (line 70): true | +| Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | b (line 70): false | +| Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | b (line 70): true | +| Assert.cs:79:16:79:32 | [b (line 77): false] String s = ... | b (line 77): false | +| Assert.cs:79:16:79:32 | [b (line 77): true] String s = ... | b (line 77): true | +| Assert.cs:79:24:79:27 | [b (line 77): true] null | b (line 77): true | +| Assert.cs:79:31:79:32 | [b (line 77): false] "" | b (line 77): false | +| Assert.cs:80:9:80:39 | [b (line 77): false] ...; | b (line 77): false | +| Assert.cs:80:9:80:39 | [b (line 77): true] ...; | b (line 77): true | +| Assert.cs:80:24:80:24 | [b (line 77): false] access to local variable s | b (line 77): false | +| Assert.cs:80:24:80:24 | [b (line 77): true] access to local variable s | b (line 77): true | +| Assert.cs:80:24:80:32 | [b (line 77): false] ... != ... | b (line 77): false | +| Assert.cs:80:24:80:32 | [b (line 77): true] ... != ... | b (line 77): true | +| Assert.cs:80:24:80:37 | [b (line 77): false] ... \|\| ... | b (line 77): false | +| Assert.cs:80:24:80:37 | [b (line 77): true] ... \|\| ... | b (line 77): true | +| Assert.cs:80:29:80:32 | [b (line 77): false] null | b (line 77): false | +| Assert.cs:80:29:80:32 | [b (line 77): true] null | b (line 77): true | +| Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | b (line 77): false | +| Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | b (line 77): true | | Assert.cs:86:16:86:32 | [b (line 84): false] String s = ... | b (line 84): false | | Assert.cs:86:16:86:32 | [b (line 84): true] String s = ... | b (line 84): true | | Assert.cs:86:24:86:27 | [b (line 84): true] null | b (line 84): true | | Assert.cs:86:31:86:32 | [b (line 84): false] "" | b (line 84): false | -| Assert.cs:87:9:87:31 | [b (line 84): false] call to method Assert | b (line 84): false | -| Assert.cs:87:9:87:31 | [b (line 84): true] call to method Assert | b (line 84): true | +| Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | b (line 84): false | +| Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | b (line 84): true | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | b (line 84): false | +| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | b (line 84): true | | Assert.cs:87:9:87:32 | [b (line 84): false] ...; | b (line 84): false | | Assert.cs:87:9:87:32 | [b (line 84): true] ...; | b (line 84): true | | Assert.cs:87:22:87:22 | [b (line 84): false] access to local variable s | b (line 84): false | @@ -31,8 +97,10 @@ booleanNode | Assert.cs:90:13:90:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | | Assert.cs:90:17:90:20 | [b (line 84): true] null | b (line 84): true | | Assert.cs:90:24:90:25 | [b (line 84): false] "" | b (line 84): false | -| Assert.cs:91:9:91:24 | [b (line 84): false] call to method IsNull | b (line 84): false | -| Assert.cs:91:9:91:24 | [b (line 84): true] call to method IsNull | b (line 84): true | +| Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | b (line 84): false | +| Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | b (line 84): true | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | b (line 84): false | +| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | b (line 84): true | | Assert.cs:91:9:91:25 | [b (line 84): false] ...; | b (line 84): false | | Assert.cs:91:9:91:25 | [b (line 84): true] ...; | b (line 84): true | | Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | b (line 84): false | @@ -55,8 +123,10 @@ booleanNode | Assert.cs:94:13:94:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | | Assert.cs:94:17:94:20 | [b (line 84): true] null | b (line 84): true | | Assert.cs:94:24:94:25 | [b (line 84): false] "" | b (line 84): false | -| Assert.cs:95:9:95:27 | [b (line 84): false] call to method IsNotNull | b (line 84): false | -| Assert.cs:95:9:95:27 | [b (line 84): true] call to method IsNotNull | b (line 84): true | +| Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | b (line 84): false | +| Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | b (line 84): true | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | b (line 84): false | +| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | b (line 84): true | | Assert.cs:95:9:95:28 | [b (line 84): false] ...; | b (line 84): false | | Assert.cs:95:9:95:28 | [b (line 84): true] ...; | b (line 84): true | | Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | b (line 84): false | @@ -79,8 +149,10 @@ booleanNode | Assert.cs:98:13:98:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | | Assert.cs:98:17:98:20 | [b (line 84): true] null | b (line 84): true | | Assert.cs:98:24:98:25 | [b (line 84): false] "" | b (line 84): false | -| Assert.cs:99:9:99:32 | [b (line 84): false] call to method IsTrue | b (line 84): false | -| Assert.cs:99:9:99:32 | [b (line 84): true] call to method IsTrue | b (line 84): true | +| Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | b (line 84): false | +| Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | b (line 84): true | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | b (line 84): false | +| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | b (line 84): true | | Assert.cs:99:9:99:33 | [b (line 84): false] ...; | b (line 84): false | | Assert.cs:99:9:99:33 | [b (line 84): true] ...; | b (line 84): true | | Assert.cs:99:23:99:23 | [b (line 84): false] access to local variable s | b (line 84): false | @@ -107,8 +179,10 @@ booleanNode | Assert.cs:102:13:102:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | | Assert.cs:102:17:102:20 | [b (line 84): true] null | b (line 84): true | | Assert.cs:102:24:102:25 | [b (line 84): false] "" | b (line 84): false | -| Assert.cs:103:9:103:32 | [b (line 84): false] call to method IsTrue | b (line 84): false | -| Assert.cs:103:9:103:32 | [b (line 84): true] call to method IsTrue | b (line 84): true | +| Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | b (line 84): false | +| Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | b (line 84): true | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | b (line 84): false | +| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | b (line 84): true | | Assert.cs:103:9:103:33 | [b (line 84): false] ...; | b (line 84): false | | Assert.cs:103:9:103:33 | [b (line 84): true] ...; | b (line 84): true | | Assert.cs:103:23:103:23 | [b (line 84): false] access to local variable s | b (line 84): false | @@ -135,8 +209,10 @@ booleanNode | Assert.cs:106:13:106:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | | Assert.cs:106:17:106:20 | [b (line 84): true] null | b (line 84): true | | Assert.cs:106:24:106:25 | [b (line 84): false] "" | b (line 84): false | -| Assert.cs:107:9:107:33 | [b (line 84): false] call to method IsFalse | b (line 84): false | -| Assert.cs:107:9:107:33 | [b (line 84): true] call to method IsFalse | b (line 84): true | +| Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | b (line 84): false | +| Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | b (line 84): true | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | b (line 84): false | +| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | b (line 84): true | | Assert.cs:107:9:107:34 | [b (line 84): false] ...; | b (line 84): false | | Assert.cs:107:9:107:34 | [b (line 84): true] ...; | b (line 84): true | | Assert.cs:107:24:107:24 | [b (line 84): false] access to local variable s | b (line 84): false | @@ -163,8 +239,10 @@ booleanNode | Assert.cs:110:13:110:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | | Assert.cs:110:17:110:20 | [b (line 84): true] null | b (line 84): true | | Assert.cs:110:24:110:25 | [b (line 84): false] "" | b (line 84): false | -| Assert.cs:111:9:111:33 | [b (line 84): false] call to method IsFalse | b (line 84): false | -| Assert.cs:111:9:111:33 | [b (line 84): true] call to method IsFalse | b (line 84): true | +| Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | b (line 84): false | +| Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | b (line 84): true | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | b (line 84): false | +| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | b (line 84): true | | Assert.cs:111:9:111:34 | [b (line 84): false] ...; | b (line 84): false | | Assert.cs:111:9:111:34 | [b (line 84): true] ...; | b (line 84): true | | Assert.cs:111:24:111:24 | [b (line 84): false] access to local variable s | b (line 84): false | @@ -191,8 +269,9 @@ booleanNode | Assert.cs:114:13:114:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | | Assert.cs:114:17:114:20 | [b (line 84): true] null | b (line 84): true | | Assert.cs:114:24:114:25 | [b (line 84): false] "" | b (line 84): false | -| Assert.cs:115:9:115:37 | [b (line 84): false] call to method IsTrue | b (line 84): false | -| Assert.cs:115:9:115:37 | [b (line 84): true] call to method IsTrue | b (line 84): true | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | b (line 84): false | +| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | b (line 84): true | +| Assert.cs:115:9:115:37 | [assertion success, b (line 84): true] call to method IsTrue | b (line 84): true | | Assert.cs:115:9:115:38 | [b (line 84): false] ...; | b (line 84): false | | Assert.cs:115:9:115:38 | [b (line 84): true] ...; | b (line 84): true | | Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | b (line 84): false | @@ -205,86 +284,57 @@ booleanNode | Assert.cs:115:28:115:31 | [b (line 84): true] null | b (line 84): true | | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | b (line 84): false | | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | b (line 84): true | -| Assert.cs:116:9:116:35 | [b (line 84): false] call to method WriteLine | b (line 84): false | | Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | b (line 84): true | -| Assert.cs:116:9:116:36 | [b (line 84): false] ...; | b (line 84): false | | Assert.cs:116:9:116:36 | [b (line 84): true] ...; | b (line 84): true | -| Assert.cs:116:27:116:27 | [b (line 84): false] access to local variable s | b (line 84): false | | Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | b (line 84): true | -| Assert.cs:116:27:116:34 | [b (line 84): false] access to property Length | b (line 84): false | | Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | b (line 84): true | -| Assert.cs:118:9:118:25 | [b (line 84): false] ... = ... | b (line 84): false | | Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | b (line 84): true | -| Assert.cs:118:9:118:26 | [b (line 84): false] ...; | b (line 84): false | | Assert.cs:118:9:118:26 | [b (line 84): true] ...; | b (line 84): true | -| Assert.cs:118:13:118:13 | [b (line 84): false] access to parameter b | b (line 84): false | | Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | b (line 84): true | -| Assert.cs:118:13:118:25 | [b (line 84): false] ... ? ... : ... | b (line 84): false | | Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | | Assert.cs:118:17:118:20 | [b (line 84): true] null | b (line 84): true | -| Assert.cs:118:24:118:25 | [b (line 84): false] "" | b (line 84): false | -| Assert.cs:119:9:119:39 | [b (line 84): false] call to method IsFalse | b (line 84): false | -| Assert.cs:119:9:119:39 | [b (line 84): true] call to method IsFalse | b (line 84): true | -| Assert.cs:119:9:119:40 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | b (line 84): true | +| Assert.cs:119:9:119:39 | [assertion success, b (line 84): true] call to method IsFalse | b (line 84): true | | Assert.cs:119:9:119:40 | [b (line 84): true] ...; | b (line 84): true | -| Assert.cs:119:24:119:24 | [b (line 84): false] access to local variable s | b (line 84): false | | Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | b (line 84): true | -| Assert.cs:119:24:119:32 | [b (line 84): false] ... == ... | b (line 84): false | | Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | b (line 84): true | -| Assert.cs:119:24:119:38 | [b (line 84): false] ... \|\| ... | b (line 84): false | | Assert.cs:119:24:119:38 | [b (line 84): true] ... \|\| ... | b (line 84): true | -| Assert.cs:119:29:119:32 | [b (line 84): false] null | b (line 84): false | | Assert.cs:119:29:119:32 | [b (line 84): true] null | b (line 84): true | -| Assert.cs:119:37:119:38 | [b (line 84): false] !... | b (line 84): false | | Assert.cs:119:37:119:38 | [b (line 84): true] !... | b (line 84): true | -| Assert.cs:119:38:119:38 | [b (line 84): false] access to parameter b | b (line 84): false | | Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | b (line 84): true | -| Assert.cs:120:9:120:35 | [b (line 84): false] call to method WriteLine | b (line 84): false | | Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | b (line 84): true | -| Assert.cs:120:9:120:36 | [b (line 84): false] ...; | b (line 84): false | | Assert.cs:120:9:120:36 | [b (line 84): true] ...; | b (line 84): true | -| Assert.cs:120:27:120:27 | [b (line 84): false] access to local variable s | b (line 84): false | | Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | b (line 84): true | -| Assert.cs:120:27:120:34 | [b (line 84): false] access to property Length | b (line 84): false | | Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | b (line 84): true | -| Assert.cs:122:9:122:25 | [b (line 84): false] ... = ... | b (line 84): false | | Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | b (line 84): true | -| Assert.cs:122:9:122:26 | [b (line 84): false] ...; | b (line 84): false | | Assert.cs:122:9:122:26 | [b (line 84): true] ...; | b (line 84): true | -| Assert.cs:122:13:122:13 | [b (line 84): false] access to parameter b | b (line 84): false | | Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | b (line 84): true | -| Assert.cs:122:13:122:25 | [b (line 84): false] ... ? ... : ... | b (line 84): false | | Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | | Assert.cs:122:17:122:20 | [b (line 84): true] null | b (line 84): true | -| Assert.cs:122:24:122:25 | [b (line 84): false] "" | b (line 84): false | -| Assert.cs:123:9:123:37 | [b (line 84): false] call to method IsTrue | b (line 84): false | -| Assert.cs:123:9:123:37 | [b (line 84): true] call to method IsTrue | b (line 84): true | -| Assert.cs:123:9:123:38 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | b (line 84): true | +| Assert.cs:123:9:123:37 | [assertion success, b (line 84): true] call to method IsTrue | b (line 84): true | | Assert.cs:123:9:123:38 | [b (line 84): true] ...; | b (line 84): true | -| Assert.cs:123:23:123:23 | [b (line 84): false] access to local variable s | b (line 84): false | | Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | b (line 84): true | -| Assert.cs:123:23:123:31 | [b (line 84): false] ... == ... | b (line 84): false | | Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | b (line 84): true | -| Assert.cs:123:23:123:36 | [b (line 84): false] ... && ... | b (line 84): false | | Assert.cs:123:23:123:36 | [b (line 84): true] ... && ... | b (line 84): true | -| Assert.cs:123:28:123:31 | [b (line 84): false] null | b (line 84): false | | Assert.cs:123:28:123:31 | [b (line 84): true] null | b (line 84): true | -| Assert.cs:123:36:123:36 | [b (line 84): false] access to parameter b | b (line 84): false | | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | b (line 84): true | -| Assert.cs:124:9:124:35 | [b (line 84): false] call to method WriteLine | b (line 84): false | | Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | b (line 84): true | -| Assert.cs:124:9:124:36 | [b (line 84): false] ...; | b (line 84): false | | Assert.cs:124:9:124:36 | [b (line 84): true] ...; | b (line 84): true | -| Assert.cs:124:27:124:27 | [b (line 84): false] access to local variable s | b (line 84): false | | Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | b (line 84): true | -| Assert.cs:124:27:124:34 | [b (line 84): false] access to property Length | b (line 84): false | | Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | b (line 84): true | -| Assert.cs:126:9:126:26 | [b (line 84): false] ...; | b (line 84): false | +| Assert.cs:126:9:126:25 | [b (line 84): true] ... = ... | b (line 84): true | | Assert.cs:126:9:126:26 | [b (line 84): true] ...; | b (line 84): true | -| Assert.cs:126:13:126:13 | [b (line 84): false] access to parameter b | b (line 84): false | | Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | b (line 84): true | -| Assert.cs:126:13:126:25 | [b (line 84): false] ... ? ... : ... | b (line 84): false | | Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | b (line 84): true | +| Assert.cs:126:17:126:20 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:127:9:127:40 | [b (line 84): true] ...; | b (line 84): true | +| Assert.cs:127:24:127:24 | [b (line 84): true] access to local variable s | b (line 84): true | +| Assert.cs:127:24:127:32 | [b (line 84): true] ... != ... | b (line 84): true | +| Assert.cs:127:24:127:38 | [b (line 84): true] ... \|\| ... | b (line 84): true | +| Assert.cs:127:29:127:32 | [b (line 84): true] null | b (line 84): true | +| Assert.cs:127:37:127:38 | [b (line 84): true] !... | b (line 84): true | +| Assert.cs:127:38:127:38 | [b (line 84): true] access to parameter b | b (line 84): true | | Conditions.cs:6:13:6:13 | [inc (line 3): true] access to parameter x | inc (line 3): true | | Conditions.cs:6:13:6:15 | [inc (line 3): true] ...++ | inc (line 3): true | | Conditions.cs:6:13:6:16 | [inc (line 3): true] ...; | inc (line 3): true | diff --git a/csharp/ql/test/library-tests/controlflow/guards/BooleanGuardedExpr.expected b/csharp/ql/test/library-tests/controlflow/guards/BooleanGuardedExpr.expected index 717a6770500..dcbf0ce8736 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/BooleanGuardedExpr.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/BooleanGuardedExpr.expected @@ -4,17 +4,9 @@ | Assert.cs:46:27:46:27 | access to local variable s | Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:24:45:24 | access to local variable s | false | | Assert.cs:53:27:53:27 | access to local variable s | Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:24:52:24 | access to local variable s | false | | Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | false | -| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:23:59:23 | access to local variable s | true | -| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:59:23:59:36 | ... && ... | Assert.cs:59:23:59:23 | access to local variable s | true | | Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | false | -| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:24:66:24 | access to local variable s | false | -| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:66:24:66:24 | access to local variable s | false | | Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | true | -| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:23:73:23 | access to local variable s | true | -| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:73:23:73:36 | ... && ... | Assert.cs:73:23:73:23 | access to local variable s | true | | Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | true | -| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:24:80:24 | access to local variable s | false | -| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:24:80:24 | access to local variable s | false | | Collections.cs:52:17:52:20 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false | | Collections.cs:53:9:53:12 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false | | Collections.cs:54:13:54:16 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false | diff --git a/csharp/ql/test/library-tests/controlflow/guards/GuardedControlFlowNode.expected b/csharp/ql/test/library-tests/controlflow/guards/GuardedControlFlowNode.expected index 5d351185f66..86e735716dc 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/GuardedControlFlowNode.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/GuardedControlFlowNode.expected @@ -10,26 +10,26 @@ | Assert.cs:46:27:46:27 | access to local variable s | Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:24:45:24 | access to local variable s | false | | Assert.cs:53:27:53:27 | access to local variable s | Assert.cs:52:24:52:24 | access to local variable s | Assert.cs:52:24:52:24 | access to local variable s | non-null | | Assert.cs:53:27:53:27 | access to local variable s | Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:24:52:24 | access to local variable s | false | -| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | false | -| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:58:20:58:32 | ... ? ... : ... | Assert.cs:58:20:58:20 | access to parameter b | non-null | -| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:59:23:59:23 | access to local variable s | Assert.cs:59:23:59:23 | access to local variable s | non-null | -| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:23:59:23 | access to local variable s | true | -| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:59:23:59:36 | ... && ... | Assert.cs:59:23:59:23 | access to local variable s | true | -| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | false | -| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:65:20:65:20 | access to parameter b | non-null | -| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:66:24:66:24 | access to local variable s | Assert.cs:66:24:66:24 | access to local variable s | non-null | -| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:24:66:24 | access to local variable s | false | -| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:66:24:66:24 | access to local variable s | false | -| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | true | -| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:72:20:72:20 | access to parameter b | null | -| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:73:23:73:23 | access to local variable s | Assert.cs:73:23:73:23 | access to local variable s | null | -| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:23:73:23 | access to local variable s | true | -| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:73:23:73:36 | ... && ... | Assert.cs:73:23:73:23 | access to local variable s | true | -| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | true | -| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:79:20:79:20 | access to parameter b | null | -| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:24 | access to local variable s | Assert.cs:80:24:80:24 | access to local variable s | null | -| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:24:80:24 | access to local variable s | false | -| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:24:80:24 | access to local variable s | false | +| Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | false | +| Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | Assert.cs:58:20:58:32 | ... ? ... : ... | Assert.cs:58:20:58:20 | access to parameter b | non-null | +| Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | false | +| Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | true | +| Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | Assert.cs:58:20:58:32 | ... ? ... : ... | Assert.cs:58:20:58:20 | access to parameter b | non-null | +| Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | false | +| Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:65:20:65:20 | access to parameter b | non-null | +| Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | false | +| Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | true | +| Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:65:20:65:20 | access to parameter b | non-null | +| Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | false | +| Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | true | +| Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:72:20:72:20 | access to parameter b | null | +| Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | true | +| Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:72:20:72:20 | access to parameter b | null | +| Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | false | +| Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | true | +| Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:79:20:79:20 | access to parameter b | null | +| Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | true | +| Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:79:20:79:20 | access to parameter b | null | | Collections.cs:52:17:52:20 | access to parameter args | Collections.cs:50:13:50:16 | access to parameter args | Collections.cs:50:13:50:16 | access to parameter args | non-empty | | Collections.cs:52:17:52:20 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false | | Collections.cs:53:9:53:12 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false | diff --git a/csharp/ql/test/library-tests/controlflow/guards/GuardedExpr.expected b/csharp/ql/test/library-tests/controlflow/guards/GuardedExpr.expected index adbc50cece7..66ee569c87b 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/GuardedExpr.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/GuardedExpr.expected @@ -12,24 +12,12 @@ | Assert.cs:53:27:53:27 | access to local variable s | Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:24:52:24 | access to local variable s | false | | Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | false | | Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:58:20:58:32 | ... ? ... : ... | Assert.cs:58:20:58:20 | access to parameter b | non-null | -| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:59:23:59:23 | access to local variable s | Assert.cs:59:23:59:23 | access to local variable s | non-null | -| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:23:59:23 | access to local variable s | true | -| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:59:23:59:36 | ... && ... | Assert.cs:59:23:59:23 | access to local variable s | true | | Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | false | | Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:65:20:65:20 | access to parameter b | non-null | -| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:66:24:66:24 | access to local variable s | Assert.cs:66:24:66:24 | access to local variable s | non-null | -| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:24:66:24 | access to local variable s | false | -| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:66:24:66:24 | access to local variable s | false | | Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | true | | Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:72:20:72:20 | access to parameter b | null | -| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:73:23:73:23 | access to local variable s | Assert.cs:73:23:73:23 | access to local variable s | null | -| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:23:73:23 | access to local variable s | true | -| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:73:23:73:36 | ... && ... | Assert.cs:73:23:73:23 | access to local variable s | true | | Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | true | | Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:79:20:79:20 | access to parameter b | null | -| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:24 | access to local variable s | Assert.cs:80:24:80:24 | access to local variable s | null | -| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:24:80:24 | access to local variable s | false | -| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:24:80:24 | access to local variable s | false | | Collections.cs:52:17:52:20 | access to parameter args | Collections.cs:50:13:50:16 | access to parameter args | Collections.cs:50:13:50:16 | access to parameter args | non-empty | | Collections.cs:52:17:52:20 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false | | Collections.cs:53:9:53:12 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false | diff --git a/csharp/ql/test/library-tests/controlflow/guards/Implications.expected b/csharp/ql/test/library-tests/controlflow/guards/Implications.expected index 8763eba9913..1f2bdd595ed 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/Implications.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/Implications.expected @@ -18,7 +18,9 @@ | Assert.cs:16:20:16:32 | ... ? ... : ... | null | Assert.cs:16:24:16:27 | null | null | | Assert.cs:17:23:17:23 | access to local variable s | empty | Assert.cs:16:20:16:32 | ... ? ... : ... | empty | | Assert.cs:17:23:17:23 | access to local variable s | non-empty | Assert.cs:16:20:16:32 | ... ? ... : ... | non-empty | +| Assert.cs:17:23:17:23 | access to local variable s | non-null | Assert.cs:16:20:16:20 | access to parameter b | false | | Assert.cs:17:23:17:23 | access to local variable s | non-null | Assert.cs:16:20:16:32 | ... ? ... : ... | non-null | +| Assert.cs:17:23:17:23 | access to local variable s | null | Assert.cs:16:20:16:20 | access to parameter b | true | | Assert.cs:17:23:17:23 | access to local variable s | null | Assert.cs:16:20:16:32 | ... ? ... : ... | null | | Assert.cs:18:27:18:27 | access to local variable s | non-null | Assert.cs:16:20:16:32 | ... ? ... : ... | non-null | | Assert.cs:18:27:18:27 | access to local variable s | null | Assert.cs:16:20:16:32 | ... ? ... : ... | null | @@ -28,7 +30,9 @@ | Assert.cs:23:20:23:32 | ... ? ... : ... | null | Assert.cs:23:24:23:27 | null | null | | Assert.cs:24:26:24:26 | access to local variable s | empty | Assert.cs:23:20:23:32 | ... ? ... : ... | empty | | Assert.cs:24:26:24:26 | access to local variable s | non-empty | Assert.cs:23:20:23:32 | ... ? ... : ... | non-empty | +| Assert.cs:24:26:24:26 | access to local variable s | non-null | Assert.cs:23:20:23:20 | access to parameter b | false | | Assert.cs:24:26:24:26 | access to local variable s | non-null | Assert.cs:23:20:23:32 | ... ? ... : ... | non-null | +| Assert.cs:24:26:24:26 | access to local variable s | null | Assert.cs:23:20:23:20 | access to parameter b | true | | Assert.cs:24:26:24:26 | access to local variable s | null | Assert.cs:23:20:23:32 | ... ? ... : ... | null | | Assert.cs:25:27:25:27 | access to local variable s | non-null | Assert.cs:23:20:23:32 | ... ? ... : ... | non-null | | Assert.cs:25:27:25:27 | access to local variable s | null | Assert.cs:23:20:23:32 | ... ? ... : ... | null | diff --git a/csharp/ql/test/library-tests/controlflow/guards/NullGuardedExpr.expected b/csharp/ql/test/library-tests/controlflow/guards/NullGuardedExpr.expected index 7c153f6e7aa..2fdd00e24b6 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/NullGuardedExpr.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/NullGuardedExpr.expected @@ -2,8 +2,6 @@ | Assert.cs:25:27:25:27 | access to local variable s | | Assert.cs:39:27:39:27 | access to local variable s | | Assert.cs:53:27:53:27 | access to local variable s | -| Assert.cs:60:27:60:27 | access to local variable s | -| Assert.cs:67:27:67:27 | access to local variable s | | Guards.cs:12:13:12:13 | access to parameter s | | Guards.cs:14:31:14:31 | access to parameter s | | Guards.cs:26:31:26:31 | access to parameter s | diff --git a/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.cs b/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.cs index e4f3781b10d..de8f52d77f3 100644 --- a/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.cs +++ b/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.cs @@ -289,7 +289,7 @@ class SignAnalysis void Assert(int i, bool b) { Debug.Assert(i > 0); - System.Console.WriteLine(i); // strictly positive [MISSING] + System.Console.WriteLine(i); // strictly positive if (b) System.Console.WriteLine(i); // strictly positive diff --git a/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.expected b/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.expected index ec16a427dcf..0e6cc20f05d 100644 --- a/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.expected +++ b/csharp/ql/test/library-tests/dataflow/signanalysis/SignAnalysis.expected @@ -156,6 +156,7 @@ | SignAnalysis.cs:278:42:278:42 | access to parameter k | positive | | SignAnalysis.cs:280:21:280:21 | access to parameter k | positive | | SignAnalysis.cs:280:26:280:26 | 5 | strictlyPositive | +| SignAnalysis.cs:292:34:292:34 | access to parameter i | strictlyPositive | | SignAnalysis.cs:295:38:295:38 | access to parameter i | strictlyPositive | | SignAnalysis.cs:300:27:300:28 | -... | strictlyNegative | | SignAnalysis.cs:300:28:300:28 | 1 | strictlyPositive | diff --git a/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.expected b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.expected index 31ef1b638e6..18340a5d5c8 100644 --- a/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.expected +++ b/csharp/ql/test/query-tests/API Abuse/FormatInvalid/FormatInvalid.expected @@ -48,7 +48,7 @@ nodes | FormatInvalid.cs:108:23:108:25 | "}" | semmle.label | "}" | | FormatInvalid.cs:109:23:109:25 | "}" | semmle.label | "}" | | FormatInvalid.cs:110:23:110:25 | "}" | semmle.label | "}" | -| FormatInvalid.cs:115:56:115:58 | "}" | semmle.label | "}" | +| FormatInvalid.cs:115:56:115:58 | [assertion success] "}" | semmle.label | [assertion success] "}" | | FormatInvalid.cs:116:18:116:20 | "}" | semmle.label | "}" | | FormatInvalid.cs:117:40:117:42 | "}" | semmle.label | "}" | | FormatInvalidBad.cs:7:30:7:44 | "class {0} { }" | semmle.label | "class {0} { }" | @@ -93,7 +93,7 @@ edges | FormatInvalid.cs:108:24:108:25 | "}" | FormatInvalid.cs:108:23:108:25 | "}" | FormatInvalid.cs:108:23:108:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:108:9:108:32 | call to method Write | this | | FormatInvalid.cs:109:24:109:25 | "}" | FormatInvalid.cs:109:23:109:25 | "}" | FormatInvalid.cs:109:23:109:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:109:9:109:35 | call to method Write | this | | FormatInvalid.cs:110:24:110:25 | "}" | FormatInvalid.cs:110:23:110:25 | "}" | FormatInvalid.cs:110:23:110:25 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:110:9:110:38 | call to method Write | this | -| FormatInvalid.cs:115:57:115:58 | "}" | FormatInvalid.cs:115:56:115:58 | "}" | FormatInvalid.cs:115:56:115:58 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:115:9:115:63 | call to method Assert | this | +| FormatInvalid.cs:115:57:115:58 | "}" | FormatInvalid.cs:115:56:115:58 | [assertion success] "}" | FormatInvalid.cs:115:56:115:58 | [assertion success] "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:115:9:115:63 | call to method Assert | this | | FormatInvalid.cs:116:19:116:20 | "}" | FormatInvalid.cs:116:18:116:20 | "}" | FormatInvalid.cs:116:18:116:20 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:116:9:116:24 | call to method Write | this | | FormatInvalid.cs:117:41:117:42 | "}" | FormatInvalid.cs:117:40:117:42 | "}" | FormatInvalid.cs:117:40:117:42 | "}" | Invalid format string used in $@ formatting call. | FormatInvalid.cs:117:9:117:47 | call to method Print | this | | FormatInvalidBad.cs:7:41:7:44 | "class {0} { }" | FormatInvalidBad.cs:7:30:7:44 | "class {0} { }" | FormatInvalidBad.cs:7:30:7:44 | "class {0} { }" | Invalid format string used in $@ formatting call. | FormatInvalidBad.cs:7:16:7:45 | call to method Format | this | diff --git a/csharp/ql/test/query-tests/Nullness/Implications.expected b/csharp/ql/test/query-tests/Nullness/Implications.expected index cd1c4113358..8ac85c3fe78 100644 --- a/csharp/ql/test/query-tests/Nullness/Implications.expected +++ b/csharp/ql/test/query-tests/Nullness/Implications.expected @@ -66,7 +66,9 @@ | Assert.cs:13:13:13:25 | ... ? ... : ... | null | Assert.cs:13:17:13:20 | null | null | | Assert.cs:14:23:14:23 | access to local variable s | empty | Assert.cs:13:13:13:25 | ... ? ... : ... | empty | | Assert.cs:14:23:14:23 | access to local variable s | non-empty | Assert.cs:13:13:13:25 | ... ? ... : ... | non-empty | +| Assert.cs:14:23:14:23 | access to local variable s | non-null | Assert.cs:13:13:13:13 | access to parameter b | false | | Assert.cs:14:23:14:23 | access to local variable s | non-null | Assert.cs:13:13:13:25 | ... ? ... : ... | non-null | +| Assert.cs:14:23:14:23 | access to local variable s | null | Assert.cs:13:13:13:13 | access to parameter b | true | | Assert.cs:14:23:14:23 | access to local variable s | null | Assert.cs:13:13:13:25 | ... ? ... : ... | null | | Assert.cs:15:27:15:27 | access to local variable s | non-null | Assert.cs:13:13:13:25 | ... ? ... : ... | non-null | | Assert.cs:15:27:15:27 | access to local variable s | null | Assert.cs:13:13:13:25 | ... ? ... : ... | null | @@ -76,7 +78,9 @@ | Assert.cs:17:13:17:25 | ... ? ... : ... | null | Assert.cs:17:17:17:20 | null | null | | Assert.cs:18:26:18:26 | access to local variable s | empty | Assert.cs:17:13:17:25 | ... ? ... : ... | empty | | Assert.cs:18:26:18:26 | access to local variable s | non-empty | Assert.cs:17:13:17:25 | ... ? ... : ... | non-empty | +| Assert.cs:18:26:18:26 | access to local variable s | non-null | Assert.cs:17:13:17:13 | access to parameter b | false | | Assert.cs:18:26:18:26 | access to local variable s | non-null | Assert.cs:17:13:17:25 | ... ? ... : ... | non-null | +| Assert.cs:18:26:18:26 | access to local variable s | null | Assert.cs:17:13:17:13 | access to parameter b | true | | Assert.cs:18:26:18:26 | access to local variable s | null | Assert.cs:17:13:17:25 | ... ? ... : ... | null | | Assert.cs:19:27:19:27 | access to local variable s | non-null | Assert.cs:17:13:17:25 | ... ? ... : ... | non-null | | Assert.cs:19:27:19:27 | access to local variable s | null | Assert.cs:17:13:17:25 | ... ? ... : ... | null | @@ -324,7 +328,9 @@ | C.cs:55:18:55:36 | ... ? ... : ... | null | C.cs:55:28:55:31 | null | null | | C.cs:56:23:56:24 | access to local variable o2 | empty | C.cs:55:18:55:36 | ... ? ... : ... | empty | | C.cs:56:23:56:24 | access to local variable o2 | non-empty | C.cs:55:18:55:36 | ... ? ... : ... | non-empty | +| C.cs:56:23:56:24 | access to local variable o2 | non-null | C.cs:55:18:55:24 | call to method Maybe | false | | C.cs:56:23:56:24 | access to local variable o2 | non-null | C.cs:55:18:55:36 | ... ? ... : ... | non-null | +| C.cs:56:23:56:24 | access to local variable o2 | null | C.cs:55:18:55:24 | call to method Maybe | true | | C.cs:56:23:56:24 | access to local variable o2 | null | C.cs:55:18:55:36 | ... ? ... : ... | null | | C.cs:57:9:57:10 | access to local variable o2 | non-null | C.cs:55:18:55:36 | ... ? ... : ... | non-null | | C.cs:57:9:57:10 | access to local variable o2 | null | C.cs:55:18:55:36 | ... ? ... : ... | null | @@ -348,7 +354,9 @@ | C.cs:70:18:70:46 | ... ? ... : ... | non-null | C.cs:70:35:70:46 | object creation of type Object | non-null | | C.cs:70:18:70:46 | ... ? ... : ... | null | C.cs:70:18:70:24 | call to method Maybe | true | | C.cs:70:18:70:46 | ... ? ... : ... | null | C.cs:70:28:70:31 | null | null | +| C.cs:71:26:71:27 | access to local variable o3 | non-null | C.cs:70:18:70:24 | call to method Maybe | false | | C.cs:71:26:71:27 | access to local variable o3 | non-null | C.cs:70:18:70:46 | ... ? ... : ... | non-null | +| C.cs:71:26:71:27 | access to local variable o3 | null | C.cs:70:18:70:24 | call to method Maybe | true | | C.cs:71:26:71:27 | access to local variable o3 | null | C.cs:70:18:70:46 | ... ? ... : ... | null | | C.cs:72:9:72:10 | access to local variable o3 | non-null | C.cs:70:18:70:46 | ... ? ... : ... | non-null | | C.cs:72:9:72:10 | access to local variable o3 | null | C.cs:70:18:70:46 | ... ? ... : ... | null | diff --git a/csharp/ql/test/query-tests/Nullness/NullCheck.expected b/csharp/ql/test/query-tests/Nullness/NullCheck.expected index 72cc5e64a0e..bf1d6480e64 100644 --- a/csharp/ql/test/query-tests/Nullness/NullCheck.expected +++ b/csharp/ql/test/query-tests/Nullness/NullCheck.expected @@ -1,5 +1,9 @@ | Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:22:10:22 | access to local variable s | false | true | | Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:22:10:22 | access to local variable s | true | false | +| Assert.cs:14:23:14:23 | access to local variable s | Assert.cs:14:23:14:23 | access to local variable s | non-null | false | +| Assert.cs:14:23:14:23 | access to local variable s | Assert.cs:14:23:14:23 | access to local variable s | null | true | +| Assert.cs:18:26:18:26 | access to local variable s | Assert.cs:18:26:18:26 | access to local variable s | non-null | false | +| Assert.cs:18:26:18:26 | access to local variable s | Assert.cs:18:26:18:26 | access to local variable s | null | true | | Assert.cs:22:23:22:31 | ... == ... | Assert.cs:22:23:22:23 | access to local variable s | false | false | | Assert.cs:22:23:22:31 | ... == ... | Assert.cs:22:23:22:23 | access to local variable s | true | true | | Assert.cs:26:23:26:31 | ... != ... | Assert.cs:26:23:26:23 | access to local variable s | false | true | @@ -60,6 +64,10 @@ | C.cs:41:22:41:30 | ... == ... | C.cs:41:22:41:22 | access to local variable s | true | true | | C.cs:45:22:45:30 | ... != ... | C.cs:45:22:45:22 | access to local variable s | false | true | | C.cs:45:22:45:30 | ... != ... | C.cs:45:22:45:22 | access to local variable s | true | false | +| C.cs:56:23:56:24 | access to local variable o2 | C.cs:56:23:56:24 | access to local variable o2 | non-null | false | +| C.cs:56:23:56:24 | access to local variable o2 | C.cs:56:23:56:24 | access to local variable o2 | null | true | +| C.cs:71:26:71:27 | access to local variable o3 | C.cs:71:26:71:27 | access to local variable o3 | non-null | false | +| C.cs:71:26:71:27 | access to local variable o3 | C.cs:71:26:71:27 | access to local variable o3 | null | true | | C.cs:78:13:78:24 | call to method IsNotNull | C.cs:78:23:78:23 | access to local variable o | false | true | | C.cs:78:13:78:24 | call to method IsNotNull | C.cs:78:23:78:23 | access to local variable o | true | false | | C.cs:82:14:82:22 | call to method IsNull | C.cs:82:21:82:21 | access to local variable o | false | false | diff --git a/csharp/ql/test/query-tests/Nullness/NullMaybe.expected b/csharp/ql/test/query-tests/Nullness/NullMaybe.expected index 3db367e90ba..6433b844ee0 100644 --- a/csharp/ql/test/query-tests/Nullness/NullMaybe.expected +++ b/csharp/ql/test/query-tests/Nullness/NullMaybe.expected @@ -30,14 +30,9 @@ nodes | Assert.cs:29:9:29:25 | [b (line 7): true] SSA def(s) | | Assert.cs:31:27:31:27 | access to local variable s | | Assert.cs:31:27:31:27 | access to local variable s | -| Assert.cs:45:9:45:25 | [b (line 7): false] SSA def(s) | | Assert.cs:45:9:45:25 | [b (line 7): true] SSA def(s) | -| Assert.cs:46:36:46:36 | [b (line 7): false] access to parameter b | -| Assert.cs:46:36:46:36 | [b (line 7): true] access to parameter b | | Assert.cs:47:27:47:27 | access to local variable s | -| Assert.cs:47:27:47:27 | access to local variable s | -| Assert.cs:49:9:49:25 | SSA def(s) | -| Assert.cs:50:37:50:38 | !... | +| Assert.cs:49:9:49:25 | [b (line 7): true] SSA def(s) | | Assert.cs:51:27:51:27 | access to local variable s | | B.cs:7:11:7:29 | SSA def(eqCallAlways) | | B.cs:10:11:10:30 | SSA def(neqCallAlways) | @@ -423,12 +418,8 @@ edges | Assert.cs:21:9:21:25 | [b (line 7): true] SSA def(s) | Assert.cs:23:27:23:27 | access to local variable s | | Assert.cs:29:9:29:25 | [b (line 7): false] SSA def(s) | Assert.cs:31:27:31:27 | access to local variable s | | Assert.cs:29:9:29:25 | [b (line 7): true] SSA def(s) | Assert.cs:31:27:31:27 | access to local variable s | -| Assert.cs:45:9:45:25 | [b (line 7): false] SSA def(s) | Assert.cs:46:36:46:36 | [b (line 7): false] access to parameter b | -| Assert.cs:45:9:45:25 | [b (line 7): true] SSA def(s) | Assert.cs:46:36:46:36 | [b (line 7): true] access to parameter b | -| Assert.cs:46:36:46:36 | [b (line 7): false] access to parameter b | Assert.cs:47:27:47:27 | access to local variable s | -| Assert.cs:46:36:46:36 | [b (line 7): true] access to parameter b | Assert.cs:47:27:47:27 | access to local variable s | -| Assert.cs:49:9:49:25 | SSA def(s) | Assert.cs:50:37:50:38 | !... | -| Assert.cs:50:37:50:38 | !... | Assert.cs:51:27:51:27 | access to local variable s | +| Assert.cs:45:9:45:25 | [b (line 7): true] SSA def(s) | Assert.cs:47:27:47:27 | access to local variable s | +| Assert.cs:49:9:49:25 | [b (line 7): true] SSA def(s) | Assert.cs:51:27:51:27 | access to local variable s | | B.cs:7:11:7:29 | SSA def(eqCallAlways) | B.cs:13:13:13:24 | access to local variable eqCallAlways | | B.cs:10:11:10:30 | SSA def(neqCallAlways) | B.cs:13:13:13:36 | ...; | | B.cs:10:11:10:30 | SSA def(neqCallAlways) | B.cs:15:9:16:26 | if (...) ... | From 1a93090778b05bb8914ad7d1b8051b9a3070af42 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 18 Sep 2020 12:01:10 +0200 Subject: [PATCH 190/411] C#: Improve guards SSA logic in the context of control-flow splitting --- csharp/ql/src/semmle/code/csharp/Caching.qll | 2 +- .../csharp/controlflow/ControlFlowElement.qll | 57 +++++++---- .../semmle/code/csharp/controlflow/Guards.qll | 99 +++++++++++-------- .../dataflow/internal/DataFlowPrivate.qll | 2 +- .../security/dataflow/ConditionalBypass.qll | 4 +- .../guards/BooleanGuardedExpr.expected | 5 + .../guards/GuardedControlFlowNode.expected | 10 ++ .../controlflow/guards/GuardedExpr.expected | 10 ++ .../controlflow/guards/Guards.cs | 2 +- .../guards/NullGuardedExpr.expected | 3 + 10 files changed, 129 insertions(+), 65 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/Caching.qll b/csharp/ql/src/semmle/code/csharp/Caching.qll index 9f6e2698f42..95ffbf9ffc9 100644 --- a/csharp/ql/src/semmle/code/csharp/Caching.qll +++ b/csharp/ql/src/semmle/code/csharp/Caching.qll @@ -39,7 +39,7 @@ module Stages { cached private predicate forceCachingInSameStageRev() { - any(ControlFlowElement cfe).controlsBlock(_, _) + any(ControlFlowElement cfe).controlsBlock(_, _, _) or exists(GuardedExpr ge) or diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowElement.qll b/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowElement.qll index a82416189fd..84d218e78d7 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowElement.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowElement.qll @@ -128,37 +128,42 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element { * does not work. */ pragma[nomagic] - private predicate immediatelyControlsBlockSplit(BasicBlock succ, ConditionalSuccessor s) { - exists(ConditionBlock cb | this.immediatelyControlsBlockSplit0(cb, succ, s) | - forall(BasicBlock pred, SuccessorType t | - this.immediatelyControlsBlockSplit1(cb, succ, s, pred, t) - | - this.immediatelyControlsBlockSplit2(cb, succ, s, pred, t) - ) + private predicate immediatelyControlsBlockSplit( + BasicBlock succ, ConditionalSuccessor s, ConditionBlock cb + ) { + this.immediatelyControlsBlockSplit0(cb, succ, s) and + forall(BasicBlock pred, SuccessorType t | + this.immediatelyControlsBlockSplit1(cb, succ, s, pred, t) + | + this.immediatelyControlsBlockSplit2(cb, succ, s, pred, t) ) } pragma[noinline] - private predicate controlsJoinBlockPredecessor(JoinBlock controlled, ConditionalSuccessor s, int i) { - this.controlsBlockSplit(controlled.getJoinBlockPredecessor(i), s) + private predicate controlsJoinBlockPredecessor( + JoinBlock controlled, ConditionalSuccessor s, int i, ConditionBlock cb + ) { + this.controlsBlockSplit(controlled.getJoinBlockPredecessor(i), s, cb) } private predicate controlsJoinBlockSplit(JoinBlock controlled, ConditionalSuccessor s, int i) { i = -1 and - this.controlsJoinBlockPredecessor(controlled, s, _) + this.controlsJoinBlockPredecessor(controlled, s, _, _) or this.controlsJoinBlockSplit(controlled, s, i - 1) and ( - this.controlsJoinBlockPredecessor(controlled, s, i) + this.controlsJoinBlockPredecessor(controlled, s, i, _) or controlled.dominates(controlled.getJoinBlockPredecessor(i)) ) } cached - private predicate controlsBlockSplit(BasicBlock controlled, ConditionalSuccessor s) { + private predicate controlsBlockSplit( + BasicBlock controlled, ConditionalSuccessor s, ConditionBlock cb + ) { Stages::GuardsStage::forceCachingInSameStage() and - this.immediatelyControlsBlockSplit(controlled, s) + this.immediatelyControlsBlockSplit(controlled, s, cb) or // Equivalent with // @@ -178,10 +183,11 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element { last = max(int i | exists(controlled.(JoinBlock).getJoinBlockPredecessor(i))) | this.controlsJoinBlockSplit(controlled, s, last) - ) + ) and + this.controlsJoinBlockPredecessor(controlled, s, _, cb) or not controlled instanceof JoinBlock and - this.controlsBlockSplit(controlled.getAPredecessor(), s) + this.controlsBlockSplit(controlled.getAPredecessor(), s, cb) } /** @@ -200,16 +206,25 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element { * ``` * * as control flow splitting is taken into account. + * + * `cb` records all of the possible condition blocks for this control flow element + * that a path from the callable entry point to `controlled` may go through. */ - predicate controlsBlock(BasicBlock controlled, ConditionalSuccessor s) { - this.controlsBlockSplit(controlled, s) + predicate controlsBlock(BasicBlock controlled, ConditionalSuccessor s, ConditionBlock cb) { + this.controlsBlockSplit(controlled, s, cb) or - exists(ConditionBlock cb | cb.getLastNode() = this.getAControlFlowNode() | - cb.controls(controlled, s) - ) + cb.getLastNode() = this.getAControlFlowNode() and + cb.controls(controlled, s) + } + + /** DEPRECATED: Use `controlsBlock/3` instead. */ + deprecated predicate controlsBlock(BasicBlock controlled, ConditionalSuccessor s) { + this.controlsBlock(controlled, s, _) } /** + * DEPRECATED. + * * Holds if control flow element `controlled` is controlled by this control flow * element with conditional value `s`. That is, `controlled` can only be reached * from the callable entry point by going via the `s` edge out of this element. @@ -227,7 +242,7 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element { */ // potentially very large predicate, so must be inlined pragma[inline] - predicate controlsElement(ControlFlowElement controlled, ConditionalSuccessor s) { + deprecated predicate controlsElement(ControlFlowElement controlled, ConditionalSuccessor s) { forex(BasicBlock bb | bb = controlled.getAControlFlowNode().getBasicBlock() | this.controlsBlock(bb, s) ) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll b/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll index 8097c4b6671..3bd57b848e5 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll @@ -36,7 +36,7 @@ class Guard extends Expr { * Holds if basic block `bb` is guarded by this expression having value `v`. */ predicate controlsBasicBlock(BasicBlock bb, AbstractValue v) { - Internal::guardControls(this, bb, v) + Internal::guardControls(this, _, bb, v) } /** @@ -1707,7 +1707,7 @@ module Internal { pragma[noinline] private predicate candidateAux(AccessOrCallExpr e, Declaration target, BasicBlock bb) { target = e.getTarget() and - exists(Guard g | e = getAChildExprStar(g) | guardControls(g, bb, _)) + exists(Guard g | e = getAChildExprStar(g) | guardControls(g, _, bb, _)) } } @@ -1715,33 +1715,51 @@ module Internal { private module Cached { private import semmle.code.csharp.Caching - /** Holds if basic block `bb` only is reached when guard `g` has abstract value `v`. */ + /** + * Holds if basic block `bb` only is reached when guard `g` has abstract value `v`. + * + * `cb` records all of the possible condition blocks for `g` that a path from the + * callable entry point to `bb` may go through. + */ cached - predicate guardControls(Guard g, BasicBlock bb, AbstractValue v) { - exists(AbstractValue v0, Guard g0 | impliesSteps(g0, v0, g, v) | - exists(ControlFlowElement cfe, ConditionalSuccessor s | - v0.branch(cfe, s, g0) and cfe.controlsBlock(bb, s) + predicate guardControls(Guard g, ConditionBlock cb, BasicBlock bb, AbstractValue v) { + exists(AbstractValue v0, Guard g0 | + impliesSteps(g0, v0, g, v) and + exists(ControlFlowElement cfe, ConditionalSuccessor cs | + v0.branch(cfe, cs, g0) and cfe.controlsBlock(bb, cs, cb) ) ) } pragma[noinline] - private predicate isGuardedByNode0( - ControlFlow::Node cfn, AccessOrCallExpr guarded, Guard g, AccessOrCallExpr sub, - AbstractValue v + private predicate nodeIsGuardedBySameSubExpr0( + ControlFlow::Node guardedCfn, AccessOrCallExpr guarded, Guard g, ConditionBlock cb, + AccessOrCallExpr sub, AbstractValue v ) { Stages::GuardsStage::forceCachingInSameStage() and - cfn = guarded.getAControlFlowNode() and - guardControls(g, cfn.getBasicBlock(), v) and + guardedCfn = guarded.getAControlFlowNode() and + guardControls(g, cb, guardedCfn.getBasicBlock(), v) and exists(ConditionOnExprComparisonConfig c | c.same(sub, guarded)) } pragma[noinline] - private predicate isGuardedByExpr1( - AccessOrCallExpr guarded, Guard g, AccessOrCallExpr sub, AbstractValue v + private predicate nodeIsGuardedBySameSubExpr( + ControlFlow::Node guardedCfn, AccessOrCallExpr guarded, Guard g, ConditionBlock cb, + AccessOrCallExpr sub, AbstractValue v ) { - forex(ControlFlow::Node cfn | cfn = guarded.getAControlFlowNode() | - isGuardedByNode0(cfn, guarded, g, sub, v) + nodeIsGuardedBySameSubExpr0(guardedCfn, guarded, g, cb, sub, v) and + sub = getAChildExprStar(g) + } + + pragma[noinline] + private predicate nodeIsGuardedBySameSubExprSsaDef( + ControlFlow::Node cfn, AccessOrCallExpr guarded, Guard g, ControlFlow::Node subCfn, + AccessOrCallExpr sub, AbstractValue v, Ssa::Definition def + ) { + exists(ConditionBlock cb | + nodeIsGuardedBySameSubExpr(cfn, guarded, g, cb, sub, v) and + subCfn.getBasicBlock().dominates(cb) and + def = sub.getAnSsaQualifier(subCfn) ) } @@ -1756,44 +1774,45 @@ module Internal { ) } + pragma[noinline] + private predicate isGuardedByExpr0( + AccessOrCallExpr guarded, Guard g, AccessOrCallExpr sub, AbstractValue v + ) { + forex(ControlFlow::Node cfn | cfn = guarded.getAControlFlowNode() | + nodeIsGuardedBySameSubExpr(cfn, guarded, g, _, sub, v) + ) + } + cached predicate isGuardedByExpr( AccessOrCallExpr guarded, Guard g, AccessOrCallExpr sub, AbstractValue v ) { - isGuardedByExpr1(guarded, g, sub, v) and - sub = getAChildExprStar(g) and - forall(Ssa::Definition def, ControlFlow::Node subCfn | def = sub.getAnSsaQualifier(subCfn) | - exists(ControlFlow::Node defCfn | def = guarded.getAnSsaQualifier(defCfn) | + isGuardedByExpr0(guarded, g, sub, v) and + forall(ControlFlow::Node subCfn, Ssa::Definition def | + nodeIsGuardedBySameSubExprSsaDef(_, guarded, g, subCfn, sub, v, def) + | + exists(ControlFlow::Node guardedCfn | + def = guarded.getAnSsaQualifier(guardedCfn) and if v.isReferentialProperty() - then adjacentReadPairSameVarUniquePredecessor(def, subCfn, defCfn) + then adjacentReadPairSameVarUniquePredecessor(def, subCfn, guardedCfn) else any() ) ) } - pragma[noinline] - private predicate isGuardedByNode1( - ControlFlow::Nodes::ElementNode guarded, Guard g, AccessOrCallExpr sub, AbstractValue v - ) { - isGuardedByNode0(guarded, _, g, sub, v) - } - - pragma[noinline] - private predicate isGuardedByNode2(ControlFlow::Nodes::ElementNode guarded, Ssa::Definition def) { - isGuardedByNode1(guarded, _, _, _) and - exists(BasicBlock bb | bb = guarded.getBasicBlock() | - def = guarded.getElement().(AccessOrCallExpr).getAnSsaQualifier(bb.getANode()) - ) - } - cached predicate isGuardedByNode( ControlFlow::Nodes::ElementNode guarded, Guard g, AccessOrCallExpr sub, AbstractValue v ) { - isGuardedByNode1(guarded, g, sub, v) and - sub = getAChildExprStar(g) and - forall(Ssa::Definition def, ControlFlow::Node subCfn | def = sub.getAnSsaQualifier(subCfn) | - isGuardedByNode2(guarded, def) and + nodeIsGuardedBySameSubExpr(guarded, _, g, _, sub, v) and + forall(ControlFlow::Node subCfn, Ssa::Definition def | + nodeIsGuardedBySameSubExprSsaDef(guarded, _, g, subCfn, sub, v, def) + | + def = + guarded + .getElement() + .(AccessOrCallExpr) + .getAnSsaQualifier(guarded.getBasicBlock().getANode()) and if v.isReferentialProperty() then adjacentReadPairSameVarUniquePredecessor(def, subCfn, guarded) else any() diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 5702fce60e4..7983b39114a 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -733,7 +733,7 @@ private module Cached { viableConstantBooleanParamArg(paramNode, bs.getValue().booleanNot(), call) and paramNode.getDefinition() = param and param.getARead() = guard and - guard.controlsBlock(n.getControlFlowNode().getBasicBlock(), bs) + guard.controlsBlock(n.getControlFlowNode().getBasicBlock(), bs, _) ) } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/ConditionalBypass.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/ConditionalBypass.qll index 0694b27f985..21399d50237 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/ConditionalBypass.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/ConditionalBypass.qll @@ -61,7 +61,9 @@ module UserControlledBypassOfSensitiveMethod { private predicate conditionControlsCall0( SensitiveExecutionMethodCall call, Expr e, ControlFlow::SuccessorTypes::BooleanSuccessor s ) { - forex(BasicBlock bb | bb = call.getAControlFlowNode().getBasicBlock() | e.controlsBlock(bb, s)) + forex(BasicBlock bb | bb = call.getAControlFlowNode().getBasicBlock() | + e.controlsBlock(bb, s, _) + ) } private predicate conditionControlsCall( diff --git a/csharp/ql/test/library-tests/controlflow/guards/BooleanGuardedExpr.expected b/csharp/ql/test/library-tests/controlflow/guards/BooleanGuardedExpr.expected index dcbf0ce8736..2264c96644f 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/BooleanGuardedExpr.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/BooleanGuardedExpr.expected @@ -4,9 +4,13 @@ | Assert.cs:46:27:46:27 | access to local variable s | Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:24:45:24 | access to local variable s | false | | Assert.cs:53:27:53:27 | access to local variable s | Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:24:52:24 | access to local variable s | false | | Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | false | +| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:23:59:23 | access to local variable s | true | | Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | false | +| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:24:66:24 | access to local variable s | false | | Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | true | +| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:23:73:23 | access to local variable s | true | | Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | true | +| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:24:80:24 | access to local variable s | false | | Collections.cs:52:17:52:20 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false | | Collections.cs:53:9:53:12 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false | | Collections.cs:54:13:54:16 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false | @@ -68,6 +72,7 @@ | Guards.cs:269:13:269:14 | access to parameter o1 | Guards.cs:268:13:268:41 | call to operator == | Guards.cs:268:13:268:14 | access to parameter o1 | true | | Guards.cs:271:13:271:14 | access to parameter o1 | Guards.cs:270:13:270:42 | call to operator == | Guards.cs:270:13:270:14 | access to parameter o1 | true | | Guards.cs:342:27:342:27 | access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | false | +| Guards.cs:343:31:343:31 | access to local variable s | Guards.cs:342:13:342:21 | ... != ... | Guards.cs:342:13:342:13 | access to local variable s | true | | Splitting.cs:13:17:13:17 | access to parameter o | Splitting.cs:12:17:12:25 | ... != ... | Splitting.cs:12:17:12:17 | access to parameter o | true | | Splitting.cs:23:24:23:24 | access to parameter o | Splitting.cs:22:17:22:25 | ... != ... | Splitting.cs:22:17:22:17 | access to parameter o | true | | Splitting.cs:25:13:25:13 | access to parameter o | Splitting.cs:22:17:22:25 | ... != ... | Splitting.cs:22:17:22:17 | access to parameter o | false | diff --git a/csharp/ql/test/library-tests/controlflow/guards/GuardedControlFlowNode.expected b/csharp/ql/test/library-tests/controlflow/guards/GuardedControlFlowNode.expected index 86e735716dc..a61814184f7 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/GuardedControlFlowNode.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/GuardedControlFlowNode.expected @@ -15,21 +15,29 @@ | Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | false | | Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | true | | Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | Assert.cs:58:20:58:32 | ... ? ... : ... | Assert.cs:58:20:58:20 | access to parameter b | non-null | +| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:59:23:59:23 | access to local variable s | Assert.cs:59:23:59:23 | access to local variable s | non-null | +| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:23:59:23 | access to local variable s | true | | Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | false | | Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:65:20:65:20 | access to parameter b | non-null | | Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | false | | Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | true | | Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:65:20:65:20 | access to parameter b | non-null | +| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:66:24:66:24 | access to local variable s | Assert.cs:66:24:66:24 | access to local variable s | non-null | +| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:24:66:24 | access to local variable s | false | | Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | false | | Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | true | | Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:72:20:72:20 | access to parameter b | null | | Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | true | | Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:72:20:72:20 | access to parameter b | null | +| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:73:23:73:23 | access to local variable s | Assert.cs:73:23:73:23 | access to local variable s | null | +| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:23:73:23 | access to local variable s | true | | Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | false | | Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | true | | Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:79:20:79:20 | access to parameter b | null | | Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | true | | Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:79:20:79:20 | access to parameter b | null | +| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:24 | access to local variable s | Assert.cs:80:24:80:24 | access to local variable s | null | +| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:24:80:24 | access to local variable s | false | | Collections.cs:52:17:52:20 | access to parameter args | Collections.cs:50:13:50:16 | access to parameter args | Collections.cs:50:13:50:16 | access to parameter args | non-empty | | Collections.cs:52:17:52:20 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false | | Collections.cs:53:9:53:12 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false | @@ -197,6 +205,8 @@ | Guards.cs:342:27:342:27 | [b (line 339): true] access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | false | | Guards.cs:342:27:342:27 | [b (line 339): true] access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | true | | Guards.cs:342:27:342:27 | [b (line 339): true] access to parameter b | Guards.cs:341:20:341:32 | ... ? ... : ... | Guards.cs:341:20:341:20 | access to parameter b | non-null | +| Guards.cs:343:31:343:31 | access to local variable s | Guards.cs:342:13:342:13 | access to local variable s | Guards.cs:342:13:342:13 | access to local variable s | non-null | +| Guards.cs:343:31:343:31 | access to local variable s | Guards.cs:342:13:342:21 | ... != ... | Guards.cs:342:13:342:13 | access to local variable s | true | | Splitting.cs:13:17:13:17 | [b (line 9): true] access to parameter o | Splitting.cs:12:17:12:17 | access to parameter o | Splitting.cs:12:17:12:17 | access to parameter o | non-null | | Splitting.cs:13:17:13:17 | [b (line 9): true] access to parameter o | Splitting.cs:12:17:12:25 | ... != ... | Splitting.cs:12:17:12:17 | access to parameter o | true | | Splitting.cs:14:13:14:13 | [b (line 9): false] access to parameter b | Splitting.cs:11:13:11:13 | access to parameter b | Splitting.cs:11:13:11:13 | access to parameter b | false | diff --git a/csharp/ql/test/library-tests/controlflow/guards/GuardedExpr.expected b/csharp/ql/test/library-tests/controlflow/guards/GuardedExpr.expected index 66ee569c87b..7e74adb0fc6 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/GuardedExpr.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/GuardedExpr.expected @@ -12,12 +12,20 @@ | Assert.cs:53:27:53:27 | access to local variable s | Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:24:52:24 | access to local variable s | false | | Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | false | | Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:58:20:58:32 | ... ? ... : ... | Assert.cs:58:20:58:20 | access to parameter b | non-null | +| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:59:23:59:23 | access to local variable s | Assert.cs:59:23:59:23 | access to local variable s | non-null | +| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:23:59:23 | access to local variable s | true | | Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | false | | Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:65:20:65:32 | ... ? ... : ... | Assert.cs:65:20:65:20 | access to parameter b | non-null | +| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:66:24:66:24 | access to local variable s | Assert.cs:66:24:66:24 | access to local variable s | non-null | +| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:24:66:24 | access to local variable s | false | | Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | true | | Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:72:20:72:32 | ... ? ... : ... | Assert.cs:72:20:72:20 | access to parameter b | null | +| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:73:23:73:23 | access to local variable s | Assert.cs:73:23:73:23 | access to local variable s | null | +| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:23:73:23 | access to local variable s | true | | Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | true | | Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:79:20:79:32 | ... ? ... : ... | Assert.cs:79:20:79:20 | access to parameter b | null | +| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:24 | access to local variable s | Assert.cs:80:24:80:24 | access to local variable s | null | +| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:24:80:24 | access to local variable s | false | | Collections.cs:52:17:52:20 | access to parameter args | Collections.cs:50:13:50:16 | access to parameter args | Collections.cs:50:13:50:16 | access to parameter args | non-empty | | Collections.cs:52:17:52:20 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false | | Collections.cs:53:9:53:12 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false | @@ -182,6 +190,8 @@ | Guards.cs:287:17:287:17 | access to parameter o | Guards.cs:276:16:276:16 | access to parameter o | Guards.cs:276:16:276:16 | access to parameter o | non-null | | Guards.cs:342:27:342:27 | access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | false | | Guards.cs:342:27:342:27 | access to parameter b | Guards.cs:341:20:341:32 | ... ? ... : ... | Guards.cs:341:20:341:20 | access to parameter b | non-null | +| Guards.cs:343:31:343:31 | access to local variable s | Guards.cs:342:13:342:13 | access to local variable s | Guards.cs:342:13:342:13 | access to local variable s | non-null | +| Guards.cs:343:31:343:31 | access to local variable s | Guards.cs:342:13:342:21 | ... != ... | Guards.cs:342:13:342:13 | access to local variable s | true | | Splitting.cs:13:17:13:17 | access to parameter o | Splitting.cs:12:17:12:17 | access to parameter o | Splitting.cs:12:17:12:17 | access to parameter o | non-null | | Splitting.cs:13:17:13:17 | access to parameter o | Splitting.cs:12:17:12:25 | ... != ... | Splitting.cs:12:17:12:17 | access to parameter o | true | | Splitting.cs:23:24:23:24 | access to parameter o | Splitting.cs:22:17:22:17 | access to parameter o | Splitting.cs:22:17:22:17 | access to parameter o | non-null | diff --git a/csharp/ql/test/library-tests/controlflow/guards/Guards.cs b/csharp/ql/test/library-tests/controlflow/guards/Guards.cs index b8e687c43bb..0c4563b3c9f 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/Guards.cs +++ b/csharp/ql/test/library-tests/controlflow/guards/Guards.cs @@ -340,7 +340,7 @@ public class Guards { string s = b ? null : ""; if (s != null && !b) - Console.WriteLine(s.Length); // null guarded [MISSING] + Console.WriteLine(s.Length); // null guarded } } diff --git a/csharp/ql/test/library-tests/controlflow/guards/NullGuardedExpr.expected b/csharp/ql/test/library-tests/controlflow/guards/NullGuardedExpr.expected index 2fdd00e24b6..eea5a4dadd3 100644 --- a/csharp/ql/test/library-tests/controlflow/guards/NullGuardedExpr.expected +++ b/csharp/ql/test/library-tests/controlflow/guards/NullGuardedExpr.expected @@ -2,6 +2,8 @@ | Assert.cs:25:27:25:27 | access to local variable s | | Assert.cs:39:27:39:27 | access to local variable s | | Assert.cs:53:27:53:27 | access to local variable s | +| Assert.cs:60:27:60:27 | access to local variable s | +| Assert.cs:67:27:67:27 | access to local variable s | | Guards.cs:12:13:12:13 | access to parameter s | | Guards.cs:14:31:14:31 | access to parameter s | | Guards.cs:26:31:26:31 | access to parameter s | @@ -43,6 +45,7 @@ | Guards.cs:279:17:279:17 | access to parameter o | | Guards.cs:283:17:283:17 | access to parameter o | | Guards.cs:287:17:287:17 | access to parameter o | +| Guards.cs:343:31:343:31 | access to local variable s | | Splitting.cs:13:17:13:17 | access to parameter o | | Splitting.cs:23:24:23:24 | access to parameter o | | Splitting.cs:35:13:35:13 | access to parameter o | From cc170bd513339a31131691398a4d1d8b98b71f7e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 Oct 2020 17:12:13 +0100 Subject: [PATCH 191/411] C++: Test layout. --- .../dataflow/taint-tests/localTaint.expected | 1748 ++++++++--------- .../dataflow/taint-tests/string.cpp | 11 +- .../dataflow/taint-tests/taint.expected | 226 +-- .../dataflow/taint-tests/test_diff.expected | 106 +- .../dataflow/taint-tests/test_ir.expected | 144 +- 5 files changed, 1121 insertions(+), 1114 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 7e362e8a2eb..26ed3c5c3dc 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -526,895 +526,895 @@ | stl.h:216:30:216:40 | call to allocator | stl.h:216:21:216:41 | noexcept(...) | TAINT | | stl.h:216:30:216:40 | call to allocator | stl.h:216:21:216:41 | noexcept(...) | TAINT | | stl.h:216:53:216:63 | 0 | stl.h:216:46:216:64 | (no string representation) | TAINT | -| string.cpp:24:12:24:17 | call to source | string.cpp:28:7:28:7 | a | | -| string.cpp:25:16:25:20 | 123 | string.cpp:25:16:25:21 | call to basic_string | TAINT | -| string.cpp:25:16:25:21 | call to basic_string | string.cpp:29:7:29:7 | b | | -| string.cpp:25:16:25:21 | call to basic_string | string.cpp:31:7:31:7 | b | | -| string.cpp:26:16:26:21 | call to source | string.cpp:26:16:26:24 | call to basic_string | TAINT | -| string.cpp:26:16:26:24 | call to basic_string | string.cpp:30:7:30:7 | c | | -| string.cpp:26:16:26:24 | call to basic_string | string.cpp:32:7:32:7 | c | | -| string.cpp:31:7:31:7 | b | string.cpp:31:9:31:13 | call to c_str | TAINT | -| string.cpp:32:7:32:7 | c | string.cpp:32:9:32:13 | call to c_str | TAINT | -| string.cpp:37:16:37:28 | call to basic_string | string.cpp:38:7:38:11 | path1 | | -| string.cpp:37:17:37:26 | call to user_input | string.cpp:37:16:37:28 | call to basic_string | TAINT | -| string.cpp:38:7:38:11 | path1 | string.cpp:38:13:38:17 | call to c_str | TAINT | -| string.cpp:41:10:41:19 | call to user_input | string.cpp:41:10:41:21 | call to basic_string | TAINT | -| string.cpp:41:10:41:21 | call to basic_string | string.cpp:41:2:41:21 | ... = ... | | -| string.cpp:41:10:41:21 | call to basic_string | string.cpp:42:7:42:11 | path2 | | -| string.cpp:42:7:42:11 | path2 | string.cpp:42:13:42:17 | call to c_str | TAINT | -| string.cpp:44:15:44:24 | call to user_input | string.cpp:44:15:44:27 | call to basic_string | TAINT | -| string.cpp:44:15:44:27 | call to basic_string | string.cpp:45:7:45:11 | path3 | | -| string.cpp:45:7:45:11 | path3 | string.cpp:45:13:45:17 | call to c_str | TAINT | -| string.cpp:50:19:50:24 | call to source | string.cpp:53:17:53:18 | cs | | -| string.cpp:50:19:50:24 | call to source | string.cpp:55:7:55:8 | cs | | -| string.cpp:53:17:53:18 | cs | string.cpp:53:17:53:19 | call to basic_string | TAINT | -| string.cpp:53:17:53:19 | call to basic_string | string.cpp:56:7:56:8 | ss | | -| string.cpp:61:19:61:24 | call to source | string.cpp:64:17:64:18 | cs | | -| string.cpp:64:17:64:18 | cs | string.cpp:64:17:64:19 | call to basic_string | TAINT | -| string.cpp:64:17:64:19 | call to basic_string | string.cpp:67:7:67:8 | ss | | -| string.cpp:64:17:64:19 | call to basic_string | string.cpp:70:7:70:8 | ss | | -| string.cpp:67:7:67:8 | ss | string.cpp:67:10:67:14 | call to c_str | TAINT | -| string.cpp:67:10:67:14 | call to c_str | string.cpp:67:2:67:16 | ... = ... | | -| string.cpp:67:10:67:14 | call to c_str | string.cpp:69:7:69:8 | cs | | -| string.cpp:76:18:76:24 | hello | string.cpp:76:18:76:25 | call to basic_string | TAINT | -| string.cpp:76:18:76:25 | call to basic_string | string.cpp:81:8:81:9 | s1 | | -| string.cpp:77:19:77:26 | call to basic_string | string.cpp:82:8:82:9 | s2 | | -| string.cpp:77:20:77:26 | hello | string.cpp:77:19:77:26 | call to basic_string | TAINT | -| string.cpp:79:8:79:14 | call to basic_string | string.cpp:79:3:79:14 | ... = ... | | -| string.cpp:79:8:79:14 | call to basic_string | string.cpp:83:8:83:9 | s3 | | -| string.cpp:79:8:79:14 | hello | string.cpp:79:8:79:14 | call to basic_string | TAINT | -| string.cpp:87:18:87:23 | call to source | string.cpp:87:18:87:26 | call to basic_string | TAINT | -| string.cpp:87:18:87:26 | call to basic_string | string.cpp:92:8:92:9 | s1 | | -| string.cpp:88:19:88:27 | call to basic_string | string.cpp:93:8:93:9 | s2 | | -| string.cpp:88:20:88:25 | call to source | string.cpp:88:19:88:27 | call to basic_string | TAINT | -| string.cpp:90:8:90:13 | call to source | string.cpp:90:8:90:15 | call to basic_string | TAINT | -| string.cpp:90:8:90:15 | call to basic_string | string.cpp:90:3:90:15 | ... = ... | | -| string.cpp:90:8:90:15 | call to basic_string | string.cpp:94:8:94:9 | s3 | | -| string.cpp:98:15:98:16 | call to basic_string | string.cpp:99:20:99:21 | s1 | | -| string.cpp:98:15:98:16 | call to basic_string | string.cpp:101:8:101:9 | s1 | | -| string.cpp:98:15:98:16 | call to basic_string | string.cpp:103:8:103:9 | s1 | | -| string.cpp:99:20:99:21 | s1 | string.cpp:104:8:104:9 | s2 | | -| string.cpp:101:8:101:9 | s1 | string.cpp:101:3:101:9 | ... = ... | | -| string.cpp:101:8:101:9 | s1 | string.cpp:105:8:105:9 | s3 | | -| string.cpp:109:19:109:40 | call to basic_string | string.cpp:113:8:113:9 | s1 | | -| string.cpp:109:32:109:37 | call to source | string.cpp:109:19:109:40 | call to basic_string | TAINT | -| string.cpp:111:8:111:28 | call to basic_string | string.cpp:111:3:111:28 | ... = ... | | -| string.cpp:111:8:111:28 | call to basic_string | string.cpp:114:8:114:9 | s2 | | -| string.cpp:111:20:111:25 | call to source | string.cpp:111:8:111:28 | call to basic_string | TAINT | -| string.cpp:119:16:119:21 | call to source | string.cpp:119:16:119:24 | call to basic_string | TAINT | -| string.cpp:119:16:119:24 | call to basic_string | string.cpp:120:15:120:15 | s | | -| string.cpp:119:16:119:24 | call to basic_string | string.cpp:124:33:124:33 | s | | -| 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++ | | -| 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 | -| string.cpp:120:15:120:15 | call to begin | string.cpp:120:15:120:15 | (__begin) | | -| string.cpp:120:15:120:15 | call to begin | string.cpp:120:15:120:15 | (__begin) | | -| string.cpp:120:15:120:15 | call to begin | string.cpp:120:15:120:15 | (__begin) | | -| string.cpp:120:15:120:15 | call to end | string.cpp:120:15:120:15 | (__end) | | -| string.cpp:120:15:120:15 | call to operator* | string.cpp:121:8:121:8 | c | | -| string.cpp:120:15:120:15 | ref arg (__begin) | string.cpp:120:15:120:15 | (__begin) | | -| string.cpp:120:15:120:15 | ref arg (__begin) | string.cpp:120:15:120:15 | (__begin) | | -| string.cpp:120:15:120:15 | ref arg (__begin) | string.cpp:120:15:120:15 | (__begin) | | -| string.cpp:120:15:120:15 | ref arg (__range) | string.cpp:120:15:120:15 | (__range) | | -| string.cpp:120:15:120:15 | s | string.cpp:120:15:120:15 | (__range) | | -| string.cpp:120:15:120:15 | s | string.cpp:120:15:120:15 | (__range) | | -| string.cpp:120:15:120:15 | s | string.cpp:120:15:120:15 | call to operator* | TAINT | -| string.cpp:124:33:124:33 | ref arg s | string.cpp:124:50:124:50 | s | | -| string.cpp:124:33:124:33 | ref arg s | string.cpp:128:16:128:16 | s | | -| string.cpp:124:33:124:33 | s | string.cpp:124:35:124:39 | call to begin | TAINT | -| string.cpp:124:35:124:39 | call to begin | string.cpp:124:44:124:45 | it | | -| string.cpp:124:35:124:39 | call to begin | string.cpp:124:61:124:62 | it | | -| string.cpp:124:35:124:39 | call to begin | string.cpp:125:9:125:10 | it | | -| 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++ | | -| 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++ | | -| 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 | -| string.cpp:128:16:128:16 | call to begin | string.cpp:128:16:128:16 | (__begin) | | -| string.cpp:128:16:128:16 | call to begin | string.cpp:128:16:128:16 | (__begin) | | -| string.cpp:128:16:128:16 | call to begin | string.cpp:128:16:128:16 | (__begin) | | -| string.cpp:128:16:128:16 | call to end | string.cpp:128:16:128:16 | (__end) | | -| string.cpp:128:16:128:16 | call to operator* | string.cpp:129:8:129:8 | c | | -| string.cpp:128:16:128:16 | ref arg (__begin) | string.cpp:128:16:128:16 | (__begin) | | -| string.cpp:128:16:128:16 | ref arg (__begin) | string.cpp:128:16:128:16 | (__begin) | | -| string.cpp:128:16:128:16 | ref arg (__begin) | string.cpp:128:16:128:16 | (__begin) | | -| string.cpp:128:16:128:16 | ref arg (__range) | string.cpp:128:16:128:16 | (__range) | | -| string.cpp:128:16:128:16 | s | string.cpp:128:16:128:16 | (__range) | | -| string.cpp:128:16:128:16 | s | string.cpp:128:16:128:16 | (__range) | | -| string.cpp:128:16:128:16 | s | string.cpp:128:16:128:16 | call to operator* | TAINT | -| 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++ | | -| 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) | | -| string.cpp:133:22:133:22 | call to begin | string.cpp:133:22:133:22 | (__begin) | | -| string.cpp:133:22:133:22 | call to begin | string.cpp:133:22:133:22 | (__begin) | | -| string.cpp:133:22:133:22 | call to end | string.cpp:133:22:133:22 | (__end) | | -| string.cpp:133:22:133:22 | call to operator* | string.cpp:134:8:134:8 | c | | -| string.cpp:133:22:133:22 | ref arg (__begin) | string.cpp:133:22:133:22 | (__begin) | | -| string.cpp:133:22:133:22 | ref arg (__begin) | string.cpp:133:22:133:22 | (__begin) | | -| string.cpp:133:22:133:22 | ref arg (__begin) | string.cpp:133:22:133:22 | (__begin) | | -| string.cpp:133:22:133:28 | const_s | string.cpp:133:22:133:22 | (__range) | | -| string.cpp:133:22:133:28 | const_s | string.cpp:133:22:133:22 | (__range) | | -| string.cpp:133:22:133:28 | const_s | string.cpp:133:22:133:22 | call to operator* | TAINT | -| string.cpp:140:18:140:24 | hello | string.cpp:140:18:140:25 | call to basic_string | TAINT | -| string.cpp:140:18:140:25 | call to basic_string | string.cpp:143:8:143:9 | s1 | | -| string.cpp:140:18:140:25 | call to basic_string | string.cpp:143:13:143:14 | s1 | | -| string.cpp:140:18:140:25 | call to basic_string | string.cpp:144:8:144:9 | s1 | | -| string.cpp:140:18:140:25 | call to basic_string | string.cpp:145:13:145:14 | s1 | | -| string.cpp:140:18:140:25 | call to basic_string | string.cpp:148:8:148:9 | s1 | | -| string.cpp:140:18:140:25 | call to basic_string | string.cpp:149:8:149:9 | s1 | | -| string.cpp:141:18:141:23 | call to source | string.cpp:141:18:141:26 | call to basic_string | TAINT | -| string.cpp:141:18:141:26 | call to basic_string | string.cpp:144:13:144:14 | s2 | | -| string.cpp:141:18:141:26 | call to basic_string | string.cpp:145:8:145:9 | s2 | | -| string.cpp:141:18:141:26 | call to basic_string | string.cpp:146:8:146:9 | s2 | | -| string.cpp:141:18:141:26 | call to basic_string | string.cpp:146:13:146:14 | s2 | | -| string.cpp:143:8:143:9 | s1 | string.cpp:143:11:143:11 | call to operator+ | TAINT | -| string.cpp:143:13:143:14 | s1 | string.cpp:143:11:143:11 | call to operator+ | TAINT | +| string.cpp:25:12:25:17 | call to source | string.cpp:29:7:29:7 | a | | +| string.cpp:26:16:26:20 | 123 | string.cpp:26:16:26:21 | call to basic_string | TAINT | +| string.cpp:26:16:26:21 | call to basic_string | string.cpp:30:7:30:7 | b | | +| string.cpp:26:16:26:21 | call to basic_string | string.cpp:32:7:32:7 | b | | +| string.cpp:27:16:27:21 | call to source | string.cpp:27:16:27:24 | call to basic_string | TAINT | +| string.cpp:27:16:27:24 | call to basic_string | string.cpp:31:7:31:7 | c | | +| string.cpp:27:16:27:24 | call to basic_string | string.cpp:33:7:33:7 | c | | +| string.cpp:32:7:32:7 | b | string.cpp:32:9:32:13 | call to c_str | TAINT | +| string.cpp:33:7:33:7 | c | string.cpp:33:9:33:13 | call to c_str | TAINT | +| string.cpp:38:16:38:28 | call to basic_string | string.cpp:39:7:39:11 | path1 | | +| string.cpp:38:17:38:26 | call to user_input | string.cpp:38:16:38:28 | call to basic_string | TAINT | +| string.cpp:39:7:39:11 | path1 | string.cpp:39:13:39:17 | call to c_str | TAINT | +| string.cpp:42:10:42:19 | call to user_input | string.cpp:42:10:42:21 | call to basic_string | TAINT | +| string.cpp:42:10:42:21 | call to basic_string | string.cpp:42:2:42:21 | ... = ... | | +| string.cpp:42:10:42:21 | call to basic_string | string.cpp:43:7:43:11 | path2 | | +| string.cpp:43:7:43:11 | path2 | string.cpp:43:13:43:17 | call to c_str | TAINT | +| string.cpp:45:15:45:24 | call to user_input | string.cpp:45:15:45:27 | call to basic_string | TAINT | +| string.cpp:45:15:45:27 | call to basic_string | string.cpp:46:7:46:11 | path3 | | +| string.cpp:46:7:46:11 | path3 | string.cpp:46:13:46:17 | call to c_str | TAINT | +| string.cpp:51:19:51:24 | call to source | string.cpp:54:17:54:18 | cs | | +| string.cpp:51:19:51:24 | call to source | string.cpp:56:7:56:8 | cs | | +| string.cpp:54:17:54:18 | cs | string.cpp:54:17:54:19 | call to basic_string | TAINT | +| string.cpp:54:17:54:19 | call to basic_string | string.cpp:57:7:57:8 | ss | | +| string.cpp:62:19:62:24 | call to source | string.cpp:65:17:65:18 | cs | | +| string.cpp:65:17:65:18 | cs | string.cpp:65:17:65:19 | call to basic_string | TAINT | +| string.cpp:65:17:65:19 | call to basic_string | string.cpp:68:7:68:8 | ss | | +| string.cpp:65:17:65:19 | call to basic_string | string.cpp:71:7:71:8 | ss | | +| string.cpp:68:7:68:8 | ss | string.cpp:68:10:68:14 | call to c_str | TAINT | +| string.cpp:68:10:68:14 | call to c_str | string.cpp:68:2:68:16 | ... = ... | | +| string.cpp:68:10:68:14 | call to c_str | string.cpp:70:7:70:8 | cs | | +| string.cpp:77:18:77:24 | hello | string.cpp:77:18:77:25 | call to basic_string | TAINT | +| string.cpp:77:18:77:25 | call to basic_string | string.cpp:82:8:82:9 | s1 | | +| string.cpp:78:19:78:26 | call to basic_string | string.cpp:83:8:83:9 | s2 | | +| string.cpp:78:20:78:26 | hello | string.cpp:78:19:78:26 | call to basic_string | TAINT | +| string.cpp:80:8:80:14 | call to basic_string | string.cpp:80:3:80:14 | ... = ... | | +| string.cpp:80:8:80:14 | call to basic_string | string.cpp:84:8:84:9 | s3 | | +| string.cpp:80:8:80:14 | hello | string.cpp:80:8:80:14 | call to basic_string | TAINT | +| string.cpp:88:18:88:23 | call to source | string.cpp:88:18:88:26 | call to basic_string | TAINT | +| string.cpp:88:18:88:26 | call to basic_string | string.cpp:93:8:93:9 | s1 | | +| string.cpp:89:19:89:27 | call to basic_string | string.cpp:94:8:94:9 | s2 | | +| string.cpp:89:20:89:25 | call to source | string.cpp:89:19:89:27 | call to basic_string | TAINT | +| string.cpp:91:8:91:13 | call to source | string.cpp:91:8:91:15 | call to basic_string | TAINT | +| string.cpp:91:8:91:15 | call to basic_string | string.cpp:91:3:91:15 | ... = ... | | +| string.cpp:91:8:91:15 | call to basic_string | string.cpp:95:8:95:9 | s3 | | +| string.cpp:99:15:99:16 | call to basic_string | string.cpp:100:20:100:21 | s1 | | +| string.cpp:99:15:99:16 | call to basic_string | string.cpp:102:8:102:9 | s1 | | +| string.cpp:99:15:99:16 | call to basic_string | string.cpp:104:8:104:9 | s1 | | +| string.cpp:100:20:100:21 | s1 | string.cpp:105:8:105:9 | s2 | | +| string.cpp:102:8:102:9 | s1 | string.cpp:102:3:102:9 | ... = ... | | +| string.cpp:102:8:102:9 | s1 | string.cpp:106:8:106:9 | s3 | | +| string.cpp:110:19:110:40 | call to basic_string | string.cpp:114:8:114:9 | s1 | | +| string.cpp:110:32:110:37 | call to source | string.cpp:110:19:110:40 | call to basic_string | TAINT | +| string.cpp:112:8:112:28 | call to basic_string | string.cpp:112:3:112:28 | ... = ... | | +| string.cpp:112:8:112:28 | call to basic_string | string.cpp:115:8:115:9 | s2 | | +| string.cpp:112:20:112:25 | call to source | string.cpp:112:8:112:28 | call to basic_string | TAINT | +| string.cpp:120:16:120:21 | call to source | string.cpp:120:16:120:24 | call to basic_string | TAINT | +| string.cpp:120:16:120:24 | call to basic_string | string.cpp:121:15:121:15 | s | | +| string.cpp:120:16:120:24 | call to basic_string | string.cpp:125:33:125:33 | s | | +| string.cpp:120:16:120:24 | call to basic_string | string.cpp:125:50:125:50 | s | | +| string.cpp:120:16:120:24 | call to basic_string | string.cpp:129:16:129:16 | s | | +| string.cpp:121:15:121:15 | (__begin) | string.cpp:121:15:121:15 | call to operator* | TAINT | +| string.cpp:121:15:121:15 | (__begin) | string.cpp:121:15:121:15 | call to operator++ | | +| string.cpp:121:15:121:15 | (__end) | string.cpp:121:15:121:15 | call to iterator | | +| string.cpp:121:15:121:15 | (__range) | string.cpp:121:15:121:15 | call to begin | TAINT | +| string.cpp:121:15:121:15 | (__range) | string.cpp:121:15:121:15 | call to end | TAINT | +| string.cpp:121:15:121:15 | call to begin | string.cpp:121:15:121:15 | (__begin) | | +| string.cpp:121:15:121:15 | call to begin | string.cpp:121:15:121:15 | (__begin) | | +| string.cpp:121:15:121:15 | call to begin | string.cpp:121:15:121:15 | (__begin) | | +| string.cpp:121:15:121:15 | call to end | string.cpp:121:15:121:15 | (__end) | | +| string.cpp:121:15:121:15 | call to operator* | string.cpp:122:8:122:8 | c | | +| string.cpp:121:15:121:15 | ref arg (__begin) | string.cpp:121:15:121:15 | (__begin) | | +| string.cpp:121:15:121:15 | ref arg (__begin) | string.cpp:121:15:121:15 | (__begin) | | +| string.cpp:121:15:121:15 | ref arg (__begin) | string.cpp:121:15:121:15 | (__begin) | | +| string.cpp:121:15:121:15 | ref arg (__range) | string.cpp:121:15:121:15 | (__range) | | +| string.cpp:121:15:121:15 | s | string.cpp:121:15:121:15 | (__range) | | +| string.cpp:121:15:121:15 | s | string.cpp:121:15:121:15 | (__range) | | +| string.cpp:121:15:121:15 | s | string.cpp:121:15:121:15 | call to operator* | TAINT | +| string.cpp:125:33:125:33 | ref arg s | string.cpp:125:50:125:50 | s | | +| string.cpp:125:33:125:33 | ref arg s | string.cpp:129:16:129:16 | s | | +| string.cpp:125:33:125:33 | s | string.cpp:125:35:125:39 | call to begin | TAINT | +| string.cpp:125:35:125:39 | call to begin | string.cpp:125:44:125:45 | it | | +| string.cpp:125:35:125:39 | call to begin | string.cpp:125:61:125:62 | it | | +| string.cpp:125:35:125:39 | call to begin | string.cpp:126:9:126:10 | it | | +| string.cpp:125:50:125:50 | ref arg s | string.cpp:125:50:125:50 | s | | +| string.cpp:125:50:125:50 | ref arg s | string.cpp:129:16:129:16 | s | | +| string.cpp:125:50:125:50 | s | string.cpp:125:52:125:54 | call to end | TAINT | +| string.cpp:125:61:125:62 | it | string.cpp:125:59:125:59 | call to operator++ | | +| string.cpp:125:61:125:62 | ref arg it | string.cpp:125:44:125:45 | it | | +| string.cpp:125:61:125:62 | ref arg it | string.cpp:125:61:125:62 | it | | +| string.cpp:125:61:125:62 | ref arg it | string.cpp:126:9:126:10 | it | | +| string.cpp:126:9:126:10 | it | string.cpp:126:8:126:8 | call to operator* | TAINT | +| string.cpp:129:16:129:16 | (__begin) | string.cpp:129:16:129:16 | call to operator* | TAINT | +| string.cpp:129:16:129:16 | (__begin) | string.cpp:129:16:129:16 | call to operator++ | | +| string.cpp:129:16:129:16 | (__end) | string.cpp:129:16:129:16 | call to iterator | | +| string.cpp:129:16:129:16 | (__range) | string.cpp:129:16:129:16 | call to begin | TAINT | +| string.cpp:129:16:129:16 | (__range) | string.cpp:129:16:129:16 | call to end | TAINT | +| string.cpp:129:16:129:16 | call to begin | string.cpp:129:16:129:16 | (__begin) | | +| string.cpp:129:16:129:16 | call to begin | string.cpp:129:16:129:16 | (__begin) | | +| string.cpp:129:16:129:16 | call to begin | string.cpp:129:16:129:16 | (__begin) | | +| string.cpp:129:16:129:16 | call to end | string.cpp:129:16:129:16 | (__end) | | +| string.cpp:129:16:129:16 | call to operator* | string.cpp:130:8:130:8 | c | | +| string.cpp:129:16:129:16 | ref arg (__begin) | string.cpp:129:16:129:16 | (__begin) | | +| string.cpp:129:16:129:16 | ref arg (__begin) | string.cpp:129:16:129:16 | (__begin) | | +| string.cpp:129:16:129:16 | ref arg (__begin) | string.cpp:129:16:129:16 | (__begin) | | +| string.cpp:129:16:129:16 | ref arg (__range) | string.cpp:129:16:129:16 | (__range) | | +| string.cpp:129:16:129:16 | s | string.cpp:129:16:129:16 | (__range) | | +| string.cpp:129:16:129:16 | s | string.cpp:129:16:129:16 | (__range) | | +| string.cpp:129:16:129:16 | s | string.cpp:129:16:129:16 | call to operator* | TAINT | +| string.cpp:133:28:133:33 | call to source | string.cpp:133:28:133:36 | call to basic_string | TAINT | +| string.cpp:133:28:133:36 | call to basic_string | string.cpp:134:22:134:28 | const_s | | +| string.cpp:134:22:134:22 | (__begin) | string.cpp:134:22:134:22 | call to operator* | TAINT | +| string.cpp:134:22:134:22 | (__begin) | string.cpp:134:22:134:22 | call to operator++ | | +| string.cpp:134:22:134:22 | (__range) | string.cpp:134:22:134:22 | call to begin | TAINT | +| string.cpp:134:22:134:22 | (__range) | string.cpp:134:22:134:22 | call to end | TAINT | +| string.cpp:134:22:134:22 | call to begin | string.cpp:134:22:134:22 | (__begin) | | +| string.cpp:134:22:134:22 | call to begin | string.cpp:134:22:134:22 | (__begin) | | +| string.cpp:134:22:134:22 | call to begin | string.cpp:134:22:134:22 | (__begin) | | +| string.cpp:134:22:134:22 | call to end | string.cpp:134:22:134:22 | (__end) | | +| string.cpp:134:22:134:22 | call to operator* | string.cpp:135:8:135:8 | c | | +| string.cpp:134:22:134:22 | ref arg (__begin) | string.cpp:134:22:134:22 | (__begin) | | +| string.cpp:134:22:134:22 | ref arg (__begin) | string.cpp:134:22:134:22 | (__begin) | | +| string.cpp:134:22:134:22 | ref arg (__begin) | string.cpp:134:22:134:22 | (__begin) | | +| string.cpp:134:22:134:28 | const_s | string.cpp:134:22:134:22 | (__range) | | +| string.cpp:134:22:134:28 | const_s | string.cpp:134:22:134:22 | (__range) | | +| string.cpp:134:22:134:28 | const_s | string.cpp:134:22:134:22 | call to operator* | TAINT | +| string.cpp:141:18:141:24 | hello | string.cpp:141:18:141:25 | call to basic_string | TAINT | +| string.cpp:141:18:141:25 | call to basic_string | string.cpp:144:8:144:9 | s1 | | +| string.cpp:141:18:141:25 | call to basic_string | string.cpp:144:13:144:14 | s1 | | +| string.cpp:141:18:141:25 | call to basic_string | string.cpp:145:8:145:9 | s1 | | +| string.cpp:141:18:141:25 | call to basic_string | string.cpp:146:13:146:14 | s1 | | +| string.cpp:141:18:141:25 | call to basic_string | string.cpp:149:8:149:9 | s1 | | +| string.cpp:141:18:141:25 | call to basic_string | string.cpp:150:8:150:9 | s1 | | +| string.cpp:142:18:142:23 | call to source | string.cpp:142:18:142:26 | call to basic_string | TAINT | +| string.cpp:142:18:142:26 | call to basic_string | string.cpp:145:13:145:14 | s2 | | +| string.cpp:142:18:142:26 | call to basic_string | string.cpp:146:8:146:9 | s2 | | +| string.cpp:142:18:142:26 | call to basic_string | string.cpp:147:8:147:9 | s2 | | +| string.cpp:142:18:142:26 | call to basic_string | string.cpp:147:13:147:14 | s2 | | | string.cpp:144:8:144:9 | s1 | string.cpp:144:11:144:11 | call to operator+ | TAINT | -| string.cpp:144:13:144:14 | s2 | string.cpp:144:11:144:11 | call to operator+ | TAINT | -| string.cpp:145:8:145:9 | s2 | string.cpp:145:11:145:11 | call to operator+ | TAINT | -| string.cpp:145:13:145:14 | s1 | string.cpp:145:11:145:11 | call to operator+ | TAINT | +| string.cpp:144:13:144:14 | s1 | string.cpp:144:11:144:11 | call to operator+ | TAINT | +| string.cpp:145:8:145:9 | s1 | string.cpp:145:11:145:11 | call to operator+ | TAINT | +| string.cpp:145:13:145:14 | s2 | string.cpp:145:11:145:11 | call to operator+ | TAINT | | string.cpp:146:8:146:9 | s2 | string.cpp:146:11:146:11 | call to operator+ | TAINT | -| string.cpp:146:13:146:14 | s2 | string.cpp:146:11:146:11 | call to operator+ | TAINT | -| string.cpp:148:8:148:9 | s1 | string.cpp:148:11:148:11 | call to operator+ | TAINT | -| string.cpp:148:13:148:20 | world | string.cpp:148:11:148:11 | call to operator+ | TAINT | +| string.cpp:146:13:146:14 | s1 | string.cpp:146:11:146:11 | call to operator+ | TAINT | +| string.cpp:147:8:147:9 | s2 | string.cpp:147:11:147:11 | call to operator+ | TAINT | +| string.cpp:147:13:147:14 | s2 | string.cpp:147:11:147:11 | call to operator+ | TAINT | | string.cpp:149:8:149:9 | s1 | string.cpp:149:11:149:11 | call to operator+ | TAINT | -| string.cpp:149:13:149:18 | call to source | string.cpp:149:11:149:11 | call to operator+ | TAINT | -| string.cpp:153:18:153:22 | abc | string.cpp:153:18:153:23 | call to basic_string | TAINT | -| string.cpp:153:18:153:23 | call to basic_string | string.cpp:157:8:157:9 | s3 | | -| string.cpp:153:18:153:23 | call to basic_string | string.cpp:160:8:160:9 | s3 | | -| string.cpp:153:18:153:23 | call to basic_string | string.cpp:164:8:164:9 | s3 | | -| string.cpp:153:18:153:23 | call to basic_string | string.cpp:169:8:169:9 | s3 | | -| string.cpp:153:18:153:23 | call to basic_string | string.cpp:173:8:173:9 | s3 | | -| string.cpp:154:18:154:23 | call to source | string.cpp:154:18:154:26 | call to basic_string | TAINT | -| string.cpp:154:18:154:26 | call to basic_string | string.cpp:157:13:157:14 | s4 | | -| string.cpp:154:18:154:26 | call to basic_string | string.cpp:161:14:161:15 | s4 | | -| string.cpp:154:18:154:26 | call to basic_string | string.cpp:170:13:170:14 | s4 | | -| string.cpp:157:8:157:9 | s3 | string.cpp:157:11:157:11 | call to operator+ | TAINT | -| string.cpp:157:11:157:11 | call to operator+ | string.cpp:157:3:157:14 | ... = ... | | -| string.cpp:157:11:157:11 | call to operator+ | string.cpp:158:8:158:9 | s5 | | -| string.cpp:157:13:157:14 | s4 | string.cpp:157:11:157:11 | call to operator+ | TAINT | -| string.cpp:160:8:160:9 | s3 | string.cpp:160:3:160:9 | ... = ... | | -| string.cpp:160:8:160:9 | s3 | string.cpp:161:8:161:9 | s6 | | -| string.cpp:160:8:160:9 | s3 | string.cpp:162:8:162:9 | s6 | | -| string.cpp:161:8:161:9 | ref arg s6 | string.cpp:162:8:162:9 | s6 | | -| string.cpp:161:8:161:9 | s6 | string.cpp:161:11:161:11 | call to operator+= | TAINT | -| string.cpp:161:14:161:15 | s4 | string.cpp:161:8:161:9 | ref arg s6 | TAINT | -| string.cpp:161:14:161:15 | s4 | string.cpp:161:11:161:11 | call to operator+= | TAINT | -| string.cpp:164:8:164:9 | s3 | string.cpp:164:3:164:9 | ... = ... | | -| string.cpp:164:8:164:9 | s3 | string.cpp:165:8:165:9 | s7 | | -| string.cpp:164:8:164:9 | s3 | string.cpp:166:8:166:9 | s7 | | -| string.cpp:164:8:164:9 | s3 | string.cpp:167:8:167:9 | s7 | | -| string.cpp:165:8:165:9 | ref arg s7 | string.cpp:166:8:166:9 | s7 | | -| string.cpp:165:8:165:9 | ref arg s7 | string.cpp:167:8:167:9 | s7 | | -| string.cpp:165:8:165:9 | s7 | string.cpp:165:11:165:11 | call to operator+= | TAINT | -| string.cpp:165:14:165:19 | call to source | string.cpp:165:8:165:9 | ref arg s7 | TAINT | -| string.cpp:165:14:165:19 | call to source | string.cpp:165:11:165:11 | call to operator+= | TAINT | +| string.cpp:149:13:149:20 | world | string.cpp:149:11:149:11 | call to operator+ | TAINT | +| string.cpp:150:8:150:9 | s1 | string.cpp:150:11:150:11 | call to operator+ | TAINT | +| string.cpp:150:13:150:18 | call to source | string.cpp:150:11:150:11 | call to operator+ | TAINT | +| string.cpp:154:18:154:22 | abc | string.cpp:154:18:154:23 | call to basic_string | TAINT | +| string.cpp:154:18:154:23 | call to basic_string | string.cpp:158:8:158:9 | s3 | | +| string.cpp:154:18:154:23 | call to basic_string | string.cpp:161:8:161:9 | s3 | | +| string.cpp:154:18:154:23 | call to basic_string | string.cpp:165:8:165:9 | s3 | | +| string.cpp:154:18:154:23 | call to basic_string | string.cpp:170:8:170:9 | s3 | | +| string.cpp:154:18:154:23 | call to basic_string | string.cpp:174:8:174:9 | s3 | | +| string.cpp:155:18:155:23 | call to source | string.cpp:155:18:155:26 | call to basic_string | TAINT | +| string.cpp:155:18:155:26 | call to basic_string | string.cpp:158:13:158:14 | s4 | | +| string.cpp:155:18:155:26 | call to basic_string | string.cpp:162:14:162:15 | s4 | | +| string.cpp:155:18:155:26 | call to basic_string | string.cpp:171:13:171:14 | s4 | | +| string.cpp:158:8:158:9 | s3 | string.cpp:158:11:158:11 | call to operator+ | TAINT | +| string.cpp:158:11:158:11 | call to operator+ | string.cpp:158:3:158:14 | ... = ... | | +| string.cpp:158:11:158:11 | call to operator+ | string.cpp:159:8:159:9 | s5 | | +| string.cpp:158:13:158:14 | s4 | string.cpp:158:11:158:11 | call to operator+ | TAINT | +| string.cpp:161:8:161:9 | s3 | string.cpp:161:3:161:9 | ... = ... | | +| string.cpp:161:8:161:9 | s3 | string.cpp:162:8:162:9 | s6 | | +| string.cpp:161:8:161:9 | s3 | string.cpp:163:8:163:9 | s6 | | +| string.cpp:162:8:162:9 | ref arg s6 | string.cpp:163:8:163:9 | s6 | | +| string.cpp:162:8:162:9 | s6 | string.cpp:162:11:162:11 | call to operator+= | TAINT | +| string.cpp:162:14:162:15 | s4 | string.cpp:162:8:162:9 | ref arg s6 | TAINT | +| string.cpp:162:14:162:15 | s4 | string.cpp:162:11:162:11 | call to operator+= | TAINT | +| string.cpp:165:8:165:9 | s3 | string.cpp:165:3:165:9 | ... = ... | | +| string.cpp:165:8:165:9 | s3 | string.cpp:166:8:166:9 | s7 | | +| string.cpp:165:8:165:9 | s3 | string.cpp:167:8:167:9 | s7 | | +| string.cpp:165:8:165:9 | s3 | string.cpp:168:8:168:9 | s7 | | | string.cpp:166:8:166:9 | ref arg s7 | string.cpp:167:8:167:9 | s7 | | +| string.cpp:166:8:166:9 | ref arg s7 | string.cpp:168:8:168:9 | s7 | | | string.cpp:166:8:166:9 | s7 | string.cpp:166:11:166:11 | call to operator+= | TAINT | -| string.cpp:166:14:166:16 | | string.cpp:166:8:166:9 | ref arg s7 | TAINT | -| string.cpp:166:14:166:16 | | string.cpp:166:11:166:11 | call to operator+= | TAINT | -| string.cpp:169:8:169:9 | s3 | string.cpp:169:3:169:9 | ... = ... | | -| string.cpp:169:8:169:9 | s3 | string.cpp:170:3:170:4 | s8 | | -| string.cpp:169:8:169:9 | s3 | string.cpp:171:8:171:9 | s8 | | -| string.cpp:170:3:170:4 | ref arg s8 | string.cpp:171:8:171:9 | s8 | | -| string.cpp:170:3:170:4 | s8 | string.cpp:170:6:170:11 | call to append | TAINT | -| string.cpp:170:13:170:14 | s4 | string.cpp:170:3:170:4 | ref arg s8 | TAINT | -| string.cpp:170:13:170:14 | s4 | string.cpp:170:6:170:11 | call to append | TAINT | -| string.cpp:173:8:173:9 | s3 | string.cpp:173:3:173:9 | ... = ... | | -| string.cpp:173:8:173:9 | s3 | string.cpp:174:3:174:4 | s9 | | -| string.cpp:173:8:173:9 | s3 | string.cpp:175:3:175:4 | s9 | | -| string.cpp:173:8:173:9 | s3 | string.cpp:176:8:176:9 | s9 | | -| string.cpp:174:3:174:4 | ref arg s9 | string.cpp:175:3:175:4 | s9 | | -| string.cpp:174:3:174:4 | ref arg s9 | string.cpp:176:8:176:9 | s9 | | -| string.cpp:174:3:174:4 | s9 | string.cpp:174:6:174:11 | call to append | TAINT | -| string.cpp:174:13:174:18 | call to source | string.cpp:174:3:174:4 | ref arg s9 | TAINT | -| string.cpp:174:13:174:18 | call to source | string.cpp:174:6:174:11 | call to append | TAINT | -| string.cpp:175:3:175:4 | ref arg s9 | string.cpp:176:8:176:9 | s9 | | +| string.cpp:166:14:166:19 | call to source | string.cpp:166:8:166:9 | ref arg s7 | TAINT | +| string.cpp:166:14:166:19 | call to source | string.cpp:166:11:166:11 | call to operator+= | TAINT | +| string.cpp:167:8:167:9 | ref arg s7 | string.cpp:168:8:168:9 | s7 | | +| string.cpp:167:8:167:9 | s7 | string.cpp:167:11:167:11 | call to operator+= | TAINT | +| string.cpp:167:14:167:16 | | string.cpp:167:8:167:9 | ref arg s7 | TAINT | +| string.cpp:167:14:167:16 | | string.cpp:167:11:167:11 | call to operator+= | TAINT | +| string.cpp:170:8:170:9 | s3 | string.cpp:170:3:170:9 | ... = ... | | +| string.cpp:170:8:170:9 | s3 | string.cpp:171:3:171:4 | s8 | | +| string.cpp:170:8:170:9 | s3 | string.cpp:172:8:172:9 | s8 | | +| string.cpp:171:3:171:4 | ref arg s8 | string.cpp:172:8:172:9 | s8 | | +| string.cpp:171:3:171:4 | s8 | string.cpp:171:6:171:11 | call to append | TAINT | +| string.cpp:171:13:171:14 | s4 | string.cpp:171:3:171:4 | ref arg s8 | TAINT | +| string.cpp:171:13:171:14 | s4 | string.cpp:171:6:171:11 | call to append | TAINT | +| string.cpp:174:8:174:9 | s3 | string.cpp:174:3:174:9 | ... = ... | | +| string.cpp:174:8:174:9 | s3 | string.cpp:175:3:175:4 | s9 | | +| string.cpp:174:8:174:9 | s3 | string.cpp:176:3:176:4 | s9 | | +| string.cpp:174:8:174:9 | s3 | string.cpp:177:8:177:9 | s9 | | +| string.cpp:175:3:175:4 | ref arg s9 | string.cpp:176:3:176:4 | s9 | | +| string.cpp:175:3:175:4 | ref arg s9 | string.cpp:177:8:177:9 | s9 | | | string.cpp:175:3:175:4 | s9 | string.cpp:175:6:175:11 | call to append | TAINT | -| string.cpp:175:13:175:15 | | string.cpp:175:3:175:4 | ref arg s9 | TAINT | -| string.cpp:175:13:175:15 | | string.cpp:175:6:175:11 | call to append | TAINT | -| string.cpp:180:19:180:23 | abc | string.cpp:180:19:180:24 | call to basic_string | TAINT | -| string.cpp:180:19:180:24 | call to basic_string | string.cpp:183:3:183:5 | s10 | | -| string.cpp:180:19:180:24 | call to basic_string | string.cpp:184:8:184:10 | s10 | | -| string.cpp:181:12:181:26 | call to source | string.cpp:183:17:183:17 | c | | -| string.cpp:183:3:183:5 | ref arg s10 | string.cpp:184:8:184:10 | s10 | | -| string.cpp:183:3:183:5 | s10 | string.cpp:183:7:183:12 | call to append | TAINT | -| string.cpp:183:17:183:17 | c | string.cpp:183:3:183:5 | ref arg s10 | TAINT | -| string.cpp:183:17:183:17 | c | string.cpp:183:7:183:12 | call to append | TAINT | -| string.cpp:189:17:189:23 | hello | string.cpp:189:17:189:24 | call to basic_string | TAINT | -| string.cpp:189:17:189:24 | call to basic_string | string.cpp:195:17:195:18 | s1 | | -| string.cpp:189:17:189:24 | call to basic_string | string.cpp:204:17:204:18 | s1 | | -| string.cpp:190:17:190:22 | call to source | string.cpp:190:17:190:25 | call to basic_string | TAINT | -| string.cpp:190:17:190:25 | call to basic_string | string.cpp:198:17:198:18 | s2 | | -| string.cpp:191:11:191:25 | call to source | string.cpp:201:21:201:21 | c | | -| string.cpp:192:14:192:15 | call to basic_string | string.cpp:195:7:195:8 | s3 | | -| string.cpp:192:14:192:15 | call to basic_string | string.cpp:196:7:196:8 | s3 | | -| string.cpp:192:18:192:19 | call to basic_string | string.cpp:198:7:198:8 | s4 | | -| string.cpp:192:18:192:19 | call to basic_string | string.cpp:199:7:199:8 | s4 | | -| string.cpp:192:22:192:23 | call to basic_string | string.cpp:201:7:201:8 | s5 | | -| string.cpp:192:22:192:23 | call to basic_string | string.cpp:202:7:202:8 | s5 | | -| string.cpp:193:17:193:22 | call to source | string.cpp:193:17:193:25 | call to basic_string | TAINT | -| string.cpp:193:17:193:25 | call to basic_string | string.cpp:204:7:204:8 | s6 | | -| string.cpp:193:17:193:25 | call to basic_string | string.cpp:205:7:205:8 | s6 | | -| string.cpp:195:7:195:8 | ref arg s3 | string.cpp:196:7:196:8 | s3 | | -| string.cpp:195:17:195:18 | s1 | string.cpp:195:7:195:8 | ref arg s3 | TAINT | -| string.cpp:195:17:195:18 | s1 | string.cpp:195:10:195:15 | call to assign | TAINT | -| string.cpp:198:7:198:8 | ref arg s4 | string.cpp:199:7:199:8 | s4 | | -| string.cpp:198:17:198:18 | s2 | string.cpp:198:7:198:8 | ref arg s4 | TAINT | -| string.cpp:198:17:198:18 | s2 | string.cpp:198:10:198:15 | call to assign | TAINT | -| string.cpp:201:7:201:8 | ref arg s5 | string.cpp:202:7:202:8 | s5 | | -| string.cpp:201:21:201:21 | c | string.cpp:201:7:201:8 | ref arg s5 | TAINT | -| string.cpp:201:21:201:21 | c | string.cpp:201:10:201:15 | call to assign | TAINT | -| string.cpp:204:7:204:8 | ref arg s6 | string.cpp:205:7:205:8 | s6 | | -| string.cpp:204:17:204:18 | s1 | string.cpp:204:7:204:8 | ref arg s6 | TAINT | -| string.cpp:204:17:204:18 | s1 | string.cpp:204:10:204:15 | call to assign | TAINT | -| string.cpp:209:17:209:23 | hello | string.cpp:209:17:209:24 | call to basic_string | TAINT | -| string.cpp:209:17:209:24 | call to basic_string | string.cpp:214:7:214:8 | s1 | | -| string.cpp:209:17:209:24 | call to basic_string | string.cpp:215:20:215:21 | s1 | | -| string.cpp:209:17:209:24 | call to basic_string | string.cpp:219:20:219:21 | s1 | | -| string.cpp:209:17:209:24 | call to basic_string | string.cpp:222:7:222:8 | s1 | | -| string.cpp:209:17:209:24 | call to basic_string | string.cpp:226:7:226:8 | s1 | | -| string.cpp:210:17:210:22 | call to source | string.cpp:210:17:210:25 | call to basic_string | TAINT | -| string.cpp:210:17:210:25 | call to basic_string | string.cpp:218:7:218:8 | s2 | | -| string.cpp:210:17:210:25 | call to basic_string | string.cpp:223:20:223:21 | s2 | | -| string.cpp:211:11:211:25 | call to source | string.cpp:227:24:227:24 | c | | -| string.cpp:214:7:214:8 | s1 | string.cpp:214:2:214:8 | ... = ... | | -| string.cpp:214:7:214:8 | s1 | string.cpp:215:7:215:8 | s3 | | -| string.cpp:214:7:214:8 | s1 | string.cpp:216:7:216:8 | s3 | | -| string.cpp:215:7:215:8 | ref arg s3 | string.cpp:216:7:216:8 | s3 | | -| string.cpp:215:7:215:8 | s3 | string.cpp:215:10:215:15 | call to insert | TAINT | -| string.cpp:215:20:215:21 | s1 | string.cpp:215:7:215:8 | ref arg s3 | TAINT | -| string.cpp:215:20:215:21 | s1 | string.cpp:215:10:215:15 | call to insert | TAINT | -| string.cpp:218:7:218:8 | s2 | string.cpp:218:2:218:8 | ... = ... | | -| string.cpp:218:7:218:8 | s2 | string.cpp:219:7:219:8 | s4 | | -| string.cpp:218:7:218:8 | s2 | string.cpp:220:7:220:8 | s4 | | -| string.cpp:219:7:219:8 | ref arg s4 | string.cpp:220:7:220:8 | s4 | | -| string.cpp:219:7:219:8 | s4 | string.cpp:219:10:219:15 | call to insert | TAINT | -| string.cpp:219:20:219:21 | s1 | string.cpp:219:7:219:8 | ref arg s4 | TAINT | -| string.cpp:219:20:219:21 | s1 | string.cpp:219:10:219:15 | call to insert | TAINT | -| string.cpp:222:7:222:8 | s1 | string.cpp:222:2:222:8 | ... = ... | | -| string.cpp:222:7:222:8 | s1 | string.cpp:223:7:223:8 | s5 | | -| string.cpp:222:7:222:8 | s1 | string.cpp:224:7:224:8 | s5 | | -| string.cpp:223:7:223:8 | ref arg s5 | string.cpp:224:7:224:8 | s5 | | -| string.cpp:223:7:223:8 | s5 | string.cpp:223:10:223:15 | call to insert | TAINT | -| string.cpp:223:20:223:21 | s2 | string.cpp:223:7:223:8 | ref arg s5 | TAINT | -| string.cpp:223:20:223:21 | s2 | string.cpp:223:10:223:15 | call to insert | TAINT | -| string.cpp:226:7:226:8 | s1 | string.cpp:226:2:226:8 | ... = ... | | -| string.cpp:226:7:226:8 | s1 | string.cpp:227:7:227:8 | s6 | | -| string.cpp:226:7:226:8 | s1 | string.cpp:228:7:228:8 | s6 | | -| string.cpp:227:7:227:8 | ref arg s6 | string.cpp:228:7:228:8 | s6 | | -| string.cpp:227:7:227:8 | s6 | string.cpp:227:10:227:15 | call to insert | TAINT | -| string.cpp:227:24:227:24 | c | string.cpp:227:7:227:8 | ref arg s6 | TAINT | -| string.cpp:227:24:227:24 | c | string.cpp:227:10:227:15 | call to insert | TAINT | -| string.cpp:232:17:232:23 | hello | string.cpp:232:17:232:24 | call to basic_string | TAINT | -| string.cpp:232:17:232:24 | call to basic_string | string.cpp:237:7:237:8 | s1 | | -| string.cpp:232:17:232:24 | call to basic_string | string.cpp:238:24:238:25 | s1 | | -| string.cpp:232:17:232:24 | call to basic_string | string.cpp:242:24:242:25 | s1 | | -| string.cpp:232:17:232:24 | call to basic_string | string.cpp:245:7:245:8 | s1 | | -| string.cpp:232:17:232:24 | call to basic_string | string.cpp:249:7:249:8 | s1 | | -| string.cpp:233:17:233:22 | call to source | string.cpp:233:17:233:25 | call to basic_string | TAINT | -| string.cpp:233:17:233:25 | call to basic_string | string.cpp:241:7:241:8 | s2 | | -| string.cpp:233:17:233:25 | call to basic_string | string.cpp:246:24:246:25 | s2 | | -| string.cpp:234:11:234:25 | call to source | string.cpp:250:28:250:28 | c | | -| string.cpp:237:7:237:8 | s1 | string.cpp:237:2:237:8 | ... = ... | | -| string.cpp:237:7:237:8 | s1 | string.cpp:238:7:238:8 | s3 | | -| string.cpp:237:7:237:8 | s1 | string.cpp:239:7:239:8 | s3 | | -| string.cpp:238:7:238:8 | ref arg s3 | string.cpp:239:7:239:8 | s3 | | -| string.cpp:238:7:238:8 | s3 | string.cpp:238:10:238:16 | call to replace | TAINT | -| string.cpp:238:24:238:25 | s1 | string.cpp:238:7:238:8 | ref arg s3 | TAINT | -| string.cpp:238:24:238:25 | s1 | string.cpp:238:10:238:16 | call to replace | TAINT | -| string.cpp:241:7:241:8 | s2 | string.cpp:241:2:241:8 | ... = ... | | -| string.cpp:241:7:241:8 | s2 | string.cpp:242:7:242:8 | s4 | | -| string.cpp:241:7:241:8 | s2 | string.cpp:243:7:243:8 | s4 | | -| string.cpp:242:7:242:8 | ref arg s4 | string.cpp:243:7:243:8 | s4 | | -| string.cpp:242:7:242:8 | s4 | string.cpp:242:10:242:16 | call to replace | TAINT | -| string.cpp:242:24:242:25 | s1 | string.cpp:242:7:242:8 | ref arg s4 | TAINT | -| string.cpp:242:24:242:25 | s1 | string.cpp:242:10:242:16 | call to replace | TAINT | -| string.cpp:245:7:245:8 | s1 | string.cpp:245:2:245:8 | ... = ... | | -| string.cpp:245:7:245:8 | s1 | string.cpp:246:7:246:8 | s5 | | -| string.cpp:245:7:245:8 | s1 | string.cpp:247:7:247:8 | s5 | | -| string.cpp:246:7:246:8 | ref arg s5 | string.cpp:247:7:247:8 | s5 | | -| string.cpp:246:7:246:8 | s5 | string.cpp:246:10:246:16 | call to replace | TAINT | -| string.cpp:246:24:246:25 | s2 | string.cpp:246:7:246:8 | ref arg s5 | TAINT | -| string.cpp:246:24:246:25 | s2 | string.cpp:246:10:246:16 | call to replace | TAINT | -| string.cpp:249:7:249:8 | s1 | string.cpp:249:2:249:8 | ... = ... | | -| string.cpp:249:7:249:8 | s1 | string.cpp:250:7:250:8 | s6 | | -| string.cpp:249:7:249:8 | s1 | string.cpp:251:7:251:8 | s6 | | -| string.cpp:250:7:250:8 | ref arg s6 | string.cpp:251:7:251:8 | s6 | | -| string.cpp:250:7:250:8 | s6 | string.cpp:250:10:250:16 | call to replace | TAINT | -| string.cpp:250:28:250:28 | c | string.cpp:250:7:250:8 | ref arg s6 | TAINT | -| string.cpp:250:28:250:28 | c | string.cpp:250:10:250:16 | call to replace | TAINT | -| string.cpp:255:17:255:20 | {...} | string.cpp:260:10:260:11 | b1 | | -| string.cpp:255:17:255:20 | {...} | string.cpp:261:7:261:8 | b1 | | -| string.cpp:255:19:255:19 | 0 | string.cpp:255:17:255:20 | {...} | TAINT | -| string.cpp:256:17:256:20 | {...} | string.cpp:263:10:263:11 | b2 | | -| string.cpp:256:17:256:20 | {...} | string.cpp:264:7:264:8 | b2 | | +| string.cpp:175:13:175:18 | call to source | string.cpp:175:3:175:4 | ref arg s9 | TAINT | +| string.cpp:175:13:175:18 | call to source | string.cpp:175:6:175:11 | call to append | TAINT | +| string.cpp:176:3:176:4 | ref arg s9 | string.cpp:177:8:177:9 | s9 | | +| string.cpp:176:3:176:4 | s9 | string.cpp:176:6:176:11 | call to append | TAINT | +| string.cpp:176:13:176:15 | | string.cpp:176:3:176:4 | ref arg s9 | TAINT | +| string.cpp:176:13:176:15 | | string.cpp:176:6:176:11 | call to append | TAINT | +| string.cpp:181:19:181:23 | abc | string.cpp:181:19:181:24 | call to basic_string | TAINT | +| string.cpp:181:19:181:24 | call to basic_string | string.cpp:184:3:184:5 | s10 | | +| string.cpp:181:19:181:24 | call to basic_string | string.cpp:185:8:185:10 | s10 | | +| string.cpp:182:12:182:26 | call to source | string.cpp:184:17:184:17 | c | | +| string.cpp:184:3:184:5 | ref arg s10 | string.cpp:185:8:185:10 | s10 | | +| string.cpp:184:3:184:5 | s10 | string.cpp:184:7:184:12 | call to append | TAINT | +| string.cpp:184:17:184:17 | c | string.cpp:184:3:184:5 | ref arg s10 | TAINT | +| string.cpp:184:17:184:17 | c | string.cpp:184:7:184:12 | call to append | TAINT | +| string.cpp:190:17:190:23 | hello | string.cpp:190:17:190:24 | call to basic_string | TAINT | +| string.cpp:190:17:190:24 | call to basic_string | string.cpp:196:17:196:18 | s1 | | +| string.cpp:190:17:190:24 | call to basic_string | string.cpp:205:17:205:18 | s1 | | +| string.cpp:191:17:191:22 | call to source | string.cpp:191:17:191:25 | call to basic_string | TAINT | +| string.cpp:191:17:191:25 | call to basic_string | string.cpp:199:17:199:18 | s2 | | +| string.cpp:192:11:192:25 | call to source | string.cpp:202:21:202:21 | c | | +| string.cpp:193:14:193:15 | call to basic_string | string.cpp:196:7:196:8 | s3 | | +| string.cpp:193:14:193:15 | call to basic_string | string.cpp:197:7:197:8 | s3 | | +| string.cpp:193:18:193:19 | call to basic_string | string.cpp:199:7:199:8 | s4 | | +| string.cpp:193:18:193:19 | call to basic_string | string.cpp:200:7:200:8 | s4 | | +| string.cpp:193:22:193:23 | call to basic_string | string.cpp:202:7:202:8 | s5 | | +| string.cpp:193:22:193:23 | call to basic_string | string.cpp:203:7:203:8 | s5 | | +| string.cpp:194:17:194:22 | call to source | string.cpp:194:17:194:25 | call to basic_string | TAINT | +| string.cpp:194:17:194:25 | call to basic_string | string.cpp:205:7:205:8 | s6 | | +| string.cpp:194:17:194:25 | call to basic_string | string.cpp:206:7:206:8 | s6 | | +| string.cpp:196:7:196:8 | ref arg s3 | string.cpp:197:7:197:8 | s3 | | +| string.cpp:196:17:196:18 | s1 | string.cpp:196:7:196:8 | ref arg s3 | TAINT | +| string.cpp:196:17:196:18 | s1 | string.cpp:196:10:196:15 | call to assign | TAINT | +| string.cpp:199:7:199:8 | ref arg s4 | string.cpp:200:7:200:8 | s4 | | +| string.cpp:199:17:199:18 | s2 | string.cpp:199:7:199:8 | ref arg s4 | TAINT | +| string.cpp:199:17:199:18 | s2 | string.cpp:199:10:199:15 | call to assign | TAINT | +| string.cpp:202:7:202:8 | ref arg s5 | string.cpp:203:7:203:8 | s5 | | +| string.cpp:202:21:202:21 | c | string.cpp:202:7:202:8 | ref arg s5 | TAINT | +| string.cpp:202:21:202:21 | c | string.cpp:202:10:202:15 | call to assign | TAINT | +| string.cpp:205:7:205:8 | ref arg s6 | string.cpp:206:7:206:8 | s6 | | +| string.cpp:205:17:205:18 | s1 | string.cpp:205:7:205:8 | ref arg s6 | TAINT | +| string.cpp:205:17:205:18 | s1 | string.cpp:205:10:205:15 | call to assign | TAINT | +| string.cpp:210:17:210:23 | hello | string.cpp:210:17:210:24 | call to basic_string | TAINT | +| string.cpp:210:17:210:24 | call to basic_string | string.cpp:215:7:215:8 | s1 | | +| string.cpp:210:17:210:24 | call to basic_string | string.cpp:216:20:216:21 | s1 | | +| string.cpp:210:17:210:24 | call to basic_string | string.cpp:220:20:220:21 | s1 | | +| string.cpp:210:17:210:24 | call to basic_string | string.cpp:223:7:223:8 | s1 | | +| string.cpp:210:17:210:24 | call to basic_string | string.cpp:227:7:227:8 | s1 | | +| string.cpp:211:17:211:22 | call to source | string.cpp:211:17:211:25 | call to basic_string | TAINT | +| string.cpp:211:17:211:25 | call to basic_string | string.cpp:219:7:219:8 | s2 | | +| string.cpp:211:17:211:25 | call to basic_string | string.cpp:224:20:224:21 | s2 | | +| string.cpp:212:11:212:25 | call to source | string.cpp:228:24:228:24 | c | | +| string.cpp:215:7:215:8 | s1 | string.cpp:215:2:215:8 | ... = ... | | +| string.cpp:215:7:215:8 | s1 | string.cpp:216:7:216:8 | s3 | | +| string.cpp:215:7:215:8 | s1 | string.cpp:217:7:217:8 | s3 | | +| string.cpp:216:7:216:8 | ref arg s3 | string.cpp:217:7:217:8 | s3 | | +| string.cpp:216:7:216:8 | s3 | string.cpp:216:10:216:15 | call to insert | TAINT | +| string.cpp:216:20:216:21 | s1 | string.cpp:216:7:216:8 | ref arg s3 | TAINT | +| string.cpp:216:20:216:21 | s1 | string.cpp:216:10:216:15 | call to insert | TAINT | +| string.cpp:219:7:219:8 | s2 | string.cpp:219:2:219:8 | ... = ... | | +| string.cpp:219:7:219:8 | s2 | string.cpp:220:7:220:8 | s4 | | +| string.cpp:219:7:219:8 | s2 | string.cpp:221:7:221:8 | s4 | | +| string.cpp:220:7:220:8 | ref arg s4 | string.cpp:221:7:221:8 | s4 | | +| string.cpp:220:7:220:8 | s4 | string.cpp:220:10:220:15 | call to insert | TAINT | +| string.cpp:220:20:220:21 | s1 | string.cpp:220:7:220:8 | ref arg s4 | TAINT | +| string.cpp:220:20:220:21 | s1 | string.cpp:220:10:220:15 | call to insert | TAINT | +| string.cpp:223:7:223:8 | s1 | string.cpp:223:2:223:8 | ... = ... | | +| string.cpp:223:7:223:8 | s1 | string.cpp:224:7:224:8 | s5 | | +| string.cpp:223:7:223:8 | s1 | string.cpp:225:7:225:8 | s5 | | +| string.cpp:224:7:224:8 | ref arg s5 | string.cpp:225:7:225:8 | s5 | | +| string.cpp:224:7:224:8 | s5 | string.cpp:224:10:224:15 | call to insert | TAINT | +| string.cpp:224:20:224:21 | s2 | string.cpp:224:7:224:8 | ref arg s5 | TAINT | +| string.cpp:224:20:224:21 | s2 | string.cpp:224:10:224:15 | call to insert | TAINT | +| string.cpp:227:7:227:8 | s1 | string.cpp:227:2:227:8 | ... = ... | | +| string.cpp:227:7:227:8 | s1 | string.cpp:228:7:228:8 | s6 | | +| string.cpp:227:7:227:8 | s1 | string.cpp:229:7:229:8 | s6 | | +| string.cpp:228:7:228:8 | ref arg s6 | string.cpp:229:7:229:8 | s6 | | +| string.cpp:228:7:228:8 | s6 | string.cpp:228:10:228:15 | call to insert | TAINT | +| string.cpp:228:24:228:24 | c | string.cpp:228:7:228:8 | ref arg s6 | TAINT | +| string.cpp:228:24:228:24 | c | string.cpp:228:10:228:15 | call to insert | TAINT | +| string.cpp:233:17:233:23 | hello | string.cpp:233:17:233:24 | call to basic_string | TAINT | +| string.cpp:233:17:233:24 | call to basic_string | string.cpp:238:7:238:8 | s1 | | +| string.cpp:233:17:233:24 | call to basic_string | string.cpp:239:24:239:25 | s1 | | +| string.cpp:233:17:233:24 | call to basic_string | string.cpp:243:24:243:25 | s1 | | +| string.cpp:233:17:233:24 | call to basic_string | string.cpp:246:7:246:8 | s1 | | +| string.cpp:233:17:233:24 | call to basic_string | string.cpp:250:7:250:8 | s1 | | +| string.cpp:234:17:234:22 | call to source | string.cpp:234:17:234:25 | call to basic_string | TAINT | +| string.cpp:234:17:234:25 | call to basic_string | string.cpp:242:7:242:8 | s2 | | +| string.cpp:234:17:234:25 | call to basic_string | string.cpp:247:24:247:25 | s2 | | +| string.cpp:235:11:235:25 | call to source | string.cpp:251:28:251:28 | c | | +| string.cpp:238:7:238:8 | s1 | string.cpp:238:2:238:8 | ... = ... | | +| string.cpp:238:7:238:8 | s1 | string.cpp:239:7:239:8 | s3 | | +| string.cpp:238:7:238:8 | s1 | string.cpp:240:7:240:8 | s3 | | +| string.cpp:239:7:239:8 | ref arg s3 | string.cpp:240:7:240:8 | s3 | | +| string.cpp:239:7:239:8 | s3 | string.cpp:239:10:239:16 | call to replace | TAINT | +| string.cpp:239:24:239:25 | s1 | string.cpp:239:7:239:8 | ref arg s3 | TAINT | +| string.cpp:239:24:239:25 | s1 | string.cpp:239:10:239:16 | call to replace | TAINT | +| string.cpp:242:7:242:8 | s2 | string.cpp:242:2:242:8 | ... = ... | | +| string.cpp:242:7:242:8 | s2 | string.cpp:243:7:243:8 | s4 | | +| string.cpp:242:7:242:8 | s2 | string.cpp:244:7:244:8 | s4 | | +| string.cpp:243:7:243:8 | ref arg s4 | string.cpp:244:7:244:8 | s4 | | +| string.cpp:243:7:243:8 | s4 | string.cpp:243:10:243:16 | call to replace | TAINT | +| string.cpp:243:24:243:25 | s1 | string.cpp:243:7:243:8 | ref arg s4 | TAINT | +| string.cpp:243:24:243:25 | s1 | string.cpp:243:10:243:16 | call to replace | TAINT | +| string.cpp:246:7:246:8 | s1 | string.cpp:246:2:246:8 | ... = ... | | +| string.cpp:246:7:246:8 | s1 | string.cpp:247:7:247:8 | s5 | | +| string.cpp:246:7:246:8 | s1 | string.cpp:248:7:248:8 | s5 | | +| string.cpp:247:7:247:8 | ref arg s5 | string.cpp:248:7:248:8 | s5 | | +| string.cpp:247:7:247:8 | s5 | string.cpp:247:10:247:16 | call to replace | TAINT | +| string.cpp:247:24:247:25 | s2 | string.cpp:247:7:247:8 | ref arg s5 | TAINT | +| string.cpp:247:24:247:25 | s2 | string.cpp:247:10:247:16 | call to replace | TAINT | +| string.cpp:250:7:250:8 | s1 | string.cpp:250:2:250:8 | ... = ... | | +| string.cpp:250:7:250:8 | s1 | string.cpp:251:7:251:8 | s6 | | +| string.cpp:250:7:250:8 | s1 | string.cpp:252:7:252:8 | s6 | | +| string.cpp:251:7:251:8 | ref arg s6 | string.cpp:252:7:252:8 | s6 | | +| string.cpp:251:7:251:8 | s6 | string.cpp:251:10:251:16 | call to replace | TAINT | +| string.cpp:251:28:251:28 | c | string.cpp:251:7:251:8 | ref arg s6 | TAINT | +| string.cpp:251:28:251:28 | c | string.cpp:251:10:251:16 | call to replace | TAINT | +| string.cpp:256:17:256:20 | {...} | string.cpp:261:10:261:11 | b1 | | +| string.cpp:256:17:256:20 | {...} | string.cpp:262:7:262:8 | b1 | | | string.cpp:256:19:256:19 | 0 | string.cpp:256:17:256:20 | {...} | TAINT | -| string.cpp:257:17:257:23 | hello | string.cpp:257:17:257:24 | call to basic_string | TAINT | -| string.cpp:257:17:257:24 | call to basic_string | string.cpp:260:2:260:3 | s1 | | -| string.cpp:257:17:257:24 | call to basic_string | string.cpp:260:14:260:15 | s1 | | -| string.cpp:257:17:257:24 | call to basic_string | string.cpp:263:14:263:15 | s1 | | -| string.cpp:258:17:258:22 | call to source | string.cpp:258:17:258:25 | call to basic_string | TAINT | -| string.cpp:258:17:258:25 | call to basic_string | string.cpp:263:2:263:3 | s2 | | -| string.cpp:260:2:260:3 | s1 | string.cpp:260:10:260:11 | ref arg b1 | TAINT | -| string.cpp:260:10:260:11 | ref arg b1 | string.cpp:261:7:261:8 | b1 | | -| string.cpp:263:2:263:3 | s2 | string.cpp:263:10:263:11 | ref arg b2 | TAINT | -| string.cpp:263:10:263:11 | ref arg b2 | string.cpp:264:7:264:8 | b2 | | -| string.cpp:268:17:268:23 | hello | string.cpp:268:17:268:24 | call to basic_string | TAINT | -| string.cpp:268:17:268:24 | call to basic_string | string.cpp:273:7:273:8 | s1 | | -| string.cpp:268:17:268:24 | call to basic_string | string.cpp:278:2:278:3 | s1 | | -| string.cpp:268:17:268:24 | call to basic_string | string.cpp:281:7:281:8 | s1 | | -| string.cpp:269:17:269:22 | call to source | string.cpp:269:17:269:25 | call to basic_string | TAINT | -| string.cpp:269:17:269:25 | call to basic_string | string.cpp:274:7:274:8 | s2 | | -| string.cpp:269:17:269:25 | call to basic_string | string.cpp:278:10:278:11 | s2 | | -| string.cpp:269:17:269:25 | call to basic_string | string.cpp:282:7:282:8 | s2 | | -| string.cpp:270:17:270:23 | world | string.cpp:270:17:270:24 | call to basic_string | TAINT | -| string.cpp:270:17:270:24 | call to basic_string | string.cpp:275:7:275:8 | s3 | | -| string.cpp:270:17:270:24 | call to basic_string | string.cpp:279:10:279:11 | s3 | | -| string.cpp:270:17:270:24 | call to basic_string | string.cpp:283:7:283:8 | s3 | | -| string.cpp:271:17:271:22 | call to source | string.cpp:271:17:271:25 | call to basic_string | TAINT | -| string.cpp:271:17:271:25 | call to basic_string | string.cpp:276:7:276:8 | s4 | | -| string.cpp:271:17:271:25 | call to basic_string | string.cpp:279:2:279:3 | s4 | | -| string.cpp:271:17:271:25 | call to basic_string | string.cpp:284:7:284:8 | s4 | | -| string.cpp:278:2:278:3 | ref arg s1 | string.cpp:281:7:281:8 | s1 | | -| string.cpp:278:2:278:3 | s1 | string.cpp:278:10:278:11 | ref arg s2 | TAINT | -| string.cpp:278:10:278:11 | ref arg s2 | string.cpp:282:7:282:8 | s2 | | -| string.cpp:278:10:278:11 | s2 | string.cpp:278:2:278:3 | ref arg s1 | TAINT | -| string.cpp:279:2:279:3 | ref arg s4 | string.cpp:284:7:284:8 | s4 | | -| string.cpp:279:2:279:3 | s4 | string.cpp:279:10:279:11 | ref arg s3 | TAINT | -| string.cpp:279:10:279:11 | ref arg s3 | string.cpp:283:7:283:8 | s3 | | -| string.cpp:279:10:279:11 | s3 | string.cpp:279:2:279:3 | ref arg s4 | TAINT | -| string.cpp:288:17:288:22 | call to source | string.cpp:288:17:288:25 | call to basic_string | TAINT | -| string.cpp:288:17:288:25 | call to basic_string | string.cpp:292:7:292:8 | s1 | | -| string.cpp:288:17:288:25 | call to basic_string | string.cpp:296:2:296:3 | s1 | | -| string.cpp:288:17:288:25 | call to basic_string | string.cpp:300:7:300:8 | s1 | | +| string.cpp:257:17:257:20 | {...} | string.cpp:264:10:264:11 | b2 | | +| string.cpp:257:17:257:20 | {...} | string.cpp:265:7:265:8 | b2 | | +| string.cpp:257:19:257:19 | 0 | string.cpp:257:17:257:20 | {...} | TAINT | +| string.cpp:258:17:258:23 | hello | string.cpp:258:17:258:24 | call to basic_string | TAINT | +| string.cpp:258:17:258:24 | call to basic_string | string.cpp:261:2:261:3 | s1 | | +| string.cpp:258:17:258:24 | call to basic_string | string.cpp:261:14:261:15 | s1 | | +| string.cpp:258:17:258:24 | call to basic_string | string.cpp:264:14:264:15 | s1 | | +| string.cpp:259:17:259:22 | call to source | string.cpp:259:17:259:25 | call to basic_string | TAINT | +| string.cpp:259:17:259:25 | call to basic_string | string.cpp:264:2:264:3 | s2 | | +| string.cpp:261:2:261:3 | s1 | string.cpp:261:10:261:11 | ref arg b1 | TAINT | +| string.cpp:261:10:261:11 | ref arg b1 | string.cpp:262:7:262:8 | b1 | | +| string.cpp:264:2:264:3 | s2 | string.cpp:264:10:264:11 | ref arg b2 | TAINT | +| string.cpp:264:10:264:11 | ref arg b2 | string.cpp:265:7:265:8 | b2 | | +| string.cpp:269:17:269:23 | hello | string.cpp:269:17:269:24 | call to basic_string | TAINT | +| string.cpp:269:17:269:24 | call to basic_string | string.cpp:274:7:274:8 | s1 | | +| string.cpp:269:17:269:24 | call to basic_string | string.cpp:279:2:279:3 | s1 | | +| string.cpp:269:17:269:24 | call to basic_string | string.cpp:282:7:282:8 | s1 | | +| string.cpp:270:17:270:22 | call to source | string.cpp:270:17:270:25 | call to basic_string | TAINT | +| string.cpp:270:17:270:25 | call to basic_string | string.cpp:275:7:275:8 | s2 | | +| string.cpp:270:17:270:25 | call to basic_string | string.cpp:279:10:279:11 | s2 | | +| string.cpp:270:17:270:25 | call to basic_string | string.cpp:283:7:283:8 | s2 | | +| string.cpp:271:17:271:23 | world | string.cpp:271:17:271:24 | call to basic_string | TAINT | +| string.cpp:271:17:271:24 | call to basic_string | string.cpp:276:7:276:8 | s3 | | +| string.cpp:271:17:271:24 | call to basic_string | string.cpp:280:10:280:11 | s3 | | +| string.cpp:271:17:271:24 | call to basic_string | string.cpp:284:7:284:8 | s3 | | +| string.cpp:272:17:272:22 | call to source | string.cpp:272:17:272:25 | call to basic_string | TAINT | +| string.cpp:272:17:272:25 | call to basic_string | string.cpp:277:7:277:8 | s4 | | +| string.cpp:272:17:272:25 | call to basic_string | string.cpp:280:2:280:3 | s4 | | +| string.cpp:272:17:272:25 | call to basic_string | string.cpp:285:7:285:8 | s4 | | +| string.cpp:279:2:279:3 | ref arg s1 | string.cpp:282:7:282:8 | s1 | | +| string.cpp:279:2:279:3 | s1 | string.cpp:279:10:279:11 | ref arg s2 | TAINT | +| string.cpp:279:10:279:11 | ref arg s2 | string.cpp:283:7:283:8 | s2 | | +| string.cpp:279:10:279:11 | s2 | string.cpp:279:2:279:3 | ref arg s1 | TAINT | +| string.cpp:280:2:280:3 | ref arg s4 | string.cpp:285:7:285:8 | s4 | | +| string.cpp:280:2:280:3 | s4 | string.cpp:280:10:280:11 | ref arg s3 | TAINT | +| string.cpp:280:10:280:11 | ref arg s3 | string.cpp:284:7:284:8 | s3 | | +| string.cpp:280:10:280:11 | s3 | string.cpp:280:2:280:3 | ref arg s4 | TAINT | | string.cpp:289:17:289:22 | call to source | string.cpp:289:17:289:25 | call to basic_string | TAINT | -| string.cpp:289:17:289:25 | call to basic_string | string.cpp:293:7:293:8 | s2 | | +| string.cpp:289:17:289:25 | call to basic_string | string.cpp:293:7:293:8 | s1 | | +| string.cpp:289:17:289:25 | call to basic_string | string.cpp:297:2:297:3 | s1 | | +| string.cpp:289:17:289:25 | call to basic_string | string.cpp:301:7:301:8 | s1 | | | string.cpp:290:17:290:22 | call to source | string.cpp:290:17:290:25 | call to basic_string | TAINT | -| string.cpp:290:17:290:25 | call to basic_string | string.cpp:294:7:294:8 | s3 | | -| string.cpp:290:17:290:25 | call to basic_string | string.cpp:298:7:298:8 | s3 | | -| string.cpp:296:2:296:3 | ref arg s1 | string.cpp:300:7:300:8 | s1 | | -| string.cpp:297:7:297:8 | | string.cpp:297:7:297:8 | call to basic_string | TAINT | -| string.cpp:297:7:297:8 | call to basic_string | string.cpp:297:2:297:8 | ... = ... | | -| string.cpp:297:7:297:8 | call to basic_string | string.cpp:301:7:301:8 | s2 | | -| string.cpp:298:7:298:8 | s3 | string.cpp:298:2:298:8 | ... = ... | | -| string.cpp:298:7:298:8 | s3 | string.cpp:302:7:302:8 | s3 | | -| string.cpp:307:16:307:20 | 123 | string.cpp:307:16:307:21 | call to basic_string | TAINT | -| string.cpp:307:16:307:21 | call to basic_string | string.cpp:310:7:310:7 | a | | -| string.cpp:307:16:307:21 | call to basic_string | string.cpp:312:7:312:7 | a | | -| string.cpp:308:16:308:21 | call to source | string.cpp:308:16:308:24 | call to basic_string | TAINT | -| string.cpp:308:16:308:24 | call to basic_string | string.cpp:311:7:311:7 | b | | -| string.cpp:308:16:308:24 | call to basic_string | string.cpp:313:7:313:7 | b | | -| string.cpp:310:7:310:7 | a | string.cpp:310:9:310:12 | call to data | TAINT | -| string.cpp:310:7:310:7 | ref arg a | string.cpp:312:7:312:7 | a | | -| string.cpp:311:7:311:7 | b | string.cpp:311:9:311:12 | call to data | TAINT | -| string.cpp:311:7:311:7 | ref arg b | string.cpp:313:7:313:7 | b | | -| string.cpp:318:16:318:20 | 123 | string.cpp:318:16:318:21 | call to basic_string | TAINT | -| string.cpp:318:16:318:21 | call to basic_string | string.cpp:321:7:321:7 | a | | -| string.cpp:318:16:318:21 | call to basic_string | string.cpp:321:19:321:19 | a | | -| string.cpp:319:16:319:21 | call to source | string.cpp:319:16:319:24 | call to basic_string | TAINT | -| string.cpp:319:16:319:24 | call to basic_string | string.cpp:322:7:322:7 | b | | -| string.cpp:319:16:319:24 | call to basic_string | string.cpp:322:19:322:19 | b | | -| string.cpp:321:7:321:7 | a | string.cpp:321:9:321:14 | call to substr | TAINT | -| string.cpp:322:7:322:7 | b | string.cpp:322:9:322:14 | call to substr | TAINT | -| string.cpp:327:16:327:20 | 123 | string.cpp:327:16:327:21 | call to basic_string | TAINT | -| string.cpp:327:16:327:21 | call to basic_string | string.cpp:331:7:331:7 | a | | -| string.cpp:327:16:327:21 | call to basic_string | string.cpp:335:2:335:2 | a | | -| string.cpp:327:16:327:21 | call to basic_string | string.cpp:337:9:337:9 | a | | -| string.cpp:327:16:327:21 | call to basic_string | string.cpp:339:7:339:7 | a | | +| string.cpp:290:17:290:25 | call to basic_string | string.cpp:294:7:294:8 | s2 | | +| string.cpp:291:17:291:22 | call to source | string.cpp:291:17:291:25 | call to basic_string | TAINT | +| string.cpp:291:17:291:25 | call to basic_string | string.cpp:295:7:295:8 | s3 | | +| string.cpp:291:17:291:25 | call to basic_string | string.cpp:299:7:299:8 | s3 | | +| string.cpp:297:2:297:3 | ref arg s1 | string.cpp:301:7:301:8 | s1 | | +| string.cpp:298:7:298:8 | | string.cpp:298:7:298:8 | call to basic_string | TAINT | +| string.cpp:298:7:298:8 | call to basic_string | string.cpp:298:2:298:8 | ... = ... | | +| string.cpp:298:7:298:8 | call to basic_string | string.cpp:302:7:302:8 | s2 | | +| string.cpp:299:7:299:8 | s3 | string.cpp:299:2:299:8 | ... = ... | | +| string.cpp:299:7:299:8 | s3 | string.cpp:303:7:303:8 | s3 | | +| string.cpp:308:16:308:20 | 123 | string.cpp:308:16:308:21 | call to basic_string | TAINT | +| string.cpp:308:16:308:21 | call to basic_string | string.cpp:311:7:311:7 | a | | +| string.cpp:308:16:308:21 | call to basic_string | string.cpp:313:7:313:7 | a | | +| string.cpp:309:16:309:21 | call to source | string.cpp:309:16:309:24 | call to basic_string | TAINT | +| string.cpp:309:16:309:24 | call to basic_string | string.cpp:312:7:312:7 | b | | +| string.cpp:309:16:309:24 | call to basic_string | string.cpp:314:7:314:7 | b | | +| string.cpp:311:7:311:7 | a | string.cpp:311:9:311:12 | call to data | TAINT | +| string.cpp:311:7:311:7 | ref arg a | string.cpp:313:7:313:7 | a | | +| string.cpp:312:7:312:7 | b | string.cpp:312:9:312:12 | call to data | TAINT | +| string.cpp:312:7:312:7 | ref arg b | string.cpp:314:7:314:7 | b | | +| string.cpp:319:16:319:20 | 123 | string.cpp:319:16:319:21 | call to basic_string | TAINT | +| string.cpp:319:16:319:21 | call to basic_string | string.cpp:322:7:322:7 | a | | +| string.cpp:319:16:319:21 | call to basic_string | string.cpp:322:19:322:19 | a | | +| string.cpp:320:16:320:21 | call to source | string.cpp:320:16:320:24 | call to basic_string | TAINT | +| string.cpp:320:16:320:24 | call to basic_string | string.cpp:323:7:323:7 | b | | +| string.cpp:320:16:320:24 | call to basic_string | string.cpp:323:19:323:19 | b | | +| string.cpp:322:7:322:7 | a | string.cpp:322:9:322:14 | call to substr | TAINT | +| string.cpp:323:7:323:7 | b | string.cpp:323:9:323:14 | call to substr | TAINT | | string.cpp:328:16:328:20 | 123 | string.cpp:328:16:328:21 | call to basic_string | TAINT | -| string.cpp:328:16:328:21 | call to basic_string | string.cpp:332:7:332:7 | b | | -| string.cpp:328:16:328:21 | call to basic_string | string.cpp:336:2:336:2 | b | | -| string.cpp:328:16:328:21 | call to basic_string | string.cpp:340:7:340:7 | b | | +| string.cpp:328:16:328:21 | call to basic_string | string.cpp:332:7:332:7 | a | | +| string.cpp:328:16:328:21 | call to basic_string | string.cpp:336:2:336:2 | a | | +| string.cpp:328:16:328:21 | call to basic_string | string.cpp:338:9:338:9 | a | | +| string.cpp:328:16:328:21 | call to basic_string | string.cpp:340:7:340:7 | a | | | string.cpp:329:16:329:20 | 123 | string.cpp:329:16:329:21 | call to basic_string | TAINT | -| string.cpp:329:16:329:21 | call to basic_string | string.cpp:333:7:333:7 | c | | -| string.cpp:329:16:329:21 | call to basic_string | string.cpp:337:2:337:2 | c | | -| string.cpp:329:16:329:21 | call to basic_string | string.cpp:341:7:341:7 | c | | -| string.cpp:335:2:335:2 | a | string.cpp:335:3:335:3 | call to operator[] | TAINT | -| string.cpp:335:2:335:2 | ref arg a | string.cpp:337:9:337:9 | a | | -| string.cpp:335:2:335:2 | ref arg a | string.cpp:339:7:339:7 | a | | -| string.cpp:335:2:335:25 | ... = ... | string.cpp:335:3:335:3 | call to operator[] [post update] | | -| string.cpp:335:3:335:3 | call to operator[] [post update] | string.cpp:335:2:335:2 | ref arg a | TAINT | -| string.cpp:335:9:335:23 | call to source | string.cpp:335:2:335:25 | ... = ... | | -| string.cpp:336:2:336:2 | b | string.cpp:336:4:336:5 | call to at | TAINT | -| string.cpp:336:2:336:2 | ref arg b | string.cpp:340:7:340:7 | b | | -| string.cpp:336:2:336:28 | ... = ... | string.cpp:336:4:336:5 | call to at [post update] | | -| string.cpp:336:4:336:5 | call to at [post update] | string.cpp:336:2:336:2 | ref arg b | TAINT | -| string.cpp:336:12:336:26 | call to source | string.cpp:336:2:336:28 | ... = ... | | -| string.cpp:337:2:337:2 | c | string.cpp:337:3:337:3 | call to operator[] | TAINT | -| string.cpp:337:2:337:2 | ref arg c | string.cpp:341:7:341:7 | c | | -| string.cpp:337:2:337:12 | ... = ... | string.cpp:337:3:337:3 | call to operator[] [post update] | | -| string.cpp:337:3:337:3 | call to operator[] [post update] | string.cpp:337:2:337:2 | ref arg c | TAINT | -| string.cpp:337:9:337:9 | a | string.cpp:337:10:337:10 | call to operator[] | TAINT | -| string.cpp:337:9:337:9 | ref arg a | string.cpp:339:7:339:7 | a | | -| string.cpp:337:10:337:10 | call to operator[] | string.cpp:337:2:337:12 | ... = ... | | -| string.cpp:346:18:346:22 | 123 | string.cpp:346:18:346:23 | call to basic_string | TAINT | -| string.cpp:346:18:346:23 | call to basic_string | string.cpp:348:2:348:4 | str | | -| string.cpp:346:18:346:23 | call to basic_string | string.cpp:349:7:349:9 | str | | -| string.cpp:346:18:346:23 | call to basic_string | string.cpp:350:7:350:9 | str | | -| string.cpp:348:2:348:4 | ref arg str | string.cpp:349:7:349:9 | str | | -| string.cpp:348:2:348:4 | ref arg str | string.cpp:350:7:350:9 | str | | -| string.cpp:348:2:348:4 | str | string.cpp:348:6:348:9 | call to data | TAINT | -| string.cpp:348:2:348:14 | access to array [post update] | string.cpp:348:6:348:9 | call to data [inner post update] | | -| string.cpp:348:2:348:34 | ... = ... | string.cpp:348:2:348:14 | access to array [post update] | | -| string.cpp:348:6:348:9 | call to data | string.cpp:348:2:348:14 | access to array | TAINT | -| string.cpp:348:6:348:9 | call to data [inner post update] | string.cpp:348:2:348:4 | ref arg str | TAINT | -| string.cpp:348:13:348:13 | 1 | string.cpp:348:2:348:14 | access to array | TAINT | -| string.cpp:348:18:348:32 | call to source | string.cpp:348:2:348:34 | ... = ... | | -| string.cpp:350:7:350:9 | str | string.cpp:350:11:350:14 | call to data | TAINT | -| string.cpp:355:18:355:24 | hello | string.cpp:355:18:355:25 | call to basic_string | TAINT | -| string.cpp:355:18:355:25 | call to basic_string | string.cpp:360:8:360:9 | s1 | | -| string.cpp:355:18:355:25 | call to basic_string | string.cpp:361:8:361:9 | s1 | | -| string.cpp:355:18:355:25 | call to basic_string | string.cpp:362:8:362:9 | s1 | | -| string.cpp:356:18:356:23 | call to source | string.cpp:356:18:356:26 | call to basic_string | TAINT | -| string.cpp:356:18:356:26 | call to basic_string | string.cpp:361:18:361:19 | s2 | | -| string.cpp:356:18:356:26 | call to basic_string | string.cpp:361:30:361:31 | s2 | | +| string.cpp:329:16:329:21 | call to basic_string | string.cpp:333:7:333:7 | b | | +| string.cpp:329:16:329:21 | call to basic_string | string.cpp:337:2:337:2 | b | | +| string.cpp:329:16:329:21 | call to basic_string | string.cpp:341:7:341:7 | b | | +| string.cpp:330:16:330:20 | 123 | string.cpp:330:16:330:21 | call to basic_string | TAINT | +| string.cpp:330:16:330:21 | call to basic_string | string.cpp:334:7:334:7 | c | | +| string.cpp:330:16:330:21 | call to basic_string | string.cpp:338:2:338:2 | c | | +| string.cpp:330:16:330:21 | call to basic_string | string.cpp:342:7:342:7 | c | | +| string.cpp:336:2:336:2 | a | string.cpp:336:3:336:3 | call to operator[] | TAINT | +| string.cpp:336:2:336:2 | ref arg a | string.cpp:338:9:338:9 | a | | +| string.cpp:336:2:336:2 | ref arg a | string.cpp:340:7:340:7 | a | | +| string.cpp:336:2:336:25 | ... = ... | string.cpp:336:3:336:3 | call to operator[] [post update] | | +| string.cpp:336:3:336:3 | call to operator[] [post update] | string.cpp:336:2:336:2 | ref arg a | TAINT | +| string.cpp:336:9:336:23 | call to source | string.cpp:336:2:336:25 | ... = ... | | +| string.cpp:337:2:337:2 | b | string.cpp:337:4:337:5 | call to at | TAINT | +| string.cpp:337:2:337:2 | ref arg b | string.cpp:341:7:341:7 | b | | +| string.cpp:337:2:337:28 | ... = ... | string.cpp:337:4:337:5 | call to at [post update] | | +| string.cpp:337:4:337:5 | call to at [post update] | string.cpp:337:2:337:2 | ref arg b | TAINT | +| string.cpp:337:12:337:26 | call to source | string.cpp:337:2:337:28 | ... = ... | | +| string.cpp:338:2:338:2 | c | string.cpp:338:3:338:3 | call to operator[] | TAINT | +| string.cpp:338:2:338:2 | ref arg c | string.cpp:342:7:342:7 | c | | +| string.cpp:338:2:338:12 | ... = ... | string.cpp:338:3:338:3 | call to operator[] [post update] | | +| string.cpp:338:3:338:3 | call to operator[] [post update] | string.cpp:338:2:338:2 | ref arg c | TAINT | +| string.cpp:338:9:338:9 | a | string.cpp:338:10:338:10 | call to operator[] | TAINT | +| string.cpp:338:9:338:9 | ref arg a | string.cpp:340:7:340:7 | a | | +| string.cpp:338:10:338:10 | call to operator[] | string.cpp:338:2:338:12 | ... = ... | | +| string.cpp:347:18:347:22 | 123 | string.cpp:347:18:347:23 | call to basic_string | TAINT | +| string.cpp:347:18:347:23 | call to basic_string | string.cpp:349:2:349:4 | str | | +| string.cpp:347:18:347:23 | call to basic_string | string.cpp:350:7:350:9 | str | | +| string.cpp:347:18:347:23 | call to basic_string | string.cpp:351:7:351:9 | str | | +| string.cpp:349:2:349:4 | ref arg str | string.cpp:350:7:350:9 | str | | +| string.cpp:349:2:349:4 | ref arg str | string.cpp:351:7:351:9 | str | | +| string.cpp:349:2:349:4 | str | string.cpp:349:6:349:9 | call to data | TAINT | +| string.cpp:349:2:349:14 | access to array [post update] | string.cpp:349:6:349:9 | call to data [inner post update] | | +| string.cpp:349:2:349:34 | ... = ... | string.cpp:349:2:349:14 | access to array [post update] | | +| string.cpp:349:6:349:9 | call to data | string.cpp:349:2:349:14 | access to array | TAINT | +| string.cpp:349:6:349:9 | call to data [inner post update] | string.cpp:349:2:349:4 | ref arg str | TAINT | +| string.cpp:349:13:349:13 | 1 | string.cpp:349:2:349:14 | access to array | TAINT | +| string.cpp:349:18:349:32 | call to source | string.cpp:349:2:349:34 | ... = ... | | +| string.cpp:351:7:351:9 | str | string.cpp:351:11:351:14 | call to data | TAINT | | string.cpp:357:18:357:24 | hello | string.cpp:357:18:357:25 | call to basic_string | TAINT | -| string.cpp:357:18:357:25 | call to basic_string | string.cpp:364:8:364:9 | s3 | | -| string.cpp:357:18:357:25 | call to basic_string | string.cpp:365:8:365:9 | s3 | | -| string.cpp:357:18:357:25 | call to basic_string | string.cpp:366:8:366:9 | s3 | | -| string.cpp:358:18:358:24 | world | string.cpp:358:18:358:25 | call to basic_string | TAINT | -| string.cpp:358:18:358:25 | call to basic_string | string.cpp:365:18:365:19 | s4 | | -| string.cpp:358:18:358:25 | call to basic_string | string.cpp:365:30:365:31 | s4 | | -| string.cpp:361:8:361:9 | ref arg s1 | string.cpp:362:8:362:9 | s1 | | -| string.cpp:361:8:361:9 | s1 | string.cpp:361:11:361:16 | call to append | TAINT | -| string.cpp:361:18:361:19 | ref arg s2 | string.cpp:361:30:361:31 | s2 | | -| string.cpp:361:18:361:19 | s2 | string.cpp:361:21:361:25 | call to begin | TAINT | -| string.cpp:361:21:361:25 | call to begin | string.cpp:361:8:361:9 | ref arg s1 | TAINT | -| string.cpp:361:21:361:25 | call to begin | string.cpp:361:11:361:16 | call to append | TAINT | -| string.cpp:361:30:361:31 | s2 | string.cpp:361:33:361:35 | call to end | TAINT | -| string.cpp:361:33:361:35 | call to end | string.cpp:361:8:361:9 | ref arg s1 | TAINT | -| string.cpp:361:33:361:35 | call to end | string.cpp:361:11:361:16 | call to append | TAINT | -| string.cpp:365:8:365:9 | ref arg s3 | string.cpp:366:8:366:9 | s3 | | -| string.cpp:365:8:365:9 | s3 | string.cpp:365:11:365:16 | call to append | TAINT | -| string.cpp:365:18:365:19 | ref arg s4 | string.cpp:365:30:365:31 | s4 | | -| string.cpp:365:18:365:19 | s4 | string.cpp:365:21:365:25 | call to begin | TAINT | -| string.cpp:365:21:365:25 | call to begin | string.cpp:365:8:365:9 | ref arg s3 | TAINT | -| string.cpp:365:21:365:25 | call to begin | string.cpp:365:11:365:16 | call to append | TAINT | -| string.cpp:365:30:365:31 | s4 | string.cpp:365:33:365:35 | call to end | TAINT | -| string.cpp:365:33:365:35 | call to end | string.cpp:365:8:365:9 | ref arg s3 | TAINT | -| string.cpp:365:33:365:35 | call to end | string.cpp:365:11:365:16 | call to append | TAINT | -| string.cpp:371:18:371:24 | hello | string.cpp:371:18:371:25 | call to basic_string | TAINT | -| string.cpp:371:18:371:25 | call to basic_string | string.cpp:374:28:374:29 | s1 | | -| string.cpp:372:18:372:23 | call to source | string.cpp:372:18:372:26 | call to basic_string | TAINT | -| string.cpp:372:18:372:26 | call to basic_string | string.cpp:378:28:378:29 | s2 | | -| string.cpp:374:28:374:29 | s1 | string.cpp:374:31:374:35 | call to begin | TAINT | -| string.cpp:374:31:374:35 | call to begin | string.cpp:376:9:376:13 | iter1 | | -| string.cpp:374:31:374:35 | call to begin | string.cpp:377:8:377:12 | iter1 | | -| string.cpp:376:9:376:13 | iter1 | string.cpp:376:8:376:8 | call to operator* | TAINT | -| string.cpp:377:8:377:12 | iter1 | string.cpp:377:13:377:13 | call to operator[] | TAINT | -| string.cpp:378:28:378:29 | s2 | string.cpp:378:31:378:35 | call to begin | TAINT | -| string.cpp:378:31:378:35 | call to begin | string.cpp:380:9:380:13 | iter2 | | -| string.cpp:378:31:378:35 | call to begin | string.cpp:381:8:381:12 | iter2 | | -| string.cpp:380:9:380:13 | iter2 | string.cpp:380:8:380:8 | call to operator* | TAINT | -| string.cpp:381:8:381:12 | iter2 | string.cpp:381:13:381:13 | call to operator[] | TAINT | -| string.cpp:386:18:386:24 | hello | string.cpp:386:18:386:25 | call to basic_string | TAINT | -| string.cpp:386:18:386:25 | call to basic_string | string.cpp:389:25:389:26 | s1 | | -| string.cpp:387:18:387:23 | call to source | string.cpp:387:18:387:26 | call to basic_string | TAINT | -| string.cpp:387:18:387:26 | call to basic_string | string.cpp:391:25:391:26 | s2 | | -| string.cpp:387:18:387:26 | call to basic_string | string.cpp:411:8:411:9 | s2 | | -| string.cpp:389:25:389:26 | s1 | string.cpp:389:28:389:32 | call to begin | TAINT | -| string.cpp:391:25:391:26 | ref arg s2 | string.cpp:411:8:411:9 | s2 | | -| string.cpp:391:25:391:26 | s2 | string.cpp:391:28:391:32 | call to begin | TAINT | -| string.cpp:391:28:391:32 | call to begin | string.cpp:394:10:394:11 | i2 | | -| string.cpp:391:28:391:32 | call to begin | string.cpp:395:10:395:11 | i2 | | -| string.cpp:391:28:391:32 | call to begin | string.cpp:396:8:396:9 | i2 | | -| string.cpp:391:28:391:32 | call to begin | string.cpp:398:8:398:9 | i2 | | -| string.cpp:391:28:391:32 | call to begin | string.cpp:400:8:400:9 | i2 | | -| string.cpp:391:28:391:32 | call to begin | string.cpp:403:8:403:9 | i2 | | -| string.cpp:391:28:391:32 | call to begin | string.cpp:406:8:406:9 | i2 | | -| string.cpp:391:28:391:32 | call to begin | string.cpp:408:8:408:9 | i2 | | -| string.cpp:394:10:394:11 | i2 | string.cpp:394:12:394:12 | call to operator+ | TAINT | -| string.cpp:394:10:394:11 | ref arg i2 | string.cpp:395:10:395:11 | i2 | | -| string.cpp:394:10:394:11 | ref arg i2 | string.cpp:396:8:396:9 | i2 | | -| string.cpp:394:10:394:11 | ref arg i2 | string.cpp:398:8:398:9 | i2 | | -| string.cpp:394:10:394:11 | ref arg i2 | string.cpp:400:8:400:9 | i2 | | -| string.cpp:394:10:394:11 | ref arg i2 | string.cpp:403:8:403:9 | i2 | | -| string.cpp:394:10:394:11 | ref arg i2 | string.cpp:406:8:406:9 | i2 | | -| string.cpp:394:10:394:11 | ref arg i2 | string.cpp:408:8:408:9 | i2 | | -| string.cpp:394:12:394:12 | call to operator+ | string.cpp:394:8:394:8 | call to operator* | TAINT | -| string.cpp:395:10:395:11 | i2 | string.cpp:395:12:395:12 | call to operator- | TAINT | -| string.cpp:395:10:395:11 | ref arg i2 | string.cpp:396:8:396:9 | i2 | | -| string.cpp:395:10:395:11 | ref arg i2 | string.cpp:398:8:398:9 | i2 | | -| string.cpp:395:10:395:11 | ref arg i2 | string.cpp:400:8:400:9 | i2 | | -| string.cpp:395:10:395:11 | ref arg i2 | string.cpp:403:8:403:9 | i2 | | -| string.cpp:395:10:395:11 | ref arg i2 | string.cpp:406:8:406:9 | i2 | | -| string.cpp:395:10:395:11 | ref arg i2 | string.cpp:408:8:408:9 | i2 | | -| string.cpp:395:12:395:12 | call to operator- | string.cpp:395:8:395:8 | call to operator* | TAINT | -| 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++ | | +| string.cpp:357:18:357:25 | call to basic_string | string.cpp:362:8:362:9 | s1 | | +| string.cpp:357:18:357:25 | call to basic_string | string.cpp:363:8:363:9 | s1 | | +| string.cpp:357:18:357:25 | call to basic_string | string.cpp:364:8:364:9 | s1 | | +| string.cpp:358:18:358:23 | call to source | string.cpp:358:18:358:26 | call to basic_string | TAINT | +| string.cpp:358:18:358:26 | call to basic_string | string.cpp:363:18:363:19 | s2 | | +| string.cpp:358:18:358:26 | call to basic_string | string.cpp:363:30:363:31 | s2 | | +| string.cpp:359:18:359:24 | hello | string.cpp:359:18:359:25 | call to basic_string | TAINT | +| string.cpp:359:18:359:25 | call to basic_string | string.cpp:366:8:366:9 | s3 | | +| string.cpp:359:18:359:25 | call to basic_string | string.cpp:367:8:367:9 | s3 | | +| string.cpp:359:18:359:25 | call to basic_string | string.cpp:368:8:368:9 | s3 | | +| string.cpp:360:18:360:24 | world | string.cpp:360:18:360:25 | call to basic_string | TAINT | +| string.cpp:360:18:360:25 | call to basic_string | string.cpp:367:18:367:19 | s4 | | +| string.cpp:360:18:360:25 | call to basic_string | string.cpp:367:30:367:31 | s4 | | +| string.cpp:363:8:363:9 | ref arg s1 | string.cpp:364:8:364:9 | s1 | | +| string.cpp:363:8:363:9 | s1 | string.cpp:363:11:363:16 | call to append | TAINT | +| string.cpp:363:18:363:19 | ref arg s2 | string.cpp:363:30:363:31 | s2 | | +| string.cpp:363:18:363:19 | s2 | string.cpp:363:21:363:25 | call to begin | TAINT | +| string.cpp:363:21:363:25 | call to begin | string.cpp:363:8:363:9 | ref arg s1 | TAINT | +| string.cpp:363:21:363:25 | call to begin | string.cpp:363:11:363:16 | call to append | TAINT | +| string.cpp:363:30:363:31 | s2 | string.cpp:363:33:363:35 | call to end | TAINT | +| string.cpp:363:33:363:35 | call to end | string.cpp:363:8:363:9 | ref arg s1 | TAINT | +| string.cpp:363:33:363:35 | call to end | string.cpp:363:11:363:16 | call to append | TAINT | +| string.cpp:367:8:367:9 | ref arg s3 | string.cpp:368:8:368:9 | s3 | | +| string.cpp:367:8:367:9 | s3 | string.cpp:367:11:367:16 | call to append | TAINT | +| string.cpp:367:18:367:19 | ref arg s4 | string.cpp:367:30:367:31 | s4 | | +| string.cpp:367:18:367:19 | s4 | string.cpp:367:21:367:25 | call to begin | TAINT | +| string.cpp:367:21:367:25 | call to begin | string.cpp:367:8:367:9 | ref arg s3 | TAINT | +| string.cpp:367:21:367:25 | call to begin | string.cpp:367:11:367:16 | call to append | TAINT | +| string.cpp:367:30:367:31 | s4 | string.cpp:367:33:367:35 | call to end | TAINT | +| string.cpp:367:33:367:35 | call to end | string.cpp:367:8:367:9 | ref arg s3 | TAINT | +| string.cpp:367:33:367:35 | call to end | string.cpp:367:11:367:16 | call to append | TAINT | +| string.cpp:373:18:373:24 | hello | string.cpp:373:18:373:25 | call to basic_string | TAINT | +| string.cpp:373:18:373:25 | call to basic_string | string.cpp:376:28:376:29 | s1 | | +| string.cpp:374:18:374:23 | call to source | string.cpp:374:18:374:26 | call to basic_string | TAINT | +| string.cpp:374:18:374:26 | call to basic_string | string.cpp:380:28:380:29 | s2 | | +| string.cpp:376:28:376:29 | s1 | string.cpp:376:31:376:35 | call to begin | TAINT | +| string.cpp:376:31:376:35 | call to begin | string.cpp:378:9:378:13 | iter1 | | +| string.cpp:376:31:376:35 | call to begin | string.cpp:379:8:379:12 | iter1 | | +| string.cpp:378:9:378:13 | iter1 | string.cpp:378:8:378:8 | call to operator* | TAINT | +| string.cpp:379:8:379:12 | iter1 | string.cpp:379:13:379:13 | call to operator[] | TAINT | +| string.cpp:380:28:380:29 | s2 | string.cpp:380:31:380:35 | call to begin | TAINT | +| string.cpp:380:31:380:35 | call to begin | string.cpp:382:9:382:13 | iter2 | | +| string.cpp:380:31:380:35 | call to begin | string.cpp:383:8:383:12 | iter2 | | +| string.cpp:382:9:382:13 | iter2 | string.cpp:382:8:382:8 | call to operator* | TAINT | +| string.cpp:383:8:383:12 | iter2 | string.cpp:383:13:383:13 | call to operator[] | TAINT | +| string.cpp:388:18:388:24 | hello | string.cpp:388:18:388:25 | call to basic_string | TAINT | +| string.cpp:388:18:388:25 | call to basic_string | string.cpp:391:25:391:26 | s1 | | +| string.cpp:389:18:389:23 | call to source | string.cpp:389:18:389:26 | call to basic_string | TAINT | +| string.cpp:389:18:389:26 | call to basic_string | string.cpp:393:25:393:26 | s2 | | +| string.cpp:389:18:389:26 | call to basic_string | string.cpp:413:8:413:9 | s2 | | +| string.cpp:391:25:391:26 | s1 | string.cpp:391:28:391:32 | call to begin | TAINT | +| string.cpp:393:25:393:26 | ref arg s2 | string.cpp:413:8:413:9 | s2 | | +| string.cpp:393:25:393:26 | s2 | string.cpp:393:28:393:32 | call to begin | TAINT | +| string.cpp:393:28:393:32 | call to begin | string.cpp:396:10:396:11 | i2 | | +| string.cpp:393:28:393:32 | call to begin | string.cpp:397:10:397:11 | i2 | | +| string.cpp:393:28:393:32 | call to begin | string.cpp:398:8:398:9 | i2 | | +| string.cpp:393:28:393:32 | call to begin | string.cpp:400:8:400:9 | i2 | | +| string.cpp:393:28:393:32 | call to begin | string.cpp:402:8:402:9 | i2 | | +| string.cpp:393:28:393:32 | call to begin | string.cpp:405:8:405:9 | i2 | | +| string.cpp:393:28:393:32 | call to begin | string.cpp:408:8:408:9 | i2 | | +| string.cpp:393:28:393:32 | call to begin | string.cpp:410:8:410:9 | i2 | | +| string.cpp:396:10:396:11 | i2 | string.cpp:396:12:396:12 | call to operator+ | TAINT | +| string.cpp:396:10:396:11 | ref arg i2 | string.cpp:397:10:397:11 | i2 | | +| string.cpp:396:10:396:11 | ref arg i2 | string.cpp:398:8:398:9 | i2 | | +| string.cpp:396:10:396:11 | ref arg i2 | string.cpp:400:8:400:9 | i2 | | +| string.cpp:396:10:396:11 | ref arg i2 | string.cpp:402:8:402:9 | i2 | | +| string.cpp:396:10:396:11 | ref arg i2 | string.cpp:405:8:405:9 | i2 | | +| string.cpp:396:10:396:11 | ref arg i2 | string.cpp:408:8:408:9 | i2 | | +| string.cpp:396:10:396:11 | ref arg i2 | string.cpp:410:8:410:9 | i2 | | +| string.cpp:396:12:396:12 | call to operator+ | string.cpp:396:8:396:8 | call to operator* | TAINT | +| string.cpp:397:10:397:11 | i2 | string.cpp:397:12:397:12 | call to operator- | TAINT | +| string.cpp:397:10:397:11 | ref arg i2 | string.cpp:398:8:398:9 | i2 | | +| string.cpp:397:10:397:11 | ref arg i2 | string.cpp:400:8:400:9 | i2 | | +| string.cpp:397:10:397:11 | ref arg i2 | string.cpp:402:8:402:9 | i2 | | +| string.cpp:397:10:397:11 | ref arg i2 | string.cpp:405:8:405:9 | i2 | | +| string.cpp:397:10:397:11 | ref arg i2 | string.cpp:408:8:408:9 | i2 | | +| string.cpp:397:10:397:11 | ref arg i2 | string.cpp:410:8:410:9 | i2 | | +| string.cpp:397:12:397:12 | call to operator- | string.cpp:397:8:397:8 | call to operator* | TAINT | | 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-- | | +| string.cpp:398:8:398:9 | i2 | string.cpp:399:12:399:13 | i3 | | +| 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 | i3 | 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++ | | -| 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-- | | -| 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+= | | -| 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:400:8:400:9 | i2 | string.cpp:401:12:401:13 | i4 | | +| string.cpp:401:10:401:10 | call to operator-- | string.cpp:401:8:401:8 | call to operator* | TAINT | +| string.cpp:401:12:401:13 | i4 | string.cpp:401:10:401:10 | call to operator-- | | +| string.cpp:402:8:402:9 | i2 | string.cpp:402:3:402:9 | ... = ... | | +| string.cpp:402:8:402:9 | i2 | string.cpp:403:3:403:4 | i5 | | +| string.cpp:402:8:402:9 | i2 | string.cpp:404:9:404:10 | i5 | | +| string.cpp:403:3:403:4 | i5 | string.cpp:403:5:403:5 | call to operator++ | | +| string.cpp:403:3:403:4 | ref arg i5 | string.cpp:404:9:404:10 | i5 | | +| string.cpp:404:9:404:10 | i5 | string.cpp:404:8:404:8 | call to operator* | TAINT | +| string.cpp:405:8:405:9 | i2 | string.cpp:405:3:405:9 | ... = ... | | +| string.cpp:405:8:405:9 | i2 | string.cpp:406:3:406:4 | i6 | | +| string.cpp:405:8:405:9 | i2 | string.cpp:407:9:407:10 | i6 | | +| string.cpp:406:3:406:4 | i6 | string.cpp:406:5:406:5 | call to operator-- | | +| string.cpp:406:3:406:4 | ref arg i6 | string.cpp:407:9:407:10 | i6 | | +| string.cpp:407:9:407:10 | i6 | string.cpp:407:8:407:8 | call to operator* | TAINT | | 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-= | | -| 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-- | | -| 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 | -| string.cpp:419:17:419:21 | call to basic_string | string.cpp:424:7:424:8 | s1 | | -| string.cpp:419:17:419:21 | call to basic_string | string.cpp:425:7:425:8 | s1 | | -| string.cpp:420:17:420:20 | bb | string.cpp:420:17:420:21 | call to basic_string | TAINT | -| string.cpp:420:17:420:21 | call to basic_string | string.cpp:427:7:427:8 | s2 | | -| string.cpp:420:17:420:21 | call to basic_string | string.cpp:428:7:428:8 | s2 | | -| string.cpp:421:14:421:17 | cc | string.cpp:424:20:424:22 | cs1 | | -| string.cpp:422:14:422:19 | call to source | string.cpp:427:20:427:22 | cs2 | | -| string.cpp:424:7:424:8 | ref arg s1 | string.cpp:425:7:425:8 | s1 | | -| string.cpp:424:7:424:8 | s1 | string.cpp:424:10:424:15 | call to insert | TAINT | -| string.cpp:424:20:424:22 | cs1 | string.cpp:424:7:424:8 | ref arg s1 | TAINT | -| string.cpp:424:20:424:22 | cs1 | string.cpp:424:10:424:15 | call to insert | TAINT | -| string.cpp:427:7:427:8 | ref arg s2 | string.cpp:428:7:428:8 | s2 | | -| string.cpp:427:7:427:8 | s2 | string.cpp:427:10:427:15 | call to insert | TAINT | -| string.cpp:427:20:427:22 | cs2 | string.cpp:427:7:427:8 | ref arg s2 | TAINT | -| string.cpp:427:20:427:22 | cs2 | string.cpp:427:10:427:15 | call to insert | TAINT | -| string.cpp:436:17:436:20 | aa | string.cpp:436:17:436:21 | call to basic_string | TAINT | -| string.cpp:436:17:436:21 | call to basic_string | string.cpp:439:8:439:8 | a | | -| string.cpp:436:17:436:21 | call to basic_string | string.cpp:439:17:439:17 | a | | -| string.cpp:436:17:436:21 | call to basic_string | string.cpp:440:8:440:8 | a | | -| string.cpp:437:17:437:20 | bb | string.cpp:437:17:437:21 | call to basic_string | TAINT | -| string.cpp:437:17:437:21 | call to basic_string | string.cpp:442:8:442:8 | b | | -| string.cpp:437:17:437:21 | call to basic_string | string.cpp:442:17:442:17 | b | | -| string.cpp:437:17:437:21 | call to basic_string | string.cpp:443:8:443:8 | b | | -| string.cpp:439:8:439:8 | a | string.cpp:439:10:439:15 | call to insert | TAINT | -| string.cpp:439:8:439:8 | ref arg a | string.cpp:440:8:440:8 | a | | -| string.cpp:439:17:439:17 | a | string.cpp:439:19:439:23 | call to begin | TAINT | -| string.cpp:439:17:439:17 | ref arg a | string.cpp:439:8:439:8 | a | | -| string.cpp:439:17:439:17 | ref arg a | string.cpp:440:8:440:8 | a | | -| string.cpp:439:19:439:23 | call to begin | string.cpp:439:17:439:25 | call to iterator | TAINT | -| string.cpp:439:32:439:34 | 120 | string.cpp:439:8:439:8 | ref arg a | TAINT | -| string.cpp:439:32:439:34 | 120 | string.cpp:439:10:439:15 | call to insert | TAINT | -| string.cpp:442:8:442:8 | b | string.cpp:442:10:442:15 | call to insert | TAINT | -| string.cpp:442:8:442:8 | ref arg b | string.cpp:443:8:443:8 | b | | -| string.cpp:442:17:442:17 | b | string.cpp:442:19:442:23 | call to begin | TAINT | -| string.cpp:442:17:442:17 | ref arg b | string.cpp:442:8:442:8 | b | | -| string.cpp:442:17:442:17 | ref arg b | string.cpp:443:8:443:8 | b | | -| string.cpp:442:19:442:23 | call to begin | string.cpp:442:17:442:25 | call to iterator | TAINT | -| string.cpp:442:32:442:46 | call to source | string.cpp:442:8:442:8 | ref arg b | TAINT | -| string.cpp:442:32:442:46 | call to source | string.cpp:442:10:442:15 | call to insert | TAINT | -| string.cpp:447:17:447:20 | cc | string.cpp:447:17:447:21 | call to basic_string | TAINT | -| string.cpp:447:17:447:21 | call to basic_string | string.cpp:452:8:452:8 | c | | -| string.cpp:447:17:447:21 | call to basic_string | string.cpp:452:17:452:17 | c | | -| string.cpp:447:17:447:21 | call to basic_string | string.cpp:453:8:453:8 | c | | -| string.cpp:448:17:448:20 | dd | string.cpp:448:17:448:21 | call to basic_string | TAINT | -| string.cpp:448:17:448:21 | call to basic_string | string.cpp:455:8:455:8 | d | | -| string.cpp:448:17:448:21 | call to basic_string | string.cpp:455:17:455:17 | d | | -| string.cpp:448:17:448:21 | call to basic_string | string.cpp:456:8:456:8 | d | | -| string.cpp:449:18:449:21 | 11 | string.cpp:449:18:449:22 | call to basic_string | TAINT | -| string.cpp:449:18:449:22 | call to basic_string | string.cpp:452:26:452:27 | s1 | | -| string.cpp:449:18:449:22 | call to basic_string | string.cpp:452:38:452:39 | s1 | | -| string.cpp:449:18:449:22 | call to basic_string | string.cpp:458:28:458:29 | s1 | | -| string.cpp:449:18:449:22 | call to basic_string | string.cpp:458:40:458:41 | s1 | | -| string.cpp:450:18:450:23 | call to source | string.cpp:450:18:450:26 | call to basic_string | TAINT | -| string.cpp:450:18:450:26 | call to basic_string | string.cpp:455:26:455:27 | s2 | | -| string.cpp:450:18:450:26 | call to basic_string | string.cpp:455:38:455:39 | s2 | | -| string.cpp:450:18:450:26 | call to basic_string | string.cpp:458:8:458:9 | s2 | | -| string.cpp:450:18:450:26 | call to basic_string | string.cpp:458:18:458:19 | s2 | | -| string.cpp:450:18:450:26 | call to basic_string | string.cpp:459:8:459:9 | s2 | | -| string.cpp:452:8:452:8 | c | string.cpp:452:10:452:15 | call to insert | TAINT | -| string.cpp:452:8:452:8 | ref arg c | string.cpp:453:8:453:8 | c | | -| string.cpp:452:17:452:17 | c | string.cpp:452:19:452:21 | call to end | TAINT | -| string.cpp:452:17:452:17 | ref arg c | string.cpp:452:8:452:8 | c | | -| string.cpp:452:17:452:17 | ref arg c | string.cpp:453:8:453:8 | c | | -| string.cpp:452:19:452:21 | call to end | string.cpp:452:17:452:23 | call to iterator | TAINT | -| string.cpp:452:26:452:27 | ref arg s1 | string.cpp:452:38:452:39 | s1 | | -| string.cpp:452:26:452:27 | ref arg s1 | string.cpp:458:28:458:29 | s1 | | -| string.cpp:452:26:452:27 | ref arg s1 | string.cpp:458:40:458:41 | s1 | | -| string.cpp:452:26:452:27 | s1 | string.cpp:452:29:452:33 | call to begin | TAINT | -| string.cpp:452:29:452:33 | call to begin | string.cpp:452:8:452:8 | ref arg c | TAINT | -| string.cpp:452:29:452:33 | call to begin | string.cpp:452:10:452:15 | call to insert | TAINT | -| string.cpp:452:38:452:39 | ref arg s1 | string.cpp:458:28:458:29 | s1 | | -| string.cpp:452:38:452:39 | ref arg s1 | string.cpp:458:40:458:41 | s1 | | -| string.cpp:452:38:452:39 | s1 | string.cpp:452:41:452:43 | call to end | TAINT | -| string.cpp:452:41:452:43 | call to end | string.cpp:452:8:452:8 | ref arg c | TAINT | -| string.cpp:452:41:452:43 | call to end | string.cpp:452:10:452:15 | call to insert | TAINT | -| string.cpp:455:8:455:8 | d | string.cpp:455:10:455:15 | call to insert | TAINT | -| string.cpp:455:8:455:8 | ref arg d | string.cpp:456:8:456:8 | d | | -| string.cpp:455:17:455:17 | d | string.cpp:455:19:455:21 | call to end | TAINT | -| string.cpp:455:17:455:17 | ref arg d | string.cpp:455:8:455:8 | d | | -| string.cpp:455:17:455:17 | ref arg d | string.cpp:456:8:456:8 | d | | -| string.cpp:455:19:455:21 | call to end | string.cpp:455:17:455:23 | call to iterator | TAINT | -| string.cpp:455:26:455:27 | ref arg s2 | string.cpp:455:38:455:39 | s2 | | -| string.cpp:455:26:455:27 | ref arg s2 | string.cpp:458:8:458:9 | s2 | | -| string.cpp:455:26:455:27 | ref arg s2 | string.cpp:458:18:458:19 | s2 | | -| string.cpp:455:26:455:27 | ref arg s2 | string.cpp:459:8:459:9 | s2 | | -| string.cpp:455:26:455:27 | s2 | string.cpp:455:29:455:33 | call to begin | TAINT | -| string.cpp:455:29:455:33 | call to begin | string.cpp:455:8:455:8 | ref arg d | TAINT | -| string.cpp:455:29:455:33 | call to begin | string.cpp:455:10:455:15 | call to insert | TAINT | -| string.cpp:455:38:455:39 | ref arg s2 | string.cpp:458:8:458:9 | s2 | | -| string.cpp:455:38:455:39 | ref arg s2 | string.cpp:458:18:458:19 | s2 | | -| string.cpp:455:38:455:39 | ref arg s2 | string.cpp:459:8:459:9 | s2 | | -| string.cpp:455:38:455:39 | s2 | string.cpp:455:41:455:43 | call to end | TAINT | -| string.cpp:455:41:455:43 | call to end | string.cpp:455:8:455:8 | ref arg d | TAINT | -| string.cpp:455:41:455:43 | call to end | string.cpp:455:10:455:15 | call to insert | TAINT | -| string.cpp:458:8:458:9 | ref arg s2 | string.cpp:459:8:459:9 | s2 | | -| string.cpp:458:8:458:9 | s2 | string.cpp:458:11:458:16 | call to insert | TAINT | -| string.cpp:458:18:458:19 | ref arg s2 | string.cpp:458:8:458:9 | s2 | | -| string.cpp:458:18:458:19 | ref arg s2 | string.cpp:459:8:459:9 | s2 | | -| string.cpp:458:18:458:19 | s2 | string.cpp:458:21:458:23 | call to end | TAINT | -| string.cpp:458:21:458:23 | call to end | string.cpp:458:18:458:25 | call to iterator | TAINT | -| string.cpp:458:28:458:29 | ref arg s1 | string.cpp:458:40:458:41 | s1 | | -| string.cpp:458:28:458:29 | s1 | string.cpp:458:31:458:35 | call to begin | TAINT | -| string.cpp:458:31:458:35 | call to begin | string.cpp:458:8:458:9 | ref arg s2 | TAINT | -| string.cpp:458:31:458:35 | call to begin | string.cpp:458:11:458:16 | call to insert | TAINT | -| string.cpp:458:40:458:41 | s1 | string.cpp:458:43:458:45 | call to end | TAINT | -| string.cpp:458:43:458:45 | call to end | string.cpp:458:8:458:9 | ref arg s2 | TAINT | -| string.cpp:458:43:458:45 | call to end | string.cpp:458:11:458:16 | call to insert | TAINT | -| string.cpp:463:17:463:20 | ee | string.cpp:463:17:463:21 | call to basic_string | TAINT | -| string.cpp:463:17:463:21 | call to basic_string | string.cpp:468:8:468:8 | e | | -| string.cpp:463:17:463:21 | call to basic_string | string.cpp:469:8:469:8 | e | | -| string.cpp:464:17:464:20 | ff | string.cpp:464:17:464:21 | call to basic_string | TAINT | -| string.cpp:464:17:464:21 | call to basic_string | string.cpp:471:8:471:8 | f | | -| string.cpp:464:17:464:21 | call to basic_string | string.cpp:472:8:472:8 | f | | -| string.cpp:465:18:465:21 | 33 | string.cpp:465:18:465:22 | call to basic_string | TAINT | -| string.cpp:465:18:465:22 | call to basic_string | string.cpp:468:17:468:18 | s3 | | -| string.cpp:465:18:465:22 | call to basic_string | string.cpp:468:29:468:30 | s3 | | -| string.cpp:465:18:465:22 | call to basic_string | string.cpp:474:18:474:19 | s3 | | -| string.cpp:465:18:465:22 | call to basic_string | string.cpp:474:30:474:31 | s3 | | -| string.cpp:466:18:466:23 | call to source | string.cpp:466:18:466:26 | call to basic_string | TAINT | -| string.cpp:466:18:466:26 | call to basic_string | string.cpp:471:17:471:18 | s4 | | -| string.cpp:466:18:466:26 | call to basic_string | string.cpp:471:29:471:30 | s4 | | -| string.cpp:466:18:466:26 | call to basic_string | string.cpp:474:8:474:9 | s4 | | -| string.cpp:466:18:466:26 | call to basic_string | string.cpp:475:8:475:9 | s4 | | -| string.cpp:468:8:468:8 | e | string.cpp:468:10:468:15 | call to append | TAINT | -| string.cpp:468:8:468:8 | ref arg e | string.cpp:469:8:469:8 | e | | -| string.cpp:468:17:468:18 | ref arg s3 | string.cpp:468:29:468:30 | s3 | | -| string.cpp:468:17:468:18 | ref arg s3 | string.cpp:474:18:474:19 | s3 | | -| string.cpp:468:17:468:18 | ref arg s3 | string.cpp:474:30:474:31 | s3 | | -| string.cpp:468:17:468:18 | s3 | string.cpp:468:20:468:24 | call to begin | TAINT | -| string.cpp:468:20:468:24 | call to begin | string.cpp:468:8:468:8 | ref arg e | TAINT | -| string.cpp:468:20:468:24 | call to begin | string.cpp:468:10:468:15 | call to append | TAINT | -| string.cpp:468:29:468:30 | ref arg s3 | string.cpp:474:18:474:19 | s3 | | -| string.cpp:468:29:468:30 | ref arg s3 | string.cpp:474:30:474:31 | s3 | | -| string.cpp:468:29:468:30 | s3 | string.cpp:468:32:468:34 | call to end | TAINT | -| string.cpp:468:32:468:34 | call to end | string.cpp:468:8:468:8 | ref arg e | TAINT | -| string.cpp:468:32:468:34 | call to end | string.cpp:468:10:468:15 | call to append | TAINT | -| string.cpp:471:8:471:8 | f | string.cpp:471:10:471:15 | call to append | TAINT | -| string.cpp:471:8:471:8 | ref arg f | string.cpp:472:8:472:8 | f | | -| string.cpp:471:17:471:18 | ref arg s4 | string.cpp:471:29:471:30 | s4 | | -| string.cpp:471:17:471:18 | ref arg s4 | string.cpp:474:8:474:9 | s4 | | -| string.cpp:471:17:471:18 | ref arg s4 | string.cpp:475:8:475:9 | s4 | | -| string.cpp:471:17:471:18 | s4 | string.cpp:471:20:471:24 | call to begin | TAINT | -| string.cpp:471:20:471:24 | call to begin | string.cpp:471:8:471:8 | ref arg f | TAINT | -| string.cpp:471:20:471:24 | call to begin | string.cpp:471:10:471:15 | call to append | TAINT | -| string.cpp:471:29:471:30 | ref arg s4 | string.cpp:474:8:474:9 | s4 | | -| string.cpp:471:29:471:30 | ref arg s4 | string.cpp:475:8:475:9 | s4 | | -| string.cpp:471:29:471:30 | s4 | string.cpp:471:32:471:34 | call to end | TAINT | -| string.cpp:471:32:471:34 | call to end | string.cpp:471:8:471:8 | ref arg f | TAINT | -| string.cpp:471:32:471:34 | call to end | string.cpp:471:10:471:15 | call to append | TAINT | -| string.cpp:474:8:474:9 | ref arg s4 | string.cpp:475:8:475:9 | s4 | | -| string.cpp:474:8:474:9 | s4 | string.cpp:474:11:474:16 | call to append | TAINT | -| string.cpp:474:18:474:19 | ref arg s3 | string.cpp:474:30:474:31 | s3 | | -| string.cpp:474:18:474:19 | s3 | string.cpp:474:21:474:25 | call to begin | TAINT | -| string.cpp:474:21:474:25 | call to begin | string.cpp:474:8:474:9 | ref arg s4 | TAINT | -| string.cpp:474:21:474:25 | call to begin | string.cpp:474:11:474:16 | call to append | TAINT | -| string.cpp:474:30:474:31 | s3 | string.cpp:474:33:474:35 | call to end | TAINT | -| string.cpp:474:33:474:35 | call to end | string.cpp:474:8:474:9 | ref arg s4 | TAINT | -| string.cpp:474:33:474:35 | call to end | string.cpp:474:11:474:16 | call to append | TAINT | -| string.cpp:479:17:479:20 | gg | string.cpp:479:17:479:21 | call to basic_string | TAINT | -| string.cpp:479:17:479:21 | call to basic_string | string.cpp:484:8:484:8 | g | | -| string.cpp:479:17:479:21 | call to basic_string | string.cpp:485:8:485:8 | g | | -| string.cpp:480:17:480:20 | hh | string.cpp:480:17:480:21 | call to basic_string | TAINT | -| string.cpp:480:17:480:21 | call to basic_string | string.cpp:487:8:487:8 | h | | -| string.cpp:480:17:480:21 | call to basic_string | string.cpp:488:8:488:8 | h | | -| string.cpp:481:18:481:21 | 55 | string.cpp:481:18:481:22 | call to basic_string | TAINT | -| string.cpp:481:18:481:22 | call to basic_string | string.cpp:484:17:484:18 | s5 | | -| string.cpp:481:18:481:22 | call to basic_string | string.cpp:484:30:484:31 | s5 | | -| string.cpp:481:18:481:22 | call to basic_string | string.cpp:490:18:490:19 | s5 | | -| string.cpp:481:18:481:22 | call to basic_string | string.cpp:490:31:490:32 | s5 | | -| string.cpp:482:18:482:23 | call to source | string.cpp:482:18:482:26 | call to basic_string | TAINT | -| string.cpp:482:18:482:26 | call to basic_string | string.cpp:487:17:487:18 | s6 | | -| string.cpp:482:18:482:26 | call to basic_string | string.cpp:487:30:487:31 | s6 | | -| string.cpp:482:18:482:26 | call to basic_string | string.cpp:490:8:490:9 | s6 | | -| string.cpp:482:18:482:26 | call to basic_string | string.cpp:491:8:491:9 | s6 | | -| string.cpp:484:8:484:8 | ref arg g | string.cpp:485:8:485:8 | g | | -| string.cpp:484:17:484:18 | s5 | string.cpp:484:20:484:25 | call to cbegin | TAINT | -| string.cpp:484:20:484:25 | call to cbegin | string.cpp:484:8:484:8 | ref arg g | TAINT | -| string.cpp:484:20:484:25 | call to cbegin | string.cpp:484:10:484:15 | call to assign | TAINT | -| string.cpp:484:30:484:31 | s5 | string.cpp:484:33:484:36 | call to cend | TAINT | -| string.cpp:484:33:484:36 | call to cend | string.cpp:484:8:484:8 | ref arg g | TAINT | -| string.cpp:484:33:484:36 | call to cend | string.cpp:484:10:484:15 | call to assign | TAINT | -| string.cpp:487:8:487:8 | ref arg h | string.cpp:488:8:488:8 | h | | -| string.cpp:487:17:487:18 | s6 | string.cpp:487:20:487:25 | call to cbegin | TAINT | -| string.cpp:487:20:487:25 | call to cbegin | string.cpp:487:8:487:8 | ref arg h | TAINT | -| string.cpp:487:20:487:25 | call to cbegin | string.cpp:487:10:487:15 | call to assign | TAINT | -| string.cpp:487:30:487:31 | s6 | string.cpp:487:33:487:36 | call to cend | TAINT | -| string.cpp:487:33:487:36 | call to cend | string.cpp:487:8:487:8 | ref arg h | TAINT | -| string.cpp:487:33:487:36 | call to cend | string.cpp:487:10:487:15 | call to assign | TAINT | -| string.cpp:490:8:490:9 | ref arg s6 | string.cpp:491:8:491:9 | s6 | | -| string.cpp:490:18:490:19 | s5 | string.cpp:490:21:490:26 | call to cbegin | TAINT | -| string.cpp:490:21:490:26 | call to cbegin | string.cpp:490:8:490:9 | ref arg s6 | TAINT | -| string.cpp:490:21:490:26 | call to cbegin | string.cpp:490:11:490:16 | call to assign | TAINT | -| string.cpp:490:31:490:32 | s5 | string.cpp:490:34:490:37 | call to cend | TAINT | -| string.cpp:490:34:490:37 | call to cend | string.cpp:490:8:490:9 | ref arg s6 | TAINT | -| string.cpp:490:34:490:37 | call to cend | string.cpp:490:11:490:16 | call to assign | TAINT | -| string.cpp:496:14:496:18 | abc | string.cpp:498:17:498:19 | cs1 | | -| string.cpp:497:14:497:19 | call to source | string.cpp:499:17:499:19 | cs2 | | -| string.cpp:498:17:498:19 | cs1 | string.cpp:498:17:498:20 | call to basic_string | TAINT | -| string.cpp:498:17:498:20 | call to basic_string | string.cpp:500:17:500:18 | s1 | | -| string.cpp:498:17:498:20 | call to basic_string | string.cpp:500:29:500:30 | s1 | | -| string.cpp:498:17:498:20 | call to basic_string | string.cpp:503:7:503:8 | s1 | | -| string.cpp:499:17:499:19 | cs2 | string.cpp:499:17:499:20 | call to basic_string | TAINT | -| string.cpp:499:17:499:20 | call to basic_string | string.cpp:501:17:501:18 | s2 | | -| string.cpp:499:17:499:20 | call to basic_string | string.cpp:501:29:501:30 | s2 | | -| string.cpp:499:17:499:20 | call to basic_string | string.cpp:504:7:504:8 | s2 | | -| string.cpp:500:17:500:18 | ref arg s1 | string.cpp:500:29:500:30 | s1 | | -| string.cpp:500:17:500:18 | ref arg s1 | string.cpp:503:7:503:8 | s1 | | -| string.cpp:500:17:500:18 | s1 | string.cpp:500:20:500:24 | call to begin | TAINT | -| string.cpp:500:17:500:37 | call to basic_string | string.cpp:505:7:505:8 | s3 | | -| string.cpp:500:20:500:24 | call to begin | string.cpp:500:17:500:37 | call to basic_string | TAINT | -| string.cpp:500:29:500:30 | ref arg s1 | string.cpp:503:7:503:8 | s1 | | -| string.cpp:500:29:500:30 | s1 | string.cpp:500:32:500:34 | call to end | TAINT | -| string.cpp:500:32:500:34 | call to end | string.cpp:500:17:500:37 | call to basic_string | TAINT | -| string.cpp:501:17:501:18 | ref arg s2 | string.cpp:501:29:501:30 | s2 | | -| string.cpp:501:17:501:18 | ref arg s2 | string.cpp:504:7:504:8 | s2 | | -| string.cpp:501:17:501:18 | s2 | string.cpp:501:20:501:24 | call to begin | TAINT | -| string.cpp:501:17:501:37 | call to basic_string | string.cpp:506:7:506:8 | s4 | | -| string.cpp:501:20:501:24 | call to begin | string.cpp:501:17:501:37 | call to basic_string | TAINT | -| string.cpp:501:29:501:30 | ref arg s2 | string.cpp:504:7:504:8 | s2 | | -| string.cpp:501:29:501:30 | s2 | string.cpp:501:32:501:34 | call to end | TAINT | -| string.cpp:501:32:501:34 | call to end | string.cpp:501:17:501:37 | call to basic_string | TAINT | -| string.cpp:510:16:510:19 | aa | string.cpp:510:16:510:20 | call to basic_string | TAINT | -| string.cpp:510:16:510:20 | call to basic_string | string.cpp:512:7:512:7 | a | | -| string.cpp:510:16:510:20 | call to basic_string | string.cpp:513:7:513:7 | a | | -| string.cpp:510:16:510:20 | call to basic_string | string.cpp:514:2:514:2 | a | | -| string.cpp:510:16:510:20 | call to basic_string | string.cpp:515:7:515:7 | a | | -| string.cpp:510:16:510:20 | call to basic_string | string.cpp:516:7:516:7 | a | | -| string.cpp:512:7:512:7 | a | string.cpp:512:9:512:13 | call to front | TAINT | -| string.cpp:512:7:512:7 | ref arg a | string.cpp:513:7:513:7 | a | | -| string.cpp:512:7:512:7 | ref arg a | string.cpp:514:2:514:2 | a | | -| string.cpp:512:7:512:7 | ref arg a | string.cpp:515:7:515:7 | a | | -| string.cpp:512:7:512:7 | ref arg a | string.cpp:516:7:516:7 | a | | -| string.cpp:513:7:513:7 | a | string.cpp:513:9:513:12 | call to back | TAINT | -| string.cpp:513:7:513:7 | ref arg a | string.cpp:514:2:514:2 | a | | -| string.cpp:513:7:513:7 | ref arg a | string.cpp:515:7:515:7 | a | | -| string.cpp:513:7:513:7 | ref arg a | string.cpp:516:7:516:7 | a | | -| string.cpp:514:2:514:2 | ref arg a | string.cpp:515:7:515:7 | a | | -| string.cpp:514:2:514:2 | ref arg a | string.cpp:516:7:516:7 | a | | -| string.cpp:514:14:514:28 | call to source | string.cpp:514:2:514:2 | ref arg a | TAINT | -| string.cpp:515:7:515:7 | a | string.cpp:515:9:515:13 | call to front | TAINT | -| string.cpp:515:7:515:7 | ref arg a | string.cpp:516:7:516:7 | a | | -| string.cpp:516:7:516:7 | a | string.cpp:516:9:516:12 | call to back | TAINT | -| string.cpp:521:17:521:20 | aa | string.cpp:521:17:521:21 | call to basic_string | TAINT | -| string.cpp:521:17:521:21 | call to basic_string | string.cpp:528:9:528:9 | a | | -| string.cpp:521:17:521:21 | call to basic_string | string.cpp:532:8:532:8 | a | | -| string.cpp:522:17:522:20 | bb | string.cpp:522:17:522:21 | call to basic_string | TAINT | -| string.cpp:522:17:522:21 | call to basic_string | string.cpp:528:15:528:15 | b | | -| string.cpp:522:17:522:21 | call to basic_string | string.cpp:533:8:533:8 | b | | -| string.cpp:523:17:523:20 | cc | string.cpp:523:17:523:21 | call to basic_string | TAINT | -| string.cpp:523:17:523:21 | call to basic_string | string.cpp:529:9:529:9 | c | | -| string.cpp:523:17:523:21 | call to basic_string | string.cpp:534:8:534:8 | c | | -| string.cpp:524:17:524:20 | dd | string.cpp:524:17:524:21 | call to basic_string | TAINT | -| string.cpp:524:17:524:21 | call to basic_string | string.cpp:529:15:529:15 | d | | -| string.cpp:524:17:524:21 | call to basic_string | string.cpp:535:8:535:8 | d | | -| string.cpp:525:17:525:20 | ee | string.cpp:525:17:525:21 | call to basic_string | TAINT | -| string.cpp:525:17:525:21 | call to basic_string | string.cpp:530:10:530:10 | e | | -| string.cpp:525:17:525:21 | call to basic_string | string.cpp:536:8:536:8 | e | | -| string.cpp:526:17:526:20 | ff | string.cpp:526:17:526:21 | call to basic_string | TAINT | -| string.cpp:526:17:526:21 | call to basic_string | string.cpp:531:10:531:10 | f | | -| string.cpp:526:17:526:21 | call to basic_string | string.cpp:537:8:537:8 | f | | -| string.cpp:528:9:528:9 | a | string.cpp:528:11:528:11 | call to operator+= | TAINT | -| string.cpp:528:9:528:9 | ref arg a | string.cpp:532:8:532:8 | a | | -| string.cpp:528:15:528:15 | b | string.cpp:528:17:528:17 | call to operator+= | TAINT | -| string.cpp:528:15:528:15 | ref arg b | string.cpp:533:8:533:8 | b | | -| string.cpp:528:17:528:17 | call to operator+= | string.cpp:528:9:528:9 | ref arg a | TAINT | -| string.cpp:528:17:528:17 | call to operator+= | string.cpp:528:11:528:11 | call to operator+= | TAINT | -| string.cpp:528:20:528:23 | bb | string.cpp:528:15:528:15 | ref arg b | TAINT | -| string.cpp:528:20:528:23 | bb | string.cpp:528:17:528:17 | call to operator+= | TAINT | -| string.cpp:529:9:529:9 | c | string.cpp:529:11:529:11 | call to operator+= | TAINT | -| string.cpp:529:9:529:9 | ref arg c | string.cpp:534:8:534:8 | c | | -| string.cpp:529:15:529:15 | d | string.cpp:529:17:529:17 | call to operator+= | TAINT | -| string.cpp:529:15:529:15 | ref arg d | string.cpp:535:8:535:8 | d | | -| string.cpp:529:17:529:17 | call to operator+= | string.cpp:529:9:529:9 | ref arg c | TAINT | -| string.cpp:529:17:529:17 | call to operator+= | string.cpp:529:11:529:11 | call to operator+= | TAINT | -| string.cpp:529:20:529:25 | call to source | string.cpp:529:15:529:15 | ref arg d | TAINT | -| string.cpp:529:20:529:25 | call to source | string.cpp:529:17:529:17 | call to operator+= | TAINT | -| string.cpp:530:10:530:10 | e | string.cpp:530:12:530:12 | call to operator+= | TAINT | -| string.cpp:530:10:530:10 | ref arg e | string.cpp:536:8:536:8 | e | | -| string.cpp:530:12:530:12 | call to operator+= | string.cpp:530:21:530:21 | call to operator+= | TAINT | -| string.cpp:530:12:530:12 | ref arg call to operator+= | string.cpp:530:10:530:10 | ref arg e | TAINT | -| string.cpp:530:15:530:18 | ee | string.cpp:530:10:530:10 | ref arg e | TAINT | -| string.cpp:530:15:530:18 | ee | string.cpp:530:12:530:12 | call to operator+= | TAINT | -| string.cpp:530:24:530:29 | call to source | string.cpp:530:12:530:12 | ref arg call to operator+= | TAINT | -| string.cpp:530:24:530:29 | call to source | string.cpp:530:21:530:21 | call to operator+= | TAINT | -| string.cpp:531:10:531:10 | f | string.cpp:531:12:531:12 | call to operator+= | TAINT | -| string.cpp:531:10:531:10 | ref arg f | string.cpp:537:8:537:8 | f | | -| string.cpp:531:12:531:12 | call to operator+= | string.cpp:531:25:531:25 | call to operator+= | TAINT | -| string.cpp:531:12:531:12 | ref arg call to operator+= | string.cpp:531:10:531:10 | ref arg f | TAINT | -| string.cpp:531:15:531:20 | call to source | string.cpp:531:10:531:10 | ref arg f | TAINT | -| string.cpp:531:15:531:20 | call to source | string.cpp:531:12:531:12 | call to operator+= | TAINT | -| string.cpp:531:28:531:31 | ff | string.cpp:531:12:531:12 | ref arg call to operator+= | TAINT | -| string.cpp:531:28:531:31 | ff | string.cpp:531:25:531:25 | call to operator+= | TAINT | -| string.cpp:541:17:541:20 | aa | string.cpp:541:17:541:21 | call to basic_string | TAINT | -| string.cpp:541:17:541:21 | call to basic_string | string.cpp:548:9:548:9 | a | | -| string.cpp:541:17:541:21 | call to basic_string | string.cpp:552:8:552:8 | a | | -| string.cpp:542:17:542:20 | bb | string.cpp:542:17:542:21 | call to basic_string | TAINT | -| string.cpp:542:17:542:21 | call to basic_string | string.cpp:548:18:548:18 | b | | -| string.cpp:542:17:542:21 | call to basic_string | string.cpp:553:8:553:8 | b | | -| string.cpp:543:17:543:20 | cc | string.cpp:543:17:543:21 | call to basic_string | TAINT | -| string.cpp:543:17:543:21 | call to basic_string | string.cpp:549:9:549:9 | c | | -| string.cpp:543:17:543:21 | call to basic_string | string.cpp:554:8:554:8 | c | | -| string.cpp:544:17:544:20 | dd | string.cpp:544:17:544:21 | call to basic_string | TAINT | -| string.cpp:544:17:544:21 | call to basic_string | string.cpp:549:18:549:18 | d | | -| string.cpp:544:17:544:21 | call to basic_string | string.cpp:555:8:555:8 | d | | -| string.cpp:545:17:545:20 | ee | string.cpp:545:17:545:21 | call to basic_string | TAINT | -| string.cpp:545:17:545:21 | call to basic_string | string.cpp:550:9:550:9 | e | | -| string.cpp:545:17:545:21 | call to basic_string | string.cpp:556:8:556:8 | e | | -| string.cpp:546:17:546:20 | ff | string.cpp:546:17:546:21 | call to basic_string | TAINT | -| string.cpp:546:17:546:21 | call to basic_string | string.cpp:551:9:551:9 | f | | -| string.cpp:546:17:546:21 | call to basic_string | string.cpp:557:8:557:8 | f | | -| string.cpp:548:9:548:9 | ref arg a | string.cpp:552:8:552:8 | a | | -| string.cpp:548:18:548:18 | ref arg b | string.cpp:553:8:553:8 | b | | -| string.cpp:548:20:548:25 | call to assign | string.cpp:548:9:548:9 | ref arg a | TAINT | -| string.cpp:548:20:548:25 | call to assign | string.cpp:548:11:548:16 | call to assign | TAINT | -| string.cpp:548:27:548:30 | bb | string.cpp:548:27:548:30 | call to basic_string | TAINT | -| string.cpp:548:27:548:30 | call to basic_string | string.cpp:548:18:548:18 | ref arg b | TAINT | -| string.cpp:548:27:548:30 | call to basic_string | string.cpp:548:20:548:25 | call to assign | TAINT | -| string.cpp:549:9:549:9 | ref arg c | string.cpp:554:8:554:8 | c | | -| string.cpp:549:18:549:18 | ref arg d | string.cpp:555:8:555:8 | d | | -| string.cpp:549:20:549:25 | call to assign | string.cpp:549:9:549:9 | ref arg c | TAINT | -| string.cpp:549:20:549:25 | call to assign | string.cpp:549:11:549:16 | call to assign | TAINT | -| string.cpp:549:27:549:32 | call to source | string.cpp:549:27:549:34 | call to basic_string | TAINT | -| string.cpp:549:27:549:34 | call to basic_string | string.cpp:549:18:549:18 | ref arg d | TAINT | -| string.cpp:549:27:549:34 | call to basic_string | string.cpp:549:20:549:25 | call to assign | TAINT | -| string.cpp:550:9:550:9 | ref arg e | string.cpp:556:8:556:8 | e | | -| string.cpp:550:11:550:16 | ref arg call to assign | string.cpp:550:9:550:9 | ref arg e | TAINT | -| string.cpp:550:18:550:21 | call to basic_string | string.cpp:550:9:550:9 | ref arg e | TAINT | -| string.cpp:550:18:550:21 | call to basic_string | string.cpp:550:11:550:16 | call to assign | TAINT | -| string.cpp:550:18:550:21 | ee | string.cpp:550:18:550:21 | call to basic_string | TAINT | -| string.cpp:550:31:550:36 | call to source | string.cpp:550:31:550:38 | call to basic_string | TAINT | -| string.cpp:550:31:550:38 | call to basic_string | string.cpp:550:11:550:16 | ref arg call to assign | TAINT | -| string.cpp:550:31:550:38 | call to basic_string | string.cpp:550:24:550:29 | call to assign | TAINT | -| string.cpp:551:9:551:9 | ref arg f | string.cpp:557:8:557:8 | f | | -| string.cpp:551:11:551:16 | ref arg call to assign | string.cpp:551:9:551:9 | ref arg f | TAINT | -| string.cpp:551:18:551:23 | call to source | string.cpp:551:18:551:25 | call to basic_string | TAINT | -| string.cpp:551:18:551:25 | call to basic_string | string.cpp:551:9:551:9 | ref arg f | TAINT | -| string.cpp:551:18:551:25 | call to basic_string | string.cpp:551:11:551:16 | call to assign | TAINT | -| string.cpp:551:35:551:38 | call to basic_string | string.cpp:551:11:551:16 | ref arg call to assign | TAINT | -| string.cpp:551:35:551:38 | call to basic_string | string.cpp:551:28:551:33 | call to assign | TAINT | -| string.cpp:551:35:551:38 | ff | string.cpp:551:35:551:38 | call to basic_string | TAINT | +| string.cpp:408:8:408:9 | i2 | string.cpp:409:10:409:11 | i7 | | +| string.cpp:409:10:409:11 | i7 | 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:410:8:410:9 | i2 | string.cpp:410:3:410:9 | ... = ... | | +| string.cpp:410:8:410:9 | i2 | string.cpp:411:10:411:11 | i8 | | +| string.cpp:411:10:411:11 | i8 | string.cpp:411:12:411:12 | call to operator-= | | +| string.cpp:411:12:411:12 | call to operator-= | string.cpp:411:8:411:8 | call to operator* | TAINT | +| string.cpp:411:14:411:14 | 1 | string.cpp:411:12:411:12 | call to operator-= | | +| string.cpp:413:8:413:9 | s2 | string.cpp:413:11:413:13 | call to end | TAINT | +| string.cpp:413:11:413:13 | call to end | string.cpp:413:3:413:15 | ... = ... | | +| string.cpp:413:11:413:13 | call to end | string.cpp:414:5:414:6 | i9 | | +| string.cpp:413:11:413:13 | call to end | string.cpp:415:9:415:10 | i9 | | +| string.cpp:414:5:414:6 | i9 | string.cpp:414:3:414:3 | call to operator-- | | +| string.cpp:414:5:414:6 | ref arg i9 | string.cpp:415:9:415:10 | i9 | | +| string.cpp:415:9:415:10 | i9 | string.cpp:415:8:415:8 | call to operator* | TAINT | +| string.cpp:428:17:428:20 | aa | string.cpp:428:17:428:21 | call to basic_string | TAINT | +| string.cpp:428:17:428:21 | call to basic_string | string.cpp:433:7:433:8 | s1 | | +| string.cpp:428:17:428:21 | call to basic_string | string.cpp:434:7:434:8 | s1 | | +| string.cpp:429:17:429:20 | bb | string.cpp:429:17:429:21 | call to basic_string | TAINT | +| string.cpp:429:17:429:21 | call to basic_string | string.cpp:436:7:436:8 | s2 | | +| string.cpp:429:17:429:21 | call to basic_string | string.cpp:437:7:437:8 | s2 | | +| string.cpp:430:14:430:17 | cc | string.cpp:433:20:433:22 | cs1 | | +| string.cpp:431:14:431:19 | call to source | string.cpp:436:20:436:22 | cs2 | | +| string.cpp:433:7:433:8 | ref arg s1 | string.cpp:434:7:434:8 | s1 | | +| string.cpp:433:7:433:8 | s1 | string.cpp:433:10:433:15 | call to insert | TAINT | +| string.cpp:433:20:433:22 | cs1 | string.cpp:433:7:433:8 | ref arg s1 | TAINT | +| string.cpp:433:20:433:22 | cs1 | string.cpp:433:10:433:15 | call to insert | TAINT | +| string.cpp:436:7:436:8 | ref arg s2 | string.cpp:437:7:437:8 | s2 | | +| string.cpp:436:7:436:8 | s2 | string.cpp:436:10:436:15 | call to insert | TAINT | +| string.cpp:436:20:436:22 | cs2 | string.cpp:436:7:436:8 | ref arg s2 | TAINT | +| string.cpp:436:20:436:22 | cs2 | string.cpp:436:10:436:15 | call to insert | TAINT | +| string.cpp:443:17:443:20 | aa | string.cpp:443:17:443:21 | call to basic_string | TAINT | +| string.cpp:443:17:443:21 | call to basic_string | string.cpp:446:8:446:8 | a | | +| string.cpp:443:17:443:21 | call to basic_string | string.cpp:446:17:446:17 | a | | +| string.cpp:443:17:443:21 | call to basic_string | string.cpp:447:8:447:8 | a | | +| string.cpp:444:17:444:20 | bb | string.cpp:444:17:444:21 | call to basic_string | TAINT | +| string.cpp:444:17:444:21 | call to basic_string | string.cpp:449:8:449:8 | b | | +| string.cpp:444:17:444:21 | call to basic_string | string.cpp:449:17:449:17 | b | | +| string.cpp:444:17:444:21 | call to basic_string | string.cpp:450:8:450:8 | b | | +| string.cpp:446:8:446:8 | a | string.cpp:446:10:446:15 | call to insert | TAINT | +| string.cpp:446:8:446:8 | ref arg a | string.cpp:447:8:447:8 | a | | +| string.cpp:446:17:446:17 | a | string.cpp:446:19:446:23 | call to begin | TAINT | +| string.cpp:446:17:446:17 | ref arg a | string.cpp:446:8:446:8 | a | | +| string.cpp:446:17:446:17 | ref arg a | string.cpp:447:8:447:8 | a | | +| string.cpp:446:19:446:23 | call to begin | string.cpp:446:17:446:25 | call to iterator | TAINT | +| string.cpp:446:32:446:34 | 120 | string.cpp:446:8:446:8 | ref arg a | TAINT | +| string.cpp:446:32:446:34 | 120 | string.cpp:446:10:446:15 | call to insert | TAINT | +| string.cpp:449:8:449:8 | b | string.cpp:449:10:449:15 | call to insert | TAINT | +| string.cpp:449:8:449:8 | ref arg b | string.cpp:450:8:450:8 | b | | +| string.cpp:449:17:449:17 | b | string.cpp:449:19:449:23 | call to begin | TAINT | +| string.cpp:449:17:449:17 | ref arg b | string.cpp:449:8:449:8 | b | | +| string.cpp:449:17:449:17 | ref arg b | string.cpp:450:8:450:8 | b | | +| string.cpp:449:19:449:23 | call to begin | string.cpp:449:17:449:25 | call to iterator | TAINT | +| string.cpp:449:32:449:46 | call to source | string.cpp:449:8:449:8 | ref arg b | TAINT | +| string.cpp:449:32:449:46 | call to source | string.cpp:449:10:449:15 | call to insert | TAINT | +| string.cpp:454:17:454:20 | cc | string.cpp:454:17:454:21 | call to basic_string | TAINT | +| string.cpp:454:17:454:21 | call to basic_string | string.cpp:459:8:459:8 | c | | +| string.cpp:454:17:454:21 | call to basic_string | string.cpp:459:17:459:17 | c | | +| string.cpp:454:17:454:21 | call to basic_string | string.cpp:460:8:460:8 | c | | +| string.cpp:455:17:455:20 | dd | string.cpp:455:17:455:21 | call to basic_string | TAINT | +| string.cpp:455:17:455:21 | call to basic_string | string.cpp:462:8:462:8 | d | | +| string.cpp:455:17:455:21 | call to basic_string | string.cpp:462:17:462:17 | d | | +| string.cpp:455:17:455:21 | call to basic_string | string.cpp:463:8:463:8 | d | | +| string.cpp:456:18:456:21 | 11 | string.cpp:456:18:456:22 | call to basic_string | TAINT | +| string.cpp:456:18:456:22 | call to basic_string | string.cpp:459:26:459:27 | s1 | | +| string.cpp:456:18:456:22 | call to basic_string | string.cpp:459:38:459:39 | s1 | | +| string.cpp:456:18:456:22 | call to basic_string | string.cpp:465:28:465:29 | s1 | | +| string.cpp:456:18:456:22 | call to basic_string | string.cpp:465:40:465:41 | s1 | | +| string.cpp:457:18:457:23 | call to source | string.cpp:457:18:457:26 | call to basic_string | TAINT | +| string.cpp:457:18:457:26 | call to basic_string | string.cpp:462:26:462:27 | s2 | | +| string.cpp:457:18:457:26 | call to basic_string | string.cpp:462:38:462:39 | s2 | | +| string.cpp:457:18:457:26 | call to basic_string | string.cpp:465:8:465:9 | s2 | | +| string.cpp:457:18:457:26 | call to basic_string | string.cpp:465:18:465:19 | s2 | | +| string.cpp:457:18:457:26 | call to basic_string | string.cpp:466:8:466:9 | s2 | | +| string.cpp:459:8:459:8 | c | string.cpp:459:10:459:15 | call to insert | TAINT | +| string.cpp:459:8:459:8 | ref arg c | string.cpp:460:8:460:8 | c | | +| string.cpp:459:17:459:17 | c | string.cpp:459:19:459:21 | call to end | TAINT | +| string.cpp:459:17:459:17 | ref arg c | string.cpp:459:8:459:8 | c | | +| string.cpp:459:17:459:17 | ref arg c | string.cpp:460:8:460:8 | c | | +| string.cpp:459:19:459:21 | call to end | string.cpp:459:17:459:23 | call to iterator | TAINT | +| string.cpp:459:26:459:27 | ref arg s1 | string.cpp:459:38:459:39 | s1 | | +| string.cpp:459:26:459:27 | ref arg s1 | string.cpp:465:28:465:29 | s1 | | +| string.cpp:459:26:459:27 | ref arg s1 | string.cpp:465:40:465:41 | s1 | | +| string.cpp:459:26:459:27 | s1 | string.cpp:459:29:459:33 | call to begin | TAINT | +| string.cpp:459:29:459:33 | call to begin | string.cpp:459:8:459:8 | ref arg c | TAINT | +| string.cpp:459:29:459:33 | call to begin | string.cpp:459:10:459:15 | call to insert | TAINT | +| string.cpp:459:38:459:39 | ref arg s1 | string.cpp:465:28:465:29 | s1 | | +| string.cpp:459:38:459:39 | ref arg s1 | string.cpp:465:40:465:41 | s1 | | +| string.cpp:459:38:459:39 | s1 | string.cpp:459:41:459:43 | call to end | TAINT | +| string.cpp:459:41:459:43 | call to end | string.cpp:459:8:459:8 | ref arg c | TAINT | +| string.cpp:459:41:459:43 | call to end | string.cpp:459:10:459:15 | call to insert | TAINT | +| string.cpp:462:8:462:8 | d | string.cpp:462:10:462:15 | call to insert | TAINT | +| string.cpp:462:8:462:8 | ref arg d | string.cpp:463:8:463:8 | d | | +| string.cpp:462:17:462:17 | d | string.cpp:462:19:462:21 | call to end | TAINT | +| string.cpp:462:17:462:17 | ref arg d | string.cpp:462:8:462:8 | d | | +| string.cpp:462:17:462:17 | ref arg d | string.cpp:463:8:463:8 | d | | +| string.cpp:462:19:462:21 | call to end | string.cpp:462:17:462:23 | call to iterator | TAINT | +| string.cpp:462:26:462:27 | ref arg s2 | string.cpp:462:38:462:39 | s2 | | +| string.cpp:462:26:462:27 | ref arg s2 | string.cpp:465:8:465:9 | s2 | | +| string.cpp:462:26:462:27 | ref arg s2 | string.cpp:465:18:465:19 | s2 | | +| string.cpp:462:26:462:27 | ref arg s2 | string.cpp:466:8:466:9 | s2 | | +| string.cpp:462:26:462:27 | s2 | string.cpp:462:29:462:33 | call to begin | TAINT | +| string.cpp:462:29:462:33 | call to begin | string.cpp:462:8:462:8 | ref arg d | TAINT | +| string.cpp:462:29:462:33 | call to begin | string.cpp:462:10:462:15 | call to insert | TAINT | +| string.cpp:462:38:462:39 | ref arg s2 | string.cpp:465:8:465:9 | s2 | | +| string.cpp:462:38:462:39 | ref arg s2 | string.cpp:465:18:465:19 | s2 | | +| string.cpp:462:38:462:39 | ref arg s2 | string.cpp:466:8:466:9 | s2 | | +| string.cpp:462:38:462:39 | s2 | string.cpp:462:41:462:43 | call to end | TAINT | +| string.cpp:462:41:462:43 | call to end | string.cpp:462:8:462:8 | ref arg d | TAINT | +| string.cpp:462:41:462:43 | call to end | string.cpp:462:10:462:15 | call to insert | TAINT | +| string.cpp:465:8:465:9 | ref arg s2 | string.cpp:466:8:466:9 | s2 | | +| string.cpp:465:8:465:9 | s2 | string.cpp:465:11:465:16 | call to insert | TAINT | +| string.cpp:465:18:465:19 | ref arg s2 | string.cpp:465:8:465:9 | s2 | | +| string.cpp:465:18:465:19 | ref arg s2 | string.cpp:466:8:466:9 | s2 | | +| string.cpp:465:18:465:19 | s2 | string.cpp:465:21:465:23 | call to end | TAINT | +| string.cpp:465:21:465:23 | call to end | string.cpp:465:18:465:25 | call to iterator | TAINT | +| string.cpp:465:28:465:29 | ref arg s1 | string.cpp:465:40:465:41 | s1 | | +| string.cpp:465:28:465:29 | s1 | string.cpp:465:31:465:35 | call to begin | TAINT | +| string.cpp:465:31:465:35 | call to begin | string.cpp:465:8:465:9 | ref arg s2 | TAINT | +| string.cpp:465:31:465:35 | call to begin | string.cpp:465:11:465:16 | call to insert | TAINT | +| string.cpp:465:40:465:41 | s1 | string.cpp:465:43:465:45 | call to end | TAINT | +| string.cpp:465:43:465:45 | call to end | string.cpp:465:8:465:9 | ref arg s2 | TAINT | +| string.cpp:465:43:465:45 | call to end | string.cpp:465:11:465:16 | call to insert | TAINT | +| string.cpp:470:17:470:20 | ee | string.cpp:470:17:470:21 | call to basic_string | TAINT | +| string.cpp:470:17:470:21 | call to basic_string | string.cpp:475:8:475:8 | e | | +| string.cpp:470:17:470:21 | call to basic_string | string.cpp:476:8:476:8 | e | | +| string.cpp:471:17:471:20 | ff | string.cpp:471:17:471:21 | call to basic_string | TAINT | +| string.cpp:471:17:471:21 | call to basic_string | string.cpp:478:8:478:8 | f | | +| string.cpp:471:17:471:21 | call to basic_string | string.cpp:479:8:479:8 | f | | +| string.cpp:472:18:472:21 | 33 | string.cpp:472:18:472:22 | call to basic_string | TAINT | +| string.cpp:472:18:472:22 | call to basic_string | string.cpp:475:17:475:18 | s3 | | +| string.cpp:472:18:472:22 | call to basic_string | string.cpp:475:29:475:30 | s3 | | +| string.cpp:472:18:472:22 | call to basic_string | string.cpp:481:18:481:19 | s3 | | +| string.cpp:472:18:472:22 | call to basic_string | string.cpp:481:30:481:31 | s3 | | +| string.cpp:473:18:473:23 | call to source | string.cpp:473:18:473:26 | call to basic_string | TAINT | +| string.cpp:473:18:473:26 | call to basic_string | string.cpp:478:17:478:18 | s4 | | +| string.cpp:473:18:473:26 | call to basic_string | string.cpp:478:29:478:30 | s4 | | +| string.cpp:473:18:473:26 | call to basic_string | string.cpp:481:8:481:9 | s4 | | +| string.cpp:473:18:473:26 | call to basic_string | string.cpp:482:8:482:9 | s4 | | +| string.cpp:475:8:475:8 | e | string.cpp:475:10:475:15 | call to append | TAINT | +| string.cpp:475:8:475:8 | ref arg e | string.cpp:476:8:476:8 | e | | +| string.cpp:475:17:475:18 | ref arg s3 | string.cpp:475:29:475:30 | s3 | | +| string.cpp:475:17:475:18 | ref arg s3 | string.cpp:481:18:481:19 | s3 | | +| string.cpp:475:17:475:18 | ref arg s3 | string.cpp:481:30:481:31 | s3 | | +| string.cpp:475:17:475:18 | s3 | string.cpp:475:20:475:24 | call to begin | TAINT | +| string.cpp:475:20:475:24 | call to begin | string.cpp:475:8:475:8 | ref arg e | TAINT | +| string.cpp:475:20:475:24 | call to begin | string.cpp:475:10:475:15 | call to append | TAINT | +| string.cpp:475:29:475:30 | ref arg s3 | string.cpp:481:18:481:19 | s3 | | +| string.cpp:475:29:475:30 | ref arg s3 | string.cpp:481:30:481:31 | s3 | | +| string.cpp:475:29:475:30 | s3 | string.cpp:475:32:475:34 | call to end | TAINT | +| string.cpp:475:32:475:34 | call to end | string.cpp:475:8:475:8 | ref arg e | TAINT | +| string.cpp:475:32:475:34 | call to end | string.cpp:475:10:475:15 | call to append | TAINT | +| string.cpp:478:8:478:8 | f | string.cpp:478:10:478:15 | call to append | TAINT | +| string.cpp:478:8:478:8 | ref arg f | string.cpp:479:8:479:8 | f | | +| string.cpp:478:17:478:18 | ref arg s4 | string.cpp:478:29:478:30 | s4 | | +| string.cpp:478:17:478:18 | ref arg s4 | string.cpp:481:8:481:9 | s4 | | +| string.cpp:478:17:478:18 | ref arg s4 | string.cpp:482:8:482:9 | s4 | | +| string.cpp:478:17:478:18 | s4 | string.cpp:478:20:478:24 | call to begin | TAINT | +| string.cpp:478:20:478:24 | call to begin | string.cpp:478:8:478:8 | ref arg f | TAINT | +| string.cpp:478:20:478:24 | call to begin | string.cpp:478:10:478:15 | call to append | TAINT | +| string.cpp:478:29:478:30 | ref arg s4 | string.cpp:481:8:481:9 | s4 | | +| string.cpp:478:29:478:30 | ref arg s4 | string.cpp:482:8:482:9 | s4 | | +| string.cpp:478:29:478:30 | s4 | string.cpp:478:32:478:34 | call to end | TAINT | +| string.cpp:478:32:478:34 | call to end | string.cpp:478:8:478:8 | ref arg f | TAINT | +| string.cpp:478:32:478:34 | call to end | string.cpp:478:10:478:15 | call to append | TAINT | +| string.cpp:481:8:481:9 | ref arg s4 | string.cpp:482:8:482:9 | s4 | | +| string.cpp:481:8:481:9 | s4 | string.cpp:481:11:481:16 | call to append | TAINT | +| string.cpp:481:18:481:19 | ref arg s3 | string.cpp:481:30:481:31 | s3 | | +| string.cpp:481:18:481:19 | s3 | string.cpp:481:21:481:25 | call to begin | TAINT | +| string.cpp:481:21:481:25 | call to begin | string.cpp:481:8:481:9 | ref arg s4 | TAINT | +| string.cpp:481:21:481:25 | call to begin | string.cpp:481:11:481:16 | call to append | TAINT | +| string.cpp:481:30:481:31 | s3 | string.cpp:481:33:481:35 | call to end | TAINT | +| string.cpp:481:33:481:35 | call to end | string.cpp:481:8:481:9 | ref arg s4 | TAINT | +| string.cpp:481:33:481:35 | call to end | string.cpp:481:11:481:16 | call to append | TAINT | +| string.cpp:486:17:486:20 | gg | string.cpp:486:17:486:21 | call to basic_string | TAINT | +| string.cpp:486:17:486:21 | call to basic_string | string.cpp:491:8:491:8 | g | | +| string.cpp:486:17:486:21 | call to basic_string | string.cpp:492:8:492:8 | g | | +| string.cpp:487:17:487:20 | hh | string.cpp:487:17:487:21 | call to basic_string | TAINT | +| string.cpp:487:17:487:21 | call to basic_string | string.cpp:494:8:494:8 | h | | +| string.cpp:487:17:487:21 | call to basic_string | string.cpp:495:8:495:8 | h | | +| string.cpp:488:18:488:21 | 55 | string.cpp:488:18:488:22 | call to basic_string | TAINT | +| string.cpp:488:18:488:22 | call to basic_string | string.cpp:491:17:491:18 | s5 | | +| string.cpp:488:18:488:22 | call to basic_string | string.cpp:491:30:491:31 | s5 | | +| string.cpp:488:18:488:22 | call to basic_string | string.cpp:497:18:497:19 | s5 | | +| string.cpp:488:18:488:22 | call to basic_string | string.cpp:497:31:497:32 | s5 | | +| string.cpp:489:18:489:23 | call to source | string.cpp:489:18:489:26 | call to basic_string | TAINT | +| string.cpp:489:18:489:26 | call to basic_string | string.cpp:494:17:494:18 | s6 | | +| string.cpp:489:18:489:26 | call to basic_string | string.cpp:494:30:494:31 | s6 | | +| string.cpp:489:18:489:26 | call to basic_string | string.cpp:497:8:497:9 | s6 | | +| string.cpp:489:18:489:26 | call to basic_string | string.cpp:498:8:498:9 | s6 | | +| string.cpp:491:8:491:8 | ref arg g | string.cpp:492:8:492:8 | g | | +| string.cpp:491:17:491:18 | s5 | string.cpp:491:20:491:25 | call to cbegin | TAINT | +| string.cpp:491:20:491:25 | call to cbegin | string.cpp:491:8:491:8 | ref arg g | TAINT | +| string.cpp:491:20:491:25 | call to cbegin | string.cpp:491:10:491:15 | call to assign | TAINT | +| string.cpp:491:30:491:31 | s5 | string.cpp:491:33:491:36 | call to cend | TAINT | +| string.cpp:491:33:491:36 | call to cend | string.cpp:491:8:491:8 | ref arg g | TAINT | +| string.cpp:491:33:491:36 | call to cend | string.cpp:491:10:491:15 | call to assign | TAINT | +| string.cpp:494:8:494:8 | ref arg h | string.cpp:495:8:495:8 | h | | +| string.cpp:494:17:494:18 | s6 | string.cpp:494:20:494:25 | call to cbegin | TAINT | +| string.cpp:494:20:494:25 | call to cbegin | string.cpp:494:8:494:8 | ref arg h | TAINT | +| string.cpp:494:20:494:25 | call to cbegin | string.cpp:494:10:494:15 | call to assign | TAINT | +| string.cpp:494:30:494:31 | s6 | string.cpp:494:33:494:36 | call to cend | TAINT | +| string.cpp:494:33:494:36 | call to cend | string.cpp:494:8:494:8 | ref arg h | TAINT | +| string.cpp:494:33:494:36 | call to cend | string.cpp:494:10:494:15 | call to assign | TAINT | +| string.cpp:497:8:497:9 | ref arg s6 | string.cpp:498:8:498:9 | s6 | | +| string.cpp:497:18:497:19 | s5 | string.cpp:497:21:497:26 | call to cbegin | TAINT | +| string.cpp:497:21:497:26 | call to cbegin | string.cpp:497:8:497:9 | ref arg s6 | TAINT | +| string.cpp:497:21:497:26 | call to cbegin | string.cpp:497:11:497:16 | call to assign | TAINT | +| string.cpp:497:31:497:32 | s5 | string.cpp:497:34:497:37 | call to cend | TAINT | +| string.cpp:497:34:497:37 | call to cend | string.cpp:497:8:497:9 | ref arg s6 | TAINT | +| string.cpp:497:34:497:37 | call to cend | string.cpp:497:11:497:16 | call to assign | TAINT | +| string.cpp:503:14:503:18 | abc | string.cpp:505:17:505:19 | cs1 | | +| string.cpp:504:14:504:19 | call to source | string.cpp:506:17:506:19 | cs2 | | +| string.cpp:505:17:505:19 | cs1 | string.cpp:505:17:505:20 | call to basic_string | TAINT | +| string.cpp:505:17:505:20 | call to basic_string | string.cpp:507:17:507:18 | s1 | | +| string.cpp:505:17:505:20 | call to basic_string | string.cpp:507:29:507:30 | s1 | | +| string.cpp:505:17:505:20 | call to basic_string | string.cpp:510:7:510:8 | s1 | | +| string.cpp:506:17:506:19 | cs2 | string.cpp:506:17:506:20 | call to basic_string | TAINT | +| string.cpp:506:17:506:20 | call to basic_string | string.cpp:508:17:508:18 | s2 | | +| string.cpp:506:17:506:20 | call to basic_string | string.cpp:508:29:508:30 | s2 | | +| string.cpp:506:17:506:20 | call to basic_string | string.cpp:511:7:511:8 | s2 | | +| string.cpp:507:17:507:18 | ref arg s1 | string.cpp:507:29:507:30 | s1 | | +| string.cpp:507:17:507:18 | ref arg s1 | string.cpp:510:7:510:8 | s1 | | +| string.cpp:507:17:507:18 | s1 | string.cpp:507:20:507:24 | call to begin | TAINT | +| string.cpp:507:17:507:37 | call to basic_string | string.cpp:512:7:512:8 | s3 | | +| string.cpp:507:20:507:24 | call to begin | string.cpp:507:17:507:37 | call to basic_string | TAINT | +| string.cpp:507:29:507:30 | ref arg s1 | string.cpp:510:7:510:8 | s1 | | +| string.cpp:507:29:507:30 | s1 | string.cpp:507:32:507:34 | call to end | TAINT | +| string.cpp:507:32:507:34 | call to end | string.cpp:507:17:507:37 | call to basic_string | TAINT | +| string.cpp:508:17:508:18 | ref arg s2 | string.cpp:508:29:508:30 | s2 | | +| string.cpp:508:17:508:18 | ref arg s2 | string.cpp:511:7:511:8 | s2 | | +| string.cpp:508:17:508:18 | s2 | string.cpp:508:20:508:24 | call to begin | TAINT | +| string.cpp:508:17:508:37 | call to basic_string | string.cpp:513:7:513:8 | s4 | | +| string.cpp:508:20:508:24 | call to begin | string.cpp:508:17:508:37 | call to basic_string | TAINT | +| string.cpp:508:29:508:30 | ref arg s2 | string.cpp:511:7:511:8 | s2 | | +| string.cpp:508:29:508:30 | s2 | string.cpp:508:32:508:34 | call to end | TAINT | +| string.cpp:508:32:508:34 | call to end | string.cpp:508:17:508:37 | call to basic_string | TAINT | +| string.cpp:517:16:517:19 | aa | string.cpp:517:16:517:20 | call to basic_string | TAINT | +| string.cpp:517:16:517:20 | call to basic_string | string.cpp:519:7:519:7 | a | | +| string.cpp:517:16:517:20 | call to basic_string | string.cpp:520:7:520:7 | a | | +| string.cpp:517:16:517:20 | call to basic_string | string.cpp:521:2:521:2 | a | | +| string.cpp:517:16:517:20 | call to basic_string | string.cpp:522:7:522:7 | a | | +| string.cpp:517:16:517:20 | call to basic_string | string.cpp:523:7:523:7 | a | | +| string.cpp:519:7:519:7 | a | string.cpp:519:9:519:13 | call to front | TAINT | +| string.cpp:519:7:519:7 | ref arg a | string.cpp:520:7:520:7 | a | | +| string.cpp:519:7:519:7 | ref arg a | string.cpp:521:2:521:2 | a | | +| string.cpp:519:7:519:7 | ref arg a | string.cpp:522:7:522:7 | a | | +| string.cpp:519:7:519:7 | ref arg a | string.cpp:523:7:523:7 | a | | +| string.cpp:520:7:520:7 | a | string.cpp:520:9:520:12 | call to back | TAINT | +| string.cpp:520:7:520:7 | ref arg a | string.cpp:521:2:521:2 | a | | +| string.cpp:520:7:520:7 | ref arg a | string.cpp:522:7:522:7 | a | | +| string.cpp:520:7:520:7 | ref arg a | string.cpp:523:7:523:7 | a | | +| string.cpp:521:2:521:2 | ref arg a | string.cpp:522:7:522:7 | a | | +| string.cpp:521:2:521:2 | ref arg a | string.cpp:523:7:523:7 | a | | +| string.cpp:521:14:521:28 | call to source | string.cpp:521:2:521:2 | ref arg a | TAINT | +| string.cpp:522:7:522:7 | a | string.cpp:522:9:522:13 | call to front | TAINT | +| string.cpp:522:7:522:7 | ref arg a | string.cpp:523:7:523:7 | a | | +| string.cpp:523:7:523:7 | a | string.cpp:523:9:523:12 | call to back | TAINT | +| string.cpp:528:17:528:20 | aa | string.cpp:528:17:528:21 | call to basic_string | TAINT | +| string.cpp:528:17:528:21 | call to basic_string | string.cpp:535:9:535:9 | a | | +| string.cpp:528:17:528:21 | call to basic_string | string.cpp:539:8:539:8 | a | | +| string.cpp:529:17:529:20 | bb | string.cpp:529:17:529:21 | call to basic_string | TAINT | +| string.cpp:529:17:529:21 | call to basic_string | string.cpp:535:15:535:15 | b | | +| string.cpp:529:17:529:21 | call to basic_string | string.cpp:540:8:540:8 | b | | +| string.cpp:530:17:530:20 | cc | string.cpp:530:17:530:21 | call to basic_string | TAINT | +| string.cpp:530:17:530:21 | call to basic_string | string.cpp:536:9:536:9 | c | | +| string.cpp:530:17:530:21 | call to basic_string | string.cpp:541:8:541:8 | c | | +| string.cpp:531:17:531:20 | dd | string.cpp:531:17:531:21 | call to basic_string | TAINT | +| string.cpp:531:17:531:21 | call to basic_string | string.cpp:536:15:536:15 | d | | +| string.cpp:531:17:531:21 | call to basic_string | string.cpp:542:8:542:8 | d | | +| string.cpp:532:17:532:20 | ee | string.cpp:532:17:532:21 | call to basic_string | TAINT | +| string.cpp:532:17:532:21 | call to basic_string | string.cpp:537:10:537:10 | e | | +| string.cpp:532:17:532:21 | call to basic_string | string.cpp:543:8:543:8 | e | | +| string.cpp:533:17:533:20 | ff | string.cpp:533:17:533:21 | call to basic_string | TAINT | +| string.cpp:533:17:533:21 | call to basic_string | string.cpp:538:10:538:10 | f | | +| string.cpp:533:17:533:21 | call to basic_string | string.cpp:544:8:544:8 | f | | +| string.cpp:535:9:535:9 | a | string.cpp:535:11:535:11 | call to operator+= | TAINT | +| string.cpp:535:9:535:9 | ref arg a | string.cpp:539:8:539:8 | a | | +| string.cpp:535:15:535:15 | b | string.cpp:535:17:535:17 | call to operator+= | TAINT | +| string.cpp:535:15:535:15 | ref arg b | string.cpp:540:8:540:8 | b | | +| string.cpp:535:17:535:17 | call to operator+= | string.cpp:535:9:535:9 | ref arg a | TAINT | +| string.cpp:535:17:535:17 | call to operator+= | string.cpp:535:11:535:11 | call to operator+= | TAINT | +| string.cpp:535:20:535:23 | bb | string.cpp:535:15:535:15 | ref arg b | TAINT | +| string.cpp:535:20:535:23 | bb | string.cpp:535:17:535:17 | call to operator+= | TAINT | +| string.cpp:536:9:536:9 | c | string.cpp:536:11:536:11 | call to operator+= | TAINT | +| string.cpp:536:9:536:9 | ref arg c | string.cpp:541:8:541:8 | c | | +| string.cpp:536:15:536:15 | d | string.cpp:536:17:536:17 | call to operator+= | TAINT | +| string.cpp:536:15:536:15 | ref arg d | string.cpp:542:8:542:8 | d | | +| string.cpp:536:17:536:17 | call to operator+= | string.cpp:536:9:536:9 | ref arg c | TAINT | +| string.cpp:536:17:536:17 | call to operator+= | string.cpp:536:11:536:11 | call to operator+= | TAINT | +| string.cpp:536:20:536:25 | call to source | string.cpp:536:15:536:15 | ref arg d | TAINT | +| string.cpp:536:20:536:25 | call to source | string.cpp:536:17:536:17 | call to operator+= | TAINT | +| string.cpp:537:10:537:10 | e | string.cpp:537:12:537:12 | call to operator+= | TAINT | +| string.cpp:537:10:537:10 | ref arg e | string.cpp:543:8:543:8 | e | | +| string.cpp:537:12:537:12 | call to operator+= | string.cpp:537:21:537:21 | call to operator+= | TAINT | +| string.cpp:537:12:537:12 | ref arg call to operator+= | string.cpp:537:10:537:10 | ref arg e | TAINT | +| string.cpp:537:15:537:18 | ee | string.cpp:537:10:537:10 | ref arg e | TAINT | +| string.cpp:537:15:537:18 | ee | string.cpp:537:12:537:12 | call to operator+= | TAINT | +| string.cpp:537:24:537:29 | call to source | string.cpp:537:12:537:12 | ref arg call to operator+= | TAINT | +| string.cpp:537:24:537:29 | call to source | string.cpp:537:21:537:21 | call to operator+= | TAINT | +| string.cpp:538:10:538:10 | f | string.cpp:538:12:538:12 | call to operator+= | TAINT | +| string.cpp:538:10:538:10 | ref arg f | string.cpp:544:8:544:8 | f | | +| string.cpp:538:12:538:12 | call to operator+= | string.cpp:538:25:538:25 | call to operator+= | TAINT | +| string.cpp:538:12:538:12 | ref arg call to operator+= | string.cpp:538:10:538:10 | ref arg f | TAINT | +| string.cpp:538:15:538:20 | call to source | string.cpp:538:10:538:10 | ref arg f | TAINT | +| string.cpp:538:15:538:20 | call to source | string.cpp:538:12:538:12 | call to operator+= | TAINT | +| string.cpp:538:28:538:31 | ff | string.cpp:538:12:538:12 | ref arg call to operator+= | TAINT | +| string.cpp:538:28:538:31 | ff | string.cpp:538:25:538:25 | call to operator+= | TAINT | +| string.cpp:548:17:548:20 | aa | string.cpp:548:17:548:21 | call to basic_string | TAINT | +| string.cpp:548:17:548:21 | call to basic_string | string.cpp:555:9:555:9 | a | | +| string.cpp:548:17:548:21 | call to basic_string | string.cpp:559:8:559:8 | a | | +| string.cpp:549:17:549:20 | bb | string.cpp:549:17:549:21 | call to basic_string | TAINT | +| string.cpp:549:17:549:21 | call to basic_string | string.cpp:555:18:555:18 | b | | +| string.cpp:549:17:549:21 | call to basic_string | string.cpp:560:8:560:8 | b | | +| string.cpp:550:17:550:20 | cc | string.cpp:550:17:550:21 | call to basic_string | TAINT | +| string.cpp:550:17:550:21 | call to basic_string | string.cpp:556:9:556:9 | c | | +| string.cpp:550:17:550:21 | call to basic_string | string.cpp:561:8:561:8 | c | | +| string.cpp:551:17:551:20 | dd | string.cpp:551:17:551:21 | call to basic_string | TAINT | +| string.cpp:551:17:551:21 | call to basic_string | string.cpp:556:18:556:18 | d | | +| string.cpp:551:17:551:21 | call to basic_string | string.cpp:562:8:562:8 | d | | +| string.cpp:552:17:552:20 | ee | string.cpp:552:17:552:21 | call to basic_string | TAINT | +| string.cpp:552:17:552:21 | call to basic_string | string.cpp:557:9:557:9 | e | | +| string.cpp:552:17:552:21 | call to basic_string | string.cpp:563:8:563:8 | e | | +| string.cpp:553:17:553:20 | ff | string.cpp:553:17:553:21 | call to basic_string | TAINT | +| string.cpp:553:17:553:21 | call to basic_string | string.cpp:558:9:558:9 | f | | +| string.cpp:553:17:553:21 | call to basic_string | string.cpp:564:8:564:8 | f | | +| string.cpp:555:9:555:9 | ref arg a | string.cpp:559:8:559:8 | a | | +| string.cpp:555:18:555:18 | ref arg b | string.cpp:560:8:560:8 | b | | +| string.cpp:555:20:555:25 | call to assign | string.cpp:555:9:555:9 | ref arg a | TAINT | +| string.cpp:555:20:555:25 | call to assign | string.cpp:555:11:555:16 | call to assign | TAINT | +| string.cpp:555:27:555:30 | bb | string.cpp:555:27:555:30 | call to basic_string | TAINT | +| string.cpp:555:27:555:30 | call to basic_string | string.cpp:555:18:555:18 | ref arg b | TAINT | +| string.cpp:555:27:555:30 | call to basic_string | string.cpp:555:20:555:25 | call to assign | TAINT | +| string.cpp:556:9:556:9 | ref arg c | string.cpp:561:8:561:8 | c | | +| string.cpp:556:18:556:18 | ref arg d | string.cpp:562:8:562:8 | d | | +| string.cpp:556:20:556:25 | call to assign | string.cpp:556:9:556:9 | ref arg c | TAINT | +| string.cpp:556:20:556:25 | call to assign | string.cpp:556:11:556:16 | call to assign | TAINT | +| string.cpp:556:27:556:32 | call to source | string.cpp:556:27:556:34 | call to basic_string | TAINT | +| string.cpp:556:27:556:34 | call to basic_string | string.cpp:556:18:556:18 | ref arg d | TAINT | +| string.cpp:556:27:556:34 | call to basic_string | string.cpp:556:20:556:25 | call to assign | TAINT | +| string.cpp:557:9:557:9 | ref arg e | string.cpp:563:8:563:8 | e | | +| string.cpp:557:11:557:16 | ref arg call to assign | string.cpp:557:9:557:9 | ref arg e | TAINT | +| string.cpp:557:18:557:21 | call to basic_string | string.cpp:557:9:557:9 | ref arg e | TAINT | +| string.cpp:557:18:557:21 | call to basic_string | string.cpp:557:11:557:16 | call to assign | TAINT | +| string.cpp:557:18:557:21 | ee | string.cpp:557:18:557:21 | call to basic_string | TAINT | +| string.cpp:557:31:557:36 | call to source | string.cpp:557:31:557:38 | call to basic_string | TAINT | +| string.cpp:557:31:557:38 | call to basic_string | string.cpp:557:11:557:16 | ref arg call to assign | TAINT | +| string.cpp:557:31:557:38 | call to basic_string | string.cpp:557:24:557:29 | call to assign | TAINT | +| string.cpp:558:9:558:9 | ref arg f | string.cpp:564:8:564:8 | f | | +| string.cpp:558:11:558:16 | ref arg call to assign | string.cpp:558:9:558:9 | ref arg f | TAINT | +| string.cpp:558:18:558:23 | call to source | string.cpp:558:18:558:25 | call to basic_string | TAINT | +| string.cpp:558:18:558:25 | call to basic_string | string.cpp:558:9:558:9 | ref arg f | TAINT | +| string.cpp:558:18:558:25 | call to basic_string | string.cpp:558:11:558:16 | call to assign | TAINT | +| string.cpp:558:35:558:38 | call to basic_string | string.cpp:558:11:558:16 | ref arg call to assign | TAINT | +| string.cpp:558:35:558:38 | call to basic_string | string.cpp:558:28:558:33 | call to assign | TAINT | +| string.cpp:558:35:558:38 | ff | string.cpp:558:35:558:38 | call to basic_string | TAINT | | stringstream.cpp:26:35:26:40 | amount | stringstream.cpp:64:46:64:51 | amount | | | stringstream.cpp:28:20:28:22 | call to basic_stringstream | stringstream.cpp:31:7:31:9 | ss1 | | | stringstream.cpp:28:20:28:22 | call to basic_stringstream | stringstream.cpp:37:7:37:9 | ss1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp index 04b88922c3f..25d771c1818 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp @@ -18,6 +18,7 @@ void sink(const char *s); void sink(const std::string &s); void sink(const char *filename, const char *mode); void sink(char); +void sink(std::string::iterator); void test_string() { @@ -349,6 +350,7 @@ void test_string_data_more() sink(str); // tainted sink(str.data()); // tainted } + void test_string_iterators() { // string append { @@ -411,6 +413,13 @@ void test_string_iterators() { i9 = s2.end(); --i9; sink(*i9); // tainted + + + + + + + } } @@ -428,8 +437,6 @@ void test_string_insert_more() sink(s2); // tainted } -void sink(std::string::iterator); - void test_string_iterator_methods() { { 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 599aa67c2af..26aa26bcb1b 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -52,119 +52,119 @@ | standalone_iterators.cpp:46:10:46:10 | call to operator* | standalone_iterators.cpp:45:39:45:45 | source1 | | standalone_iterators.cpp:47:10:47:10 | call to operator* | standalone_iterators.cpp:45:39:45:45 | source1 | | standalone_iterators.cpp:48:10:48:10 | call to operator* | standalone_iterators.cpp:45:39:45:45 | source1 | -| string.cpp:28:7:28:7 | a | string.cpp:24:12:24:17 | call to source | -| string.cpp:30:7:30:7 | c | string.cpp:26:16:26:21 | call to source | -| string.cpp:32:9:32:13 | call to c_str | string.cpp:26:16:26:21 | call to source | -| string.cpp:38:13:38:17 | call to c_str | string.cpp:14:10:14:15 | call to source | -| string.cpp:42:13:42:17 | call to c_str | string.cpp:14:10:14:15 | call to source | -| string.cpp:45:13:45:17 | call to c_str | string.cpp:14:10:14:15 | call to source | -| string.cpp:55:7:55:8 | cs | string.cpp:50:19:50:24 | call to source | -| string.cpp:56:7:56:8 | ss | string.cpp:50:19:50:24 | call to source | -| string.cpp:69:7:69:8 | cs | string.cpp:61:19:61:24 | call to source | -| string.cpp:70:7:70:8 | ss | string.cpp:61:19:61:24 | call to source | -| string.cpp:92:8:92:9 | s1 | string.cpp:87:18:87:23 | call to source | -| string.cpp:93:8:93:9 | s2 | string.cpp:88:20:88:25 | call to source | -| string.cpp:94:8:94:9 | s3 | string.cpp:90:8:90:13 | call to source | -| string.cpp:113:8:113:9 | s1 | string.cpp:109:32:109:37 | call to source | -| string.cpp:114:8:114:9 | s2 | string.cpp:111:20:111:25 | call to source | -| string.cpp:121:8:121:8 | c | string.cpp:119:16:119:21 | call to source | -| string.cpp:125:8:125:8 | call to operator* | string.cpp:119:16:119:21 | call to source | -| string.cpp:129:8:129:8 | c | string.cpp:119:16:119:21 | call to source | -| string.cpp:134:8:134:8 | c | string.cpp:132:28:132:33 | call to source | -| string.cpp:144:11:144:11 | call to operator+ | string.cpp:141:18:141:23 | call to source | -| string.cpp:145:11:145:11 | call to operator+ | string.cpp:141:18:141:23 | call to source | -| string.cpp:146:11:146:11 | call to operator+ | string.cpp:141:18:141:23 | call to source | -| string.cpp:149:11:149:11 | call to operator+ | string.cpp:149:13:149:18 | call to source | -| string.cpp:158:8:158:9 | s5 | string.cpp:154:18:154:23 | call to source | -| string.cpp:161:11:161:11 | call to operator+= | string.cpp:154:18:154:23 | call to source | -| string.cpp:162:8:162:9 | s6 | string.cpp:154:18:154:23 | call to source | -| string.cpp:165:11:165:11 | call to operator+= | string.cpp:165:14:165:19 | call to source | -| string.cpp:166:11:166:11 | call to operator+= | string.cpp:165:14:165:19 | call to source | -| string.cpp:167:8:167:9 | s7 | string.cpp:165:14:165:19 | call to source | -| string.cpp:171:8:171:9 | s8 | string.cpp:154:18:154:23 | call to source | -| string.cpp:176:8:176:9 | s9 | string.cpp:174:13:174:18 | call to source | -| string.cpp:184:8:184:10 | s10 | string.cpp:181:12:181:26 | call to source | -| string.cpp:198:10:198:15 | call to assign | string.cpp:190:17:190:22 | call to source | -| string.cpp:199:7:199:8 | s4 | string.cpp:190:17:190:22 | call to source | -| string.cpp:201:10:201:15 | call to assign | string.cpp:191:11:191:25 | call to source | -| string.cpp:202:7:202:8 | s5 | string.cpp:191:11:191:25 | call to source | -| string.cpp:205:7:205:8 | s6 | string.cpp:193:17:193:22 | call to source | -| string.cpp:219:10:219:15 | call to insert | string.cpp:210:17:210:22 | call to source | -| string.cpp:220:7:220:8 | s4 | string.cpp:210:17:210:22 | call to source | -| string.cpp:223:10:223:15 | call to insert | string.cpp:210:17:210:22 | call to source | -| string.cpp:224:7:224:8 | s5 | string.cpp:210:17:210:22 | call to source | -| string.cpp:227:10:227:15 | call to insert | string.cpp:211:11:211:25 | call to source | -| string.cpp:228:7:228:8 | s6 | string.cpp:211:11:211:25 | call to source | -| string.cpp:242:10:242:16 | call to replace | string.cpp:233:17:233:22 | call to source | -| string.cpp:243:7:243:8 | s4 | string.cpp:233:17:233:22 | call to source | -| string.cpp:246:10:246:16 | call to replace | string.cpp:233:17:233:22 | call to source | -| string.cpp:247:7:247:8 | s5 | string.cpp:233:17:233:22 | call to source | -| string.cpp:250:10:250:16 | call to replace | string.cpp:234:11:234:25 | call to source | -| string.cpp:251:7:251:8 | s6 | string.cpp:234:11:234:25 | call to source | -| string.cpp:264:7:264:8 | b2 | string.cpp:258:17:258:22 | call to source | -| string.cpp:274:7:274:8 | s2 | string.cpp:269:17:269:22 | call to source | -| string.cpp:276:7:276:8 | s4 | string.cpp:271:17:271:22 | call to source | -| string.cpp:281:7:281:8 | s1 | string.cpp:269:17:269:22 | call to source | -| string.cpp:282:7:282:8 | s2 | string.cpp:269:17:269:22 | call to source | -| string.cpp:283:7:283:8 | s3 | string.cpp:271:17:271:22 | call to source | -| string.cpp:284:7:284:8 | s4 | string.cpp:271:17:271:22 | call to source | -| string.cpp:292:7:292:8 | s1 | string.cpp:288:17:288:22 | call to source | -| string.cpp:293:7:293:8 | s2 | string.cpp:289:17:289:22 | call to source | -| string.cpp:294:7:294:8 | s3 | string.cpp:290:17:290:22 | call to source | -| string.cpp:300:7:300:8 | s1 | string.cpp:288:17:288:22 | call to source | -| string.cpp:302:7:302:8 | s3 | string.cpp:290:17:290:22 | call to source | -| string.cpp:311:9:311:12 | call to data | string.cpp:308:16:308:21 | call to source | -| string.cpp:322:9:322:14 | call to substr | string.cpp:319:16:319:21 | call to source | -| string.cpp:339:7:339:7 | a | string.cpp:335:9:335:23 | call to source | -| string.cpp:340:7:340:7 | b | string.cpp:336:12:336:26 | call to source | -| string.cpp:341:7:341:7 | c | string.cpp:335:9:335:23 | call to source | -| string.cpp:349:7:349:9 | str | string.cpp:348:18:348:32 | call to source | -| string.cpp:350:11:350:14 | call to data | string.cpp:348:18:348:32 | call to source | -| string.cpp:361:11:361:16 | call to append | string.cpp:356:18:356:23 | call to source | -| string.cpp:362:8:362:9 | s1 | string.cpp:356:18:356:23 | call to source | -| string.cpp:380:8:380:8 | call to operator* | string.cpp:372:18:372:23 | call to source | -| string.cpp:381:13:381:13 | call to operator[] | string.cpp:372:18:372:23 | call to source | -| string.cpp:394:8:394:8 | call to operator* | string.cpp:387:18:387:23 | call to source | -| string.cpp:395:8:395:8 | call to operator* | string.cpp:387:18:387:23 | call to source | -| string.cpp:397:8:397:8 | call to operator* | string.cpp:387:18:387:23 | call to source | -| string.cpp:399:8:399:8 | call to operator* | string.cpp:387:18:387:23 | call to source | -| string.cpp:402:8:402:8 | call to operator* | string.cpp:387:18:387:23 | call to source | -| string.cpp:405:8:405:8 | call to operator* | string.cpp:387:18:387:23 | call to source | -| string.cpp:407:8:407:8 | call to operator* | string.cpp:387:18:387:23 | call to source | -| string.cpp:409:8:409:8 | call to operator* | string.cpp:387:18:387:23 | call to source | -| string.cpp:413:8:413:8 | call to operator* | string.cpp:387:18:387:23 | call to source | -| string.cpp:427:10:427:15 | call to insert | string.cpp:422:14:422:19 | call to source | -| string.cpp:428:7:428:8 | s2 | string.cpp:422:14:422:19 | call to source | -| string.cpp:442:10:442:15 | call to insert | string.cpp:442:32:442:46 | call to source | -| string.cpp:443:8:443:8 | b | string.cpp:442:32:442:46 | call to source | -| string.cpp:455:10:455:15 | call to insert | string.cpp:450:18:450:23 | call to source | -| string.cpp:456:8:456:8 | d | string.cpp:450:18:450:23 | call to source | -| string.cpp:458:11:458:16 | call to insert | string.cpp:450:18:450:23 | call to source | -| string.cpp:459:8:459:9 | s2 | string.cpp:450:18:450:23 | call to source | -| string.cpp:471:10:471:15 | call to append | string.cpp:466:18:466:23 | call to source | -| string.cpp:472:8:472:8 | f | string.cpp:466:18:466:23 | call to source | -| string.cpp:474:11:474:16 | call to append | string.cpp:466:18:466:23 | call to source | -| string.cpp:475:8:475:9 | s4 | string.cpp:466:18:466:23 | call to source | -| string.cpp:487:10:487:15 | call to assign | string.cpp:482:18:482:23 | call to source | -| string.cpp:488:8:488:8 | h | string.cpp:482:18:482:23 | call to source | -| string.cpp:491:8:491:9 | s6 | string.cpp:482:18:482:23 | call to source | -| string.cpp:504:7:504:8 | s2 | string.cpp:497:14:497:19 | call to source | -| string.cpp:506:7:506:8 | s4 | string.cpp:497:14:497:19 | call to source | -| string.cpp:515:9:515:13 | call to front | string.cpp:514:14:514:28 | call to source | -| string.cpp:516:9:516:12 | call to back | string.cpp:514:14:514:28 | call to source | -| string.cpp:529:11:529:11 | call to operator+= | string.cpp:529:20:529:25 | call to source | -| string.cpp:530:21:530:21 | call to operator+= | string.cpp:530:24:530:29 | call to source | -| string.cpp:531:25:531:25 | call to operator+= | string.cpp:531:15:531:20 | call to source | -| string.cpp:534:8:534:8 | c | string.cpp:529:20:529:25 | call to source | -| string.cpp:535:8:535:8 | d | string.cpp:529:20:529:25 | call to source | -| string.cpp:536:8:536:8 | e | string.cpp:530:24:530:29 | call to source | -| string.cpp:537:8:537:8 | f | string.cpp:531:15:531:20 | call to source | -| string.cpp:549:11:549:16 | call to assign | string.cpp:549:27:549:32 | call to source | -| string.cpp:550:24:550:29 | call to assign | string.cpp:550:31:550:36 | call to source | -| string.cpp:554:8:554:8 | c | string.cpp:549:27:549:32 | call to source | -| string.cpp:555:8:555:8 | d | string.cpp:549:27:549:32 | call to source | -| string.cpp:556:8:556:8 | e | string.cpp:550:31:550:36 | call to source | -| string.cpp:557:8:557:8 | f | string.cpp:551:18:551:23 | call to source | +| string.cpp:29:7:29:7 | a | string.cpp:25:12:25:17 | call to source | +| string.cpp:31:7:31:7 | c | string.cpp:27:16:27:21 | call to source | +| string.cpp:33:9:33:13 | call to c_str | string.cpp:27:16:27:21 | call to source | +| string.cpp:39:13:39:17 | call to c_str | string.cpp:14:10:14:15 | call to source | +| string.cpp:43:13:43:17 | call to c_str | string.cpp:14:10:14:15 | call to source | +| string.cpp:46:13:46:17 | call to c_str | string.cpp:14:10:14:15 | call to source | +| string.cpp:56:7:56:8 | cs | string.cpp:51:19:51:24 | call to source | +| string.cpp:57:7:57:8 | ss | string.cpp:51:19:51:24 | call to source | +| string.cpp:70:7:70:8 | cs | string.cpp:62:19:62:24 | call to source | +| string.cpp:71:7:71:8 | ss | string.cpp:62:19:62:24 | call to source | +| string.cpp:93:8:93:9 | s1 | string.cpp:88:18:88:23 | call to source | +| string.cpp:94:8:94:9 | s2 | string.cpp:89:20:89:25 | call to source | +| string.cpp:95:8:95:9 | s3 | string.cpp:91:8:91:13 | call to source | +| string.cpp:114:8:114:9 | s1 | string.cpp:110:32:110:37 | call to source | +| string.cpp:115:8:115:9 | s2 | string.cpp:112:20:112:25 | call to source | +| string.cpp:122:8:122:8 | c | string.cpp:120:16:120:21 | call to source | +| string.cpp:126:8:126:8 | call to operator* | string.cpp:120:16:120:21 | call to source | +| string.cpp:130:8:130:8 | c | string.cpp:120:16:120:21 | call to source | +| string.cpp:135:8:135:8 | c | string.cpp:133:28:133:33 | call to source | +| string.cpp:145:11:145:11 | call to operator+ | string.cpp:142:18:142:23 | call to source | +| string.cpp:146:11:146:11 | call to operator+ | string.cpp:142:18:142:23 | call to source | +| string.cpp:147:11:147:11 | call to operator+ | string.cpp:142:18:142:23 | call to source | +| string.cpp:150:11:150:11 | call to operator+ | string.cpp:150:13:150:18 | call to source | +| string.cpp:159:8:159:9 | s5 | string.cpp:155:18:155:23 | call to source | +| string.cpp:162:11:162:11 | call to operator+= | string.cpp:155:18:155:23 | call to source | +| string.cpp:163:8:163:9 | s6 | string.cpp:155:18:155:23 | call to source | +| string.cpp:166:11:166:11 | call to operator+= | string.cpp:166:14:166:19 | call to source | +| string.cpp:167:11:167:11 | call to operator+= | string.cpp:166:14:166:19 | call to source | +| string.cpp:168:8:168:9 | s7 | string.cpp:166:14:166:19 | call to source | +| string.cpp:172:8:172:9 | s8 | string.cpp:155:18:155:23 | call to source | +| string.cpp:177:8:177:9 | s9 | string.cpp:175:13:175:18 | call to source | +| string.cpp:185:8:185:10 | s10 | string.cpp:182:12:182:26 | call to source | +| string.cpp:199:10:199:15 | call to assign | string.cpp:191:17:191:22 | call to source | +| string.cpp:200:7:200:8 | s4 | string.cpp:191:17:191:22 | call to source | +| string.cpp:202:10:202:15 | call to assign | string.cpp:192:11:192:25 | call to source | +| string.cpp:203:7:203:8 | s5 | string.cpp:192:11:192:25 | call to source | +| string.cpp:206:7:206:8 | s6 | string.cpp:194:17:194:22 | call to source | +| string.cpp:220:10:220:15 | call to insert | string.cpp:211:17:211:22 | call to source | +| string.cpp:221:7:221:8 | s4 | string.cpp:211:17:211:22 | call to source | +| string.cpp:224:10:224:15 | call to insert | string.cpp:211:17:211:22 | call to source | +| string.cpp:225:7:225:8 | s5 | string.cpp:211:17:211:22 | call to source | +| string.cpp:228:10:228:15 | call to insert | string.cpp:212:11:212:25 | call to source | +| string.cpp:229:7:229:8 | s6 | string.cpp:212:11:212:25 | call to source | +| string.cpp:243:10:243:16 | call to replace | string.cpp:234:17:234:22 | call to source | +| string.cpp:244:7:244:8 | s4 | string.cpp:234:17:234:22 | call to source | +| string.cpp:247:10:247:16 | call to replace | string.cpp:234:17:234:22 | call to source | +| string.cpp:248:7:248:8 | s5 | string.cpp:234:17:234:22 | call to source | +| string.cpp:251:10:251:16 | call to replace | string.cpp:235:11:235:25 | call to source | +| string.cpp:252:7:252:8 | s6 | string.cpp:235:11:235:25 | call to source | +| string.cpp:265:7:265:8 | b2 | string.cpp:259:17:259:22 | call to source | +| string.cpp:275:7:275:8 | s2 | string.cpp:270:17:270:22 | call to source | +| string.cpp:277:7:277:8 | s4 | string.cpp:272:17:272:22 | call to source | +| string.cpp:282:7:282:8 | s1 | string.cpp:270:17:270:22 | call to source | +| string.cpp:283:7:283:8 | s2 | string.cpp:270:17:270:22 | call to source | +| string.cpp:284:7:284:8 | s3 | string.cpp:272:17:272:22 | call to source | +| string.cpp:285:7:285:8 | s4 | string.cpp:272:17:272:22 | call to source | +| string.cpp:293:7:293:8 | s1 | string.cpp:289:17:289:22 | call to source | +| string.cpp:294:7:294:8 | s2 | string.cpp:290:17:290:22 | call to source | +| string.cpp:295:7:295:8 | s3 | string.cpp:291:17:291:22 | call to source | +| string.cpp:301:7:301:8 | s1 | string.cpp:289:17:289:22 | call to source | +| string.cpp:303:7:303:8 | s3 | string.cpp:291:17:291:22 | call to source | +| string.cpp:312:9:312:12 | call to data | string.cpp:309:16:309:21 | call to source | +| string.cpp:323:9:323:14 | call to substr | string.cpp:320:16:320:21 | call to source | +| string.cpp:340:7:340:7 | a | string.cpp:336:9:336:23 | call to source | +| string.cpp:341:7:341:7 | b | string.cpp:337:12:337:26 | call to source | +| string.cpp:342:7:342:7 | c | string.cpp:336:9:336:23 | call to source | +| string.cpp:350:7:350:9 | str | string.cpp:349:18:349:32 | call to source | +| string.cpp:351:11:351:14 | call to data | string.cpp:349:18:349:32 | call to source | +| string.cpp:363:11:363:16 | call to append | string.cpp:358:18:358:23 | call to source | +| string.cpp:364:8:364:9 | s1 | string.cpp:358:18:358:23 | call to source | +| string.cpp:382:8:382:8 | call to operator* | string.cpp:374:18:374:23 | call to source | +| string.cpp:383:13:383:13 | call to operator[] | string.cpp:374:18:374:23 | call to source | +| string.cpp:396:8:396:8 | call to operator* | string.cpp:389:18:389:23 | call to source | +| string.cpp:397:8:397:8 | call to operator* | string.cpp:389:18:389:23 | call to source | +| string.cpp:399:8:399:8 | call to operator* | string.cpp:389:18:389:23 | call to source | +| string.cpp:401:8:401:8 | call to operator* | string.cpp:389:18:389:23 | call to source | +| string.cpp:404:8:404:8 | call to operator* | string.cpp:389:18:389:23 | call to source | +| string.cpp:407:8:407:8 | call to operator* | string.cpp:389:18:389:23 | call to source | +| string.cpp:409:8:409:8 | call to operator* | string.cpp:389:18:389:23 | call to source | +| string.cpp:411:8:411:8 | call to operator* | string.cpp:389:18:389:23 | call to source | +| string.cpp:415:8:415:8 | call to operator* | string.cpp:389:18:389:23 | call to source | +| string.cpp:436:10:436:15 | call to insert | string.cpp:431:14:431:19 | call to source | +| string.cpp:437:7:437:8 | s2 | string.cpp:431:14:431:19 | call to source | +| string.cpp:449:10:449:15 | call to insert | string.cpp:449:32:449:46 | call to source | +| string.cpp:450:8:450:8 | b | string.cpp:449:32:449:46 | call to source | +| string.cpp:462:10:462:15 | call to insert | string.cpp:457:18:457:23 | call to source | +| string.cpp:463:8:463:8 | d | string.cpp:457:18:457:23 | call to source | +| string.cpp:465:11:465:16 | call to insert | string.cpp:457:18:457:23 | call to source | +| string.cpp:466:8:466:9 | s2 | string.cpp:457:18:457:23 | call to source | +| string.cpp:478:10:478:15 | call to append | string.cpp:473:18:473:23 | call to source | +| string.cpp:479:8:479:8 | f | string.cpp:473:18:473:23 | call to source | +| string.cpp:481:11:481:16 | call to append | string.cpp:473:18:473:23 | call to source | +| string.cpp:482:8:482:9 | s4 | string.cpp:473:18:473:23 | call to source | +| string.cpp:494:10:494:15 | call to assign | string.cpp:489:18:489:23 | call to source | +| string.cpp:495:8:495:8 | h | string.cpp:489:18:489:23 | call to source | +| string.cpp:498:8:498:9 | s6 | string.cpp:489:18:489:23 | call to source | +| string.cpp:511:7:511:8 | s2 | string.cpp:504:14:504:19 | call to source | +| string.cpp:513:7:513:8 | s4 | string.cpp:504:14:504:19 | call to source | +| string.cpp:522:9:522:13 | call to front | string.cpp:521:14:521:28 | call to source | +| string.cpp:523:9:523:12 | call to back | string.cpp:521:14:521:28 | call to source | +| string.cpp:536:11:536:11 | call to operator+= | string.cpp:536:20:536:25 | call to source | +| string.cpp:537:21:537:21 | call to operator+= | string.cpp:537:24:537:29 | call to source | +| string.cpp:538:25:538:25 | call to operator+= | string.cpp:538:15:538:20 | call to source | +| string.cpp:541:8:541:8 | c | string.cpp:536:20:536:25 | call to source | +| string.cpp:542:8:542:8 | d | string.cpp:536:20:536:25 | call to source | +| string.cpp:543:8:543:8 | e | string.cpp:537:24:537:29 | call to source | +| string.cpp:544:8:544:8 | f | string.cpp:538:15:538:20 | call to source | +| string.cpp:556:11:556:16 | call to assign | string.cpp:556:27:556:32 | call to source | +| string.cpp:557:24:557:29 | call to assign | string.cpp:557:31:557:36 | call to source | +| string.cpp:561:8:561:8 | c | string.cpp:556:27:556:32 | call to source | +| string.cpp:562:8:562:8 | d | string.cpp:556:27:556:32 | call to source | +| string.cpp:563:8:563:8 | e | string.cpp:557:31:557:36 | call to source | +| string.cpp:564:8:564:8 | f | string.cpp:558:18:558:23 | call to source | | stringstream.cpp:32:11:32:11 | call to operator<< | stringstream.cpp:32:14:32:19 | call to source | | stringstream.cpp:33:20:33:20 | call to operator<< | stringstream.cpp:33:23:33:28 | call to source | | stringstream.cpp:34:23:34:23 | call to operator<< | stringstream.cpp:34:14:34:19 | 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 e5ee0437639..12ed84c7cb4 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 @@ -25,59 +25,59 @@ | standalone_iterators.cpp:42:10:42:10 | standalone_iterators.cpp:39:45:39:51 | AST only | | standalone_iterators.cpp:47:10:47:10 | standalone_iterators.cpp:45:39:45:45 | AST only | | standalone_iterators.cpp:48:10:48:10 | standalone_iterators.cpp:45:39:45:45 | AST only | -| string.cpp:32:9:32:13 | string.cpp:26:16:26:21 | AST only | -| string.cpp:38:13:38:17 | string.cpp:14:10:14:15 | AST only | -| string.cpp:42:13:42:17 | string.cpp:14:10:14:15 | AST only | -| string.cpp:45:13:45:17 | string.cpp:14:10:14:15 | AST only | -| string.cpp:69:7:69:8 | string.cpp:61:19:61:24 | AST only | -| string.cpp:125:8:125:11 | string.cpp:119:16:119:21 | IR only | -| string.cpp:161:11:161:11 | string.cpp:154:18:154:23 | AST only | -| string.cpp:165:11:165:11 | string.cpp:165:14:165:19 | AST only | -| string.cpp:166:11:166:11 | string.cpp:165:14:165:19 | AST only | -| string.cpp:198:10:198:15 | string.cpp:190:17:190:22 | AST only | -| string.cpp:201:10:201:15 | string.cpp:191:11:191:25 | AST only | -| string.cpp:219:10:219:15 | string.cpp:210:17:210:22 | AST only | -| string.cpp:223:10:223:15 | string.cpp:210:17:210:22 | AST only | -| string.cpp:227:10:227:15 | string.cpp:211:11:211:25 | AST only | -| string.cpp:242:10:242:16 | string.cpp:233:17:233:22 | AST only | -| string.cpp:246:10:246:16 | string.cpp:233:17:233:22 | AST only | -| string.cpp:250:10:250:16 | string.cpp:234:11:234:25 | AST only | -| string.cpp:311:9:311:12 | string.cpp:308:16:308:21 | AST only | -| string.cpp:339:7:339:7 | string.cpp:335:9:335:23 | AST only | -| string.cpp:340:7:340:7 | string.cpp:336:12:336:26 | AST only | -| string.cpp:341:7:341:7 | string.cpp:335:9:335:23 | AST only | -| string.cpp:349:7:349:9 | string.cpp:348:18:348:32 | AST only | -| string.cpp:350:11:350:14 | string.cpp:348:18:348:32 | AST only | -| string.cpp:361:11:361:16 | string.cpp:356:18:356:23 | AST only | -| string.cpp:380:8:380:14 | string.cpp:372:18:372:23 | IR only | -| string.cpp:381:13:381:15 | string.cpp:372:18:372:23 | IR only | -| string.cpp:394:8:394:8 | string.cpp:387:18:387:23 | AST only | -| string.cpp:395:8:395:8 | string.cpp:387:18:387:23 | AST only | -| string.cpp:397:8:397:8 | string.cpp:387:18:387:23 | AST only | -| string.cpp:399:8:399:8 | string.cpp:387:18:387:23 | AST only | -| string.cpp:402:8:402:11 | string.cpp:387:18:387:23 | IR only | -| string.cpp:405:8:405:11 | string.cpp:387:18:387:23 | IR only | -| string.cpp:407:8:407:8 | string.cpp:387:18:387:23 | AST only | -| string.cpp:409:8:409:8 | string.cpp:387:18:387:23 | AST only | -| string.cpp:413:8:413:11 | string.cpp:387:18:387:23 | IR only | -| string.cpp:427:10:427:15 | string.cpp:422:14:422:19 | AST only | -| string.cpp:442:10:442:15 | string.cpp:442:32:442:46 | AST only | -| string.cpp:455:10:455:15 | string.cpp:450:18:450:23 | AST only | -| string.cpp:458:11:458:16 | string.cpp:450:18:450:23 | AST only | -| string.cpp:471:10:471:15 | string.cpp:466:18:466:23 | AST only | -| string.cpp:474:11:474:16 | string.cpp:466:18:466:23 | AST only | -| string.cpp:487:10:487:15 | string.cpp:482:18:482:23 | AST only | -| string.cpp:515:9:515:13 | string.cpp:514:14:514:28 | AST only | -| string.cpp:516:9:516:12 | string.cpp:514:14:514:28 | AST only | -| string.cpp:529:11:529:11 | string.cpp:529:20:529:25 | AST only | -| string.cpp:530:21:530:21 | string.cpp:530:24:530:29 | AST only | -| string.cpp:531:25:531:25 | string.cpp:531:15:531:20 | AST only | -| string.cpp:534:8:534:8 | string.cpp:529:20:529:25 | AST only | -| string.cpp:536:8:536:8 | string.cpp:530:24:530:29 | AST only | -| string.cpp:549:11:549:16 | string.cpp:549:27:549:32 | AST only | -| string.cpp:550:24:550:29 | string.cpp:550:31:550:36 | AST only | -| string.cpp:554:8:554:8 | string.cpp:549:27:549:32 | AST only | -| string.cpp:556:8:556:8 | string.cpp:550:31:550:36 | AST only | +| string.cpp:33:9:33:13 | string.cpp:27:16:27:21 | AST only | +| string.cpp:39:13:39:17 | string.cpp:14:10:14:15 | AST only | +| string.cpp:43:13:43:17 | string.cpp:14:10:14:15 | AST only | +| string.cpp:46:13:46:17 | string.cpp:14:10:14:15 | AST only | +| string.cpp:70:7:70:8 | string.cpp:62:19:62:24 | AST only | +| string.cpp:126:8:126:11 | string.cpp:120:16:120:21 | IR only | +| string.cpp:162:11:162:11 | string.cpp:155:18:155:23 | AST only | +| string.cpp:166:11:166:11 | string.cpp:166:14:166:19 | AST only | +| string.cpp:167:11:167:11 | string.cpp:166:14:166:19 | AST only | +| string.cpp:199:10:199:15 | string.cpp:191:17:191:22 | AST only | +| string.cpp:202:10:202:15 | string.cpp:192:11:192:25 | AST only | +| string.cpp:220:10:220:15 | string.cpp:211:17:211:22 | AST only | +| string.cpp:224:10:224:15 | string.cpp:211:17:211:22 | AST only | +| string.cpp:228:10:228:15 | string.cpp:212:11:212:25 | AST only | +| string.cpp:243:10:243:16 | string.cpp:234:17:234:22 | AST only | +| string.cpp:247:10:247:16 | string.cpp:234:17:234:22 | AST only | +| string.cpp:251:10:251:16 | string.cpp:235:11:235:25 | AST only | +| string.cpp:312:9:312:12 | string.cpp:309:16:309:21 | AST only | +| string.cpp:340:7:340:7 | string.cpp:336:9:336:23 | AST only | +| string.cpp:341:7:341:7 | string.cpp:337:12:337:26 | AST only | +| string.cpp:342:7:342:7 | string.cpp:336:9:336:23 | AST only | +| string.cpp:350:7:350:9 | string.cpp:349:18:349:32 | AST only | +| string.cpp:351:11:351:14 | string.cpp:349:18:349:32 | AST only | +| string.cpp:363:11:363:16 | string.cpp:358:18:358:23 | AST only | +| string.cpp:382:8:382:14 | string.cpp:374:18:374:23 | IR only | +| string.cpp:383:13:383:15 | string.cpp:374:18:374:23 | IR only | +| string.cpp:396:8:396:8 | string.cpp:389:18:389:23 | AST only | +| string.cpp:397:8:397:8 | string.cpp:389:18:389:23 | AST only | +| string.cpp:399:8:399:8 | string.cpp:389:18:389:23 | AST only | +| string.cpp:401:8:401:8 | string.cpp:389:18:389:23 | AST only | +| string.cpp:404:8:404:11 | string.cpp:389:18:389:23 | IR only | +| string.cpp:407:8:407:11 | string.cpp:389:18:389:23 | IR only | +| string.cpp:409:8:409:8 | string.cpp:389:18:389:23 | AST only | +| string.cpp:411:8:411:8 | string.cpp:389:18:389:23 | AST only | +| string.cpp:415:8:415:11 | string.cpp:389:18:389:23 | IR only | +| string.cpp:436:10:436:15 | string.cpp:431:14:431:19 | AST only | +| string.cpp:449:10:449:15 | string.cpp:449:32:449:46 | AST only | +| string.cpp:462:10:462:15 | string.cpp:457:18:457:23 | AST only | +| string.cpp:465:11:465:16 | string.cpp:457:18:457:23 | AST only | +| string.cpp:478:10:478:15 | string.cpp:473:18:473:23 | AST only | +| string.cpp:481:11:481:16 | string.cpp:473:18:473:23 | AST only | +| string.cpp:494:10:494:15 | string.cpp:489:18:489:23 | AST only | +| string.cpp:522:9:522:13 | string.cpp:521:14:521:28 | AST only | +| string.cpp:523:9:523:12 | string.cpp:521:14:521:28 | AST only | +| string.cpp:536:11:536:11 | string.cpp:536:20:536:25 | AST only | +| string.cpp:537:21:537:21 | string.cpp:537:24:537:29 | AST only | +| string.cpp:538:25:538:25 | string.cpp:538:15:538:20 | AST only | +| string.cpp:541:8:541:8 | string.cpp:536:20:536:25 | AST only | +| string.cpp:543:8:543:8 | string.cpp:537:24:537:29 | AST only | +| string.cpp:556:11:556:16 | string.cpp:556:27:556:32 | AST only | +| string.cpp:557:24:557:29 | string.cpp:557:31:557:36 | AST only | +| string.cpp:561:8:561:8 | string.cpp:556:27:556:32 | AST only | +| string.cpp:563:8:563:8 | string.cpp:557:31:557:36 | AST only | | stringstream.cpp:32:11:32:22 | stringstream.cpp:32:14:32:19 | IR only | | stringstream.cpp:33:20:33:31 | stringstream.cpp:33:23:33:28 | IR only | | stringstream.cpp:34:23:34:31 | stringstream.cpp:34:14:34:19 | IR 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 07aa8b78d1d..dbf4a629988 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 @@ -55,80 +55,80 @@ | smart_pointer.cpp:57:12:57:14 | call to get | smart_pointer.cpp:56:52:56:57 | call to source | | standalone_iterators.cpp:40:10:40:10 | call to operator* | standalone_iterators.cpp:39:45:39:51 | source1 | | standalone_iterators.cpp:46:10:46:10 | call to operator* | standalone_iterators.cpp:45:39:45:45 | source1 | -| string.cpp:28:7:28:7 | a | string.cpp:24:12:24:17 | call to source | -| string.cpp:30:7:30:7 | Argument 0 indirection | string.cpp:26:16:26:21 | call to source | -| string.cpp:55:7:55:8 | cs | string.cpp:50:19:50:24 | call to source | -| string.cpp:56:7:56:8 | Argument 0 indirection | string.cpp:50:19:50:24 | call to source | -| string.cpp:70:7:70:8 | Argument 0 indirection | string.cpp:61:19:61:24 | call to source | -| string.cpp:92:8:92:9 | Argument 0 indirection | string.cpp:87:18:87:23 | call to source | -| string.cpp:93:8:93:9 | Argument 0 indirection | string.cpp:88:20:88:25 | call to source | -| string.cpp:94:8:94:9 | Argument 0 indirection | string.cpp:90:8:90:13 | call to source | -| string.cpp:113:8:113:9 | Argument 0 indirection | string.cpp:109:32:109:37 | call to source | -| string.cpp:114:8:114:9 | Argument 0 indirection | string.cpp:111:20:111:25 | call to source | -| string.cpp:121:8:121:8 | c | string.cpp:119:16:119:21 | call to source | -| string.cpp:125:8:125:8 | call to operator* | string.cpp:119:16:119:21 | call to source | -| string.cpp:125:8:125:11 | (reference dereference) | string.cpp:119:16:119:21 | call to source | -| string.cpp:129:8:129:8 | (reference dereference) | string.cpp:119:16:119:21 | call to source | -| string.cpp:129:8:129:8 | c | string.cpp:119:16:119:21 | call to source | -| string.cpp:134:8:134:8 | (reference dereference) | string.cpp:132:28:132:33 | call to source | -| string.cpp:134:8:134:8 | c | string.cpp:132:28:132:33 | call to source | -| string.cpp:144:11:144:11 | call to operator+ | string.cpp:141:18:141:23 | call to source | -| string.cpp:145:11:145:11 | call to operator+ | string.cpp:141:18:141:23 | call to source | -| string.cpp:146:11:146:11 | call to operator+ | string.cpp:141:18:141:23 | call to source | -| string.cpp:149:11:149:11 | call to operator+ | string.cpp:149:13:149:18 | call to source | -| string.cpp:158:8:158:9 | Argument 0 indirection | string.cpp:154:18:154:23 | call to source | -| string.cpp:162:8:162:9 | Argument 0 indirection | string.cpp:154:18:154:23 | call to source | -| string.cpp:167:8:167:9 | Argument 0 indirection | string.cpp:165:14:165:19 | call to source | -| string.cpp:171:8:171:9 | Argument 0 indirection | string.cpp:154:18:154:23 | call to source | -| string.cpp:176:8:176:9 | Argument 0 indirection | string.cpp:174:13:174:18 | call to source | -| string.cpp:184:8:184:10 | Argument 0 indirection | string.cpp:181:12:181:26 | call to source | -| string.cpp:199:7:199:8 | Argument 0 indirection | string.cpp:190:17:190:22 | call to source | -| string.cpp:202:7:202:8 | Argument 0 indirection | string.cpp:191:11:191:25 | call to source | -| string.cpp:205:7:205:8 | Argument 0 indirection | string.cpp:193:17:193:22 | call to source | -| string.cpp:220:7:220:8 | Argument 0 indirection | string.cpp:210:17:210:22 | call to source | -| string.cpp:224:7:224:8 | Argument 0 indirection | string.cpp:210:17:210:22 | call to source | -| string.cpp:228:7:228:8 | Argument 0 indirection | string.cpp:211:11:211:25 | call to source | -| string.cpp:243:7:243:8 | Argument 0 indirection | string.cpp:233:17:233:22 | call to source | -| string.cpp:247:7:247:8 | Argument 0 indirection | string.cpp:233:17:233:22 | call to source | -| string.cpp:251:7:251:8 | Argument 0 indirection | string.cpp:234:11:234:25 | call to source | -| string.cpp:264:7:264:8 | Argument 0 indirection | string.cpp:258:17:258:22 | call to source | -| string.cpp:274:7:274:8 | Argument 0 indirection | string.cpp:269:17:269:22 | call to source | -| string.cpp:276:7:276:8 | Argument 0 indirection | string.cpp:271:17:271:22 | call to source | -| string.cpp:281:7:281:8 | Argument 0 indirection | string.cpp:269:17:269:22 | call to source | -| string.cpp:282:7:282:8 | Argument 0 indirection | string.cpp:269:17:269:22 | call to source | -| string.cpp:283:7:283:8 | Argument 0 indirection | string.cpp:271:17:271:22 | call to source | -| string.cpp:284:7:284:8 | Argument 0 indirection | string.cpp:271:17:271:22 | call to source | -| string.cpp:292:7:292:8 | Argument 0 indirection | string.cpp:288:17:288:22 | call to source | +| string.cpp:29:7:29:7 | a | string.cpp:25:12:25:17 | call to source | +| string.cpp:31:7:31:7 | Argument 0 indirection | string.cpp:27:16:27:21 | call to source | +| string.cpp:56:7:56:8 | cs | string.cpp:51:19:51:24 | call to source | +| string.cpp:57:7:57:8 | Argument 0 indirection | string.cpp:51:19:51:24 | call to source | +| string.cpp:71:7:71:8 | Argument 0 indirection | string.cpp:62:19:62:24 | call to source | +| string.cpp:93:8:93:9 | Argument 0 indirection | string.cpp:88:18:88:23 | call to source | +| string.cpp:94:8:94:9 | Argument 0 indirection | string.cpp:89:20:89:25 | call to source | +| string.cpp:95:8:95:9 | Argument 0 indirection | string.cpp:91:8:91:13 | call to source | +| string.cpp:114:8:114:9 | Argument 0 indirection | string.cpp:110:32:110:37 | call to source | +| string.cpp:115:8:115:9 | Argument 0 indirection | string.cpp:112:20:112:25 | call to source | +| string.cpp:122:8:122:8 | c | string.cpp:120:16:120:21 | call to source | +| string.cpp:126:8:126:8 | call to operator* | string.cpp:120:16:120:21 | call to source | +| string.cpp:126:8:126:11 | (reference dereference) | string.cpp:120:16:120:21 | call to source | +| string.cpp:130:8:130:8 | (reference dereference) | string.cpp:120:16:120:21 | call to source | +| string.cpp:130:8:130:8 | c | string.cpp:120:16:120:21 | call to source | +| string.cpp:135:8:135:8 | (reference dereference) | string.cpp:133:28:133:33 | call to source | +| string.cpp:135:8:135:8 | c | string.cpp:133:28:133:33 | call to source | +| string.cpp:145:11:145:11 | call to operator+ | string.cpp:142:18:142:23 | call to source | +| string.cpp:146:11:146:11 | call to operator+ | string.cpp:142:18:142:23 | call to source | +| string.cpp:147:11:147:11 | call to operator+ | string.cpp:142:18:142:23 | call to source | +| string.cpp:150:11:150:11 | call to operator+ | string.cpp:150:13:150:18 | call to source | +| string.cpp:159:8:159:9 | Argument 0 indirection | string.cpp:155:18:155:23 | call to source | +| string.cpp:163:8:163:9 | Argument 0 indirection | string.cpp:155:18:155:23 | call to source | +| string.cpp:168:8:168:9 | Argument 0 indirection | string.cpp:166:14:166:19 | call to source | +| string.cpp:172:8:172:9 | Argument 0 indirection | string.cpp:155:18:155:23 | call to source | +| string.cpp:177:8:177:9 | Argument 0 indirection | string.cpp:175:13:175:18 | call to source | +| string.cpp:185:8:185:10 | Argument 0 indirection | string.cpp:182:12:182:26 | call to source | +| string.cpp:200:7:200:8 | Argument 0 indirection | string.cpp:191:17:191:22 | call to source | +| string.cpp:203:7:203:8 | Argument 0 indirection | string.cpp:192:11:192:25 | call to source | +| string.cpp:206:7:206:8 | Argument 0 indirection | string.cpp:194:17:194:22 | call to source | +| string.cpp:221:7:221:8 | Argument 0 indirection | string.cpp:211:17:211:22 | call to source | +| string.cpp:225:7:225:8 | Argument 0 indirection | string.cpp:211:17:211:22 | call to source | +| string.cpp:229:7:229:8 | Argument 0 indirection | string.cpp:212:11:212:25 | call to source | +| string.cpp:244:7:244:8 | Argument 0 indirection | string.cpp:234:17:234:22 | call to source | +| string.cpp:248:7:248:8 | Argument 0 indirection | string.cpp:234:17:234:22 | call to source | +| string.cpp:252:7:252:8 | Argument 0 indirection | string.cpp:235:11:235:25 | call to source | +| string.cpp:265:7:265:8 | Argument 0 indirection | string.cpp:259:17:259:22 | call to source | +| string.cpp:275:7:275:8 | Argument 0 indirection | string.cpp:270:17:270:22 | call to source | +| string.cpp:277:7:277:8 | Argument 0 indirection | string.cpp:272:17:272:22 | call to source | +| string.cpp:282:7:282:8 | Argument 0 indirection | string.cpp:270:17:270:22 | call to source | +| string.cpp:283:7:283:8 | Argument 0 indirection | string.cpp:270:17:270:22 | call to source | +| string.cpp:284:7:284:8 | Argument 0 indirection | string.cpp:272:17:272:22 | call to source | +| string.cpp:285:7:285:8 | Argument 0 indirection | string.cpp:272:17:272:22 | call to source | | string.cpp:293:7:293:8 | Argument 0 indirection | string.cpp:289:17:289:22 | call to source | | string.cpp:294:7:294:8 | Argument 0 indirection | string.cpp:290:17:290:22 | call to source | -| string.cpp:300:7:300:8 | Argument 0 indirection | string.cpp:288:17:288:22 | call to source | -| string.cpp:302:7:302:8 | Argument 0 indirection | string.cpp:290:17:290:22 | call to source | -| string.cpp:322:9:322:14 | call to substr | string.cpp:319:16:319:21 | call to source | -| string.cpp:362:8:362:9 | Argument 0 indirection | string.cpp:356:18:356:23 | call to source | -| string.cpp:380:8:380:8 | call to operator* | string.cpp:372:18:372:23 | call to source | -| string.cpp:380:8:380:14 | (reference dereference) | string.cpp:372:18:372:23 | call to source | -| string.cpp:381:13:381:13 | call to operator[] | string.cpp:372:18:372:23 | call to source | -| string.cpp:381:13:381:15 | (reference dereference) | string.cpp:372:18:372:23 | call to source | -| string.cpp:402:8:402:8 | call to operator* | string.cpp:387:18:387:23 | call to source | -| string.cpp:402:8:402:11 | (reference dereference) | string.cpp:387:18:387:23 | call to source | -| string.cpp:405:8:405:8 | call to operator* | string.cpp:387:18:387:23 | call to source | -| string.cpp:405:8:405:11 | (reference dereference) | string.cpp:387:18:387:23 | call to source | -| string.cpp:413:8:413:8 | call to operator* | string.cpp:387:18:387:23 | call to source | -| string.cpp:413:8:413:11 | (reference dereference) | string.cpp:387:18:387:23 | call to source | -| string.cpp:428:7:428:8 | Argument 0 indirection | string.cpp:422:14:422:19 | call to source | -| string.cpp:443:8:443:8 | Argument 0 indirection | string.cpp:442:32:442:46 | call to source | -| string.cpp:456:8:456:8 | Argument 0 indirection | string.cpp:450:18:450:23 | call to source | -| string.cpp:459:8:459:9 | Argument 0 indirection | string.cpp:450:18:450:23 | call to source | -| string.cpp:472:8:472:8 | Argument 0 indirection | string.cpp:466:18:466:23 | call to source | -| string.cpp:475:8:475:9 | Argument 0 indirection | string.cpp:466:18:466:23 | call to source | -| string.cpp:488:8:488:8 | Argument 0 indirection | string.cpp:482:18:482:23 | call to source | -| string.cpp:491:8:491:9 | Argument 0 indirection | string.cpp:482:18:482:23 | call to source | -| string.cpp:504:7:504:8 | Argument 0 indirection | string.cpp:497:14:497:19 | call to source | -| string.cpp:506:7:506:8 | Argument 0 indirection | string.cpp:497:14:497:19 | call to source | -| string.cpp:535:8:535:8 | Argument 0 indirection | string.cpp:529:20:529:25 | call to source | -| string.cpp:537:8:537:8 | Argument 0 indirection | string.cpp:531:15:531:20 | call to source | -| string.cpp:555:8:555:8 | Argument 0 indirection | string.cpp:549:27:549:32 | call to source | -| string.cpp:557:8:557:8 | Argument 0 indirection | string.cpp:551:18:551:23 | call to source | +| string.cpp:295:7:295:8 | Argument 0 indirection | string.cpp:291:17:291:22 | call to source | +| string.cpp:301:7:301:8 | Argument 0 indirection | string.cpp:289:17:289:22 | call to source | +| string.cpp:303:7:303:8 | Argument 0 indirection | string.cpp:291:17:291:22 | call to source | +| string.cpp:323:9:323:14 | call to substr | string.cpp:320:16:320:21 | call to source | +| string.cpp:364:8:364:9 | Argument 0 indirection | string.cpp:358:18:358:23 | call to source | +| string.cpp:382:8:382:8 | call to operator* | string.cpp:374:18:374:23 | call to source | +| string.cpp:382:8:382:14 | (reference dereference) | string.cpp:374:18:374:23 | call to source | +| string.cpp:383:13:383:13 | call to operator[] | string.cpp:374:18:374:23 | call to source | +| string.cpp:383:13:383:15 | (reference dereference) | string.cpp:374:18:374:23 | call to source | +| string.cpp:404:8:404:8 | call to operator* | string.cpp:389:18:389:23 | call to source | +| string.cpp:404:8:404:11 | (reference dereference) | string.cpp:389:18:389:23 | call to source | +| string.cpp:407:8:407:8 | call to operator* | string.cpp:389:18:389:23 | call to source | +| string.cpp:407:8:407:11 | (reference dereference) | string.cpp:389:18:389:23 | call to source | +| string.cpp:415:8:415:8 | call to operator* | string.cpp:389:18:389:23 | call to source | +| string.cpp:415:8:415:11 | (reference dereference) | string.cpp:389:18:389:23 | call to source | +| string.cpp:437:7:437:8 | Argument 0 indirection | string.cpp:431:14:431:19 | call to source | +| string.cpp:450:8:450:8 | Argument 0 indirection | string.cpp:449:32:449:46 | call to source | +| string.cpp:463:8:463:8 | Argument 0 indirection | string.cpp:457:18:457:23 | call to source | +| string.cpp:466:8:466:9 | Argument 0 indirection | string.cpp:457:18:457:23 | call to source | +| string.cpp:479:8:479:8 | Argument 0 indirection | string.cpp:473:18:473:23 | call to source | +| string.cpp:482:8:482:9 | Argument 0 indirection | string.cpp:473:18:473:23 | call to source | +| string.cpp:495:8:495:8 | Argument 0 indirection | string.cpp:489:18:489:23 | call to source | +| string.cpp:498:8:498:9 | Argument 0 indirection | string.cpp:489:18:489:23 | call to source | +| string.cpp:511:7:511:8 | Argument 0 indirection | string.cpp:504:14:504:19 | call to source | +| string.cpp:513:7:513:8 | Argument 0 indirection | string.cpp:504:14:504:19 | call to source | +| string.cpp:542:8:542:8 | Argument 0 indirection | string.cpp:536:20:536:25 | call to source | +| string.cpp:544:8:544:8 | Argument 0 indirection | string.cpp:538:15:538:20 | call to source | +| string.cpp:562:8:562:8 | Argument 0 indirection | string.cpp:556:27:556:32 | call to source | +| string.cpp:564:8:564:8 | Argument 0 indirection | string.cpp:558:18:558:23 | call to source | | stringstream.cpp:32:11:32:11 | call to operator<< | stringstream.cpp:32:14:32:19 | call to source | | stringstream.cpp:32:11:32:22 | (reference dereference) | stringstream.cpp:32:14:32:19 | call to source | | stringstream.cpp:33:20:33:20 | call to operator<< | stringstream.cpp:33:23:33:28 | call to source | From 8d5febf9c4c067ec4b51aa9c072ee5641af039b9 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 Oct 2020 17:26:47 +0100 Subject: [PATCH 192/411] C++: Add a couple more test cases that have been discussed. --- .../dataflow/taint-tests/localTaint.expected | 20 +++++++++++++++++++ .../dataflow/taint-tests/string.cpp | 14 ++++++------- .../dataflow/taint-tests/taint.expected | 4 ++++ .../dataflow/taint-tests/test_diff.expected | 4 ++++ 4 files changed, 35 insertions(+), 7 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 26ed3c5c3dc..ea53e5121aa 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -1020,6 +1020,8 @@ | string.cpp:393:28:393:32 | call to begin | string.cpp:405:8:405:9 | i2 | | | string.cpp:393:28:393:32 | call to begin | string.cpp:408:8:408:9 | i2 | | | string.cpp:393:28:393:32 | call to begin | string.cpp:410:8:410:9 | i2 | | +| string.cpp:393:28:393:32 | call to begin | string.cpp:417:9:417:10 | i2 | | +| string.cpp:393:28:393:32 | call to begin | string.cpp:420:9:420:10 | i2 | | | string.cpp:396:10:396:11 | i2 | string.cpp:396:12:396:12 | call to operator+ | TAINT | | string.cpp:396:10:396:11 | ref arg i2 | string.cpp:397:10:397:11 | i2 | | | string.cpp:396:10:396:11 | ref arg i2 | string.cpp:398:8:398:9 | i2 | | @@ -1028,6 +1030,8 @@ | string.cpp:396:10:396:11 | ref arg i2 | string.cpp:405:8:405:9 | i2 | | | string.cpp:396:10:396:11 | ref arg i2 | string.cpp:408:8:408:9 | i2 | | | string.cpp:396:10:396:11 | ref arg i2 | string.cpp:410:8:410:9 | i2 | | +| string.cpp:396:10:396:11 | ref arg i2 | string.cpp:417:9:417:10 | i2 | | +| string.cpp:396:10:396:11 | ref arg i2 | string.cpp:420:9:420:10 | i2 | | | string.cpp:396:12:396:12 | call to operator+ | string.cpp:396:8:396:8 | call to operator* | TAINT | | string.cpp:397:10:397:11 | i2 | string.cpp:397:12:397:12 | call to operator- | TAINT | | string.cpp:397:10:397:11 | ref arg i2 | string.cpp:398:8:398:9 | i2 | | @@ -1036,6 +1040,8 @@ | string.cpp:397:10:397:11 | ref arg i2 | string.cpp:405:8:405:9 | i2 | | | string.cpp:397:10:397:11 | ref arg i2 | string.cpp:408:8:408:9 | i2 | | | string.cpp:397:10:397:11 | ref arg i2 | string.cpp:410:8:410:9 | i2 | | +| string.cpp:397:10:397:11 | ref arg i2 | string.cpp:417:9:417:10 | i2 | | +| string.cpp:397:10:397:11 | ref arg i2 | string.cpp:420:9:420:10 | i2 | | | string.cpp:397:12:397:12 | call to operator- | string.cpp:397:8:397:8 | call to operator* | TAINT | | 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 | i3 | | @@ -1074,6 +1080,20 @@ | string.cpp:414:5:414:6 | i9 | string.cpp:414:3:414:3 | call to operator-- | | | string.cpp:414:5:414:6 | ref arg i9 | string.cpp:415:9:415:10 | i9 | | | string.cpp:415:9:415:10 | i9 | string.cpp:415:8:415:8 | call to operator* | TAINT | +| string.cpp:417:9:417:10 | i2 | string.cpp:417:3:417:10 | ... = ... | | +| string.cpp:417:9:417:10 | i2 | string.cpp:418:10:418:12 | i10 | | +| string.cpp:417:9:417:10 | i2 | string.cpp:419:8:419:10 | i10 | | +| string.cpp:418:10:418:12 | i10 | string.cpp:418:13:418:13 | call to operator++ | | +| string.cpp:418:10:418:12 | ref arg i10 | string.cpp:419:8:419:10 | i10 | | +| string.cpp:418:13:418:13 | call to operator++ | string.cpp:418:8:418:8 | call to operator* | TAINT | +| string.cpp:419:8:419:10 | i10 | string.cpp:419:8:419:10 | call to iterator | | +| string.cpp:420:9:420:10 | i2 | string.cpp:420:3:420:10 | ... = ... | | +| string.cpp:420:9:420:10 | i2 | string.cpp:421:10:421:12 | i11 | | +| string.cpp:420:9:420:10 | i2 | string.cpp:422:8:422:10 | i11 | | +| string.cpp:421:10:421:12 | i11 | string.cpp:421:13:421:13 | call to operator-- | | +| string.cpp:421:10:421:12 | ref arg i11 | string.cpp:422:8:422:10 | i11 | | +| string.cpp:421:13:421:13 | call to operator-- | string.cpp:421:8:421:8 | call to operator* | TAINT | +| string.cpp:422:8:422:10 | i11 | string.cpp:422:8:422:10 | call to iterator | | | string.cpp:428:17:428:20 | aa | string.cpp:428:17:428:21 | call to basic_string | TAINT | | string.cpp:428:17:428:21 | call to basic_string | string.cpp:433:7:433:8 | s1 | | | string.cpp:428:17:428:21 | call to basic_string | string.cpp:434:7:434:8 | s1 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp index 25d771c1818..6a0bf47e4d7 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp @@ -391,7 +391,7 @@ void test_string_iterators() { string::iterator i1 = s1.begin(); string::iterator i2 = s2.begin(); - string::iterator i3, i4, i5, i6, i7, i8, i9; + string::iterator i3, i4, i5, i6, i7, i8, i9, i10, i11; sink(*(i2+1)); //tainted sink(*(i2-1)); // tainted @@ -414,12 +414,12 @@ void test_string_iterators() { --i9; sink(*i9); // tainted - - - - - - + i10 = i2; + sink(*(i10++)); // tainted + sink(i10); // tainted + i11 = i2; + sink(*(i11--)); // tainted + sink(i11); // 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 26aa26bcb1b..fd41252b1da 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -133,6 +133,10 @@ | string.cpp:409:8:409:8 | call to operator* | string.cpp:389:18:389:23 | call to source | | string.cpp:411:8:411:8 | call to operator* | string.cpp:389:18:389:23 | call to source | | string.cpp:415:8:415:8 | call to operator* | string.cpp:389:18:389:23 | call to source | +| string.cpp:418:8:418:8 | call to operator* | string.cpp:389:18:389:23 | call to source | +| string.cpp:419:8:419:10 | call to iterator | string.cpp:389:18:389:23 | call to source | +| string.cpp:421:8:421:8 | call to operator* | string.cpp:389:18:389:23 | call to source | +| string.cpp:422:8:422:10 | call to iterator | string.cpp:389:18:389:23 | call to source | | string.cpp:436:10:436:15 | call to insert | string.cpp:431:14:431:19 | call to source | | string.cpp:437:7:437:8 | s2 | string.cpp:431:14:431:19 | call to source | | string.cpp:449:10:449:15 | call to insert | string.cpp:449:32:449:46 | 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 12ed84c7cb4..d9aa053d8e9 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 @@ -60,6 +60,10 @@ | string.cpp:409:8:409:8 | string.cpp:389:18:389:23 | AST only | | string.cpp:411:8:411:8 | string.cpp:389:18:389:23 | AST only | | string.cpp:415:8:415:11 | string.cpp:389:18:389:23 | IR only | +| string.cpp:418:8:418:8 | string.cpp:389:18:389:23 | AST only | +| string.cpp:419:8:419:10 | string.cpp:389:18:389:23 | AST only | +| string.cpp:421:8:421:8 | string.cpp:389:18:389:23 | AST only | +| string.cpp:422:8:422:10 | string.cpp:389:18:389:23 | AST only | | string.cpp:436:10:436:15 | string.cpp:431:14:431:19 | AST only | | string.cpp:449:10:449:15 | string.cpp:449:32:449:46 | AST only | | string.cpp:462:10:462:15 | string.cpp:457:18:457:23 | AST only | From 8d5bd2289bcb3c5a966b3167dfcba8d59a48da4f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 Oct 2020 16:56:37 +0100 Subject: [PATCH 193/411] C++: Remove parts of StdSequenceContainerBeginEnd in favour of BeginOrEndFunction. --- .../code/cpp/models/implementations/StdContainer.qll | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll index 7a8b3a30b76..acc10398750 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll @@ -171,17 +171,13 @@ class StdSequenceContainerAssign extends TaintFunction { } /** - * The standard container `begin` and `end` functions and their - * variants. + * The standard container `before_begin` and `cbefore_begin` functions. */ class StdSequenceContainerBeginEnd extends TaintFunction { StdSequenceContainerBeginEnd() { - this - .hasQualifiedName("std", ["array", "vector", "deque", "list"], - ["begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend"]) or this .hasQualifiedName("std", "forward_list", - ["before_begin", "begin", "end", "cbefore_begin", "cbegin", "cend"]) + ["before_begin", "cbefore_begin"]) } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { From 1efe461a98d7718d24fdb2ca7172f040002349db Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 Oct 2020 16:57:51 +0100 Subject: [PATCH 194/411] C++: Move the rest of of StdSequenceContainerBeginEnd into BeginOrEndFunction. --- .../code/cpp/models/implementations/Iterator.qll | 4 +++- .../cpp/models/implementations/StdContainer.qll | 16 ---------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll index ded937d5312..71453467d8a 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll @@ -280,7 +280,9 @@ class IteratorArrayMemberOperator extends MemberFunction, TaintFunction, Iterato */ class BeginOrEndFunction extends MemberFunction, TaintFunction { BeginOrEndFunction() { - this.hasName(["begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend"]) and + this + .hasName(["begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend", + "before_begin", "cbefore_begin"]) and this.getType().getUnspecifiedType() instanceof Iterator } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll index acc10398750..a339dadb860 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll @@ -170,22 +170,6 @@ class StdSequenceContainerAssign extends TaintFunction { } } -/** - * The standard container `before_begin` and `cbefore_begin` functions. - */ -class StdSequenceContainerBeginEnd extends TaintFunction { - StdSequenceContainerBeginEnd() { - this - .hasQualifiedName("std", "forward_list", - ["before_begin", "cbefore_begin"]) - } - - override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - input.isQualifierObject() and - output.isReturnValue() - } -} - /** * The standard container `swap` functions. */ From 3536d84bdf5e03cbed13dc3b7ddde240f97ee948 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 Oct 2020 17:57:02 +0100 Subject: [PATCH 195/411] C++: Use [, ...] syntax more widely. --- cpp/ql/src/Critical/OverflowDestination.ql | 5 +- cpp/ql/src/Critical/SizeCheck2.ql | 5 +- .../LOC-2/Rule 11/SimpleControlFlowJmp.ql | 9 +-- .../UncheckedReturnValueForTimeFunctions.ql | 18 ++---- cpp/ql/src/Microsoft/SAL.qll | 14 +---- .../CWE/CWE-121/UnterminatedVarargsCall.ql | 2 +- .../Security/CWE/CWE-676/DangerousUseOfCin.ql | 9 +-- .../CWE-676/PotentiallyDangerousFunction.ql | 7 +-- .../CWE/CWE-732/DoNotCreateWorldWritable.ql | 7 +-- .../Security/CWE/CWE-732/FilePermissions.qll | 21 ++----- cpp/ql/src/jsf/4.09 Style/AV Rule 53.ql | 2 +- cpp/ql/src/jsf/4.12 Templates/AV Rule 104.ql | 4 +- .../semmle/code/cpp/commons/Environment.qll | 2 +- cpp/ql/src/semmle/code/cpp/commons/Printf.qll | 41 +++++-------- cpp/ql/src/semmle/code/cpp/commons/Strcat.qll | 17 +++--- .../code/cpp/models/implementations/Gets.qll | 9 ++- .../implementations/IdentityFunction.qll | 9 +-- .../cpp/models/implementations/Strcpy.qll | 57 +++++++------------ .../semmle/code/cpp/security/BufferWrite.qll | 9 ++- .../semmle/code/cpp/security/FileWrite.qll | 14 +---- .../semmle/code/cpp/security/OutputWrite.qll | 5 +- .../code/cpp/security/TaintTrackingImpl.qll | 10 ++-- cpp/ql/src/semmle/uml/MagicDraw.qll | 11 +--- 23 files changed, 87 insertions(+), 200 deletions(-) diff --git a/cpp/ql/src/Critical/OverflowDestination.ql b/cpp/ql/src/Critical/OverflowDestination.ql index ad925daed62..bff3cac9326 100644 --- a/cpp/ql/src/Critical/OverflowDestination.ql +++ b/cpp/ql/src/Critical/OverflowDestination.ql @@ -23,10 +23,7 @@ import semmle.code.cpp.security.TaintTracking * ``` */ predicate sourceSized(FunctionCall fc, Expr src) { - exists(string name | - (name = "strncpy" or name = "strncat" or name = "memcpy" or name = "memmove") and - fc.getTarget().hasGlobalOrStdName(name) - ) and + fc.getTarget().hasGlobalOrStdName(["strncpy", "strncat", "memcpy", "memmove"]) and exists(Expr dest, Expr size, Variable v | fc.getArgument(0) = dest and fc.getArgument(1) = src and diff --git a/cpp/ql/src/Critical/SizeCheck2.ql b/cpp/ql/src/Critical/SizeCheck2.ql index 1b716d79d49..fc51be1b1aa 100644 --- a/cpp/ql/src/Critical/SizeCheck2.ql +++ b/cpp/ql/src/Critical/SizeCheck2.ql @@ -16,10 +16,7 @@ import cpp class Allocation extends FunctionCall { Allocation() { - exists(string name | - this.getTarget().hasGlobalOrStdName(name) and - (name = "malloc" or name = "calloc" or name = "realloc") - ) + this.getTarget().hasGlobalOrStdName(["malloc", "calloc", "realloc"]) } private string getName() { this.getTarget().hasGlobalOrStdName(result) } diff --git a/cpp/ql/src/JPL_C/LOC-2/Rule 11/SimpleControlFlowJmp.ql b/cpp/ql/src/JPL_C/LOC-2/Rule 11/SimpleControlFlowJmp.ql index 7468b6e7174..0623036a592 100644 --- a/cpp/ql/src/JPL_C/LOC-2/Rule 11/SimpleControlFlowJmp.ql +++ b/cpp/ql/src/JPL_C/LOC-2/Rule 11/SimpleControlFlowJmp.ql @@ -13,14 +13,7 @@ import cpp class ForbiddenFunction extends Function { - ForbiddenFunction() { - exists(string name | name = this.getName() | - name = "setjmp" or - name = "longjmp" or - name = "sigsetjmp" or - name = "siglongjmp" - ) - } + ForbiddenFunction() { this.getName() = ["setjmp", "longjmp", "sigsetjmp", "siglongjmp"] } } from FunctionCall call diff --git a/cpp/ql/src/Likely Bugs/Leap Year/UncheckedReturnValueForTimeFunctions.ql b/cpp/ql/src/Likely Bugs/Leap Year/UncheckedReturnValueForTimeFunctions.ql index 31af5b3ce79..ca36e6d1ce2 100644 --- a/cpp/ql/src/Likely Bugs/Leap Year/UncheckedReturnValueForTimeFunctions.ql +++ b/cpp/ql/src/Likely Bugs/Leap Year/UncheckedReturnValueForTimeFunctions.ql @@ -40,9 +40,7 @@ class DateStructModifiedFieldAccess extends LeapYearFieldAccess { */ class SafeTimeGatheringFunction extends Function { SafeTimeGatheringFunction() { - this.getQualifiedName() = "GetFileTime" or - this.getQualifiedName() = "GetSystemTime" or - this.getQualifiedName() = "NtQuerySystemTime" + this.getQualifiedName() = ["GetFileTime", "GetSystemTime", "NtQuerySystemTime"] } } @@ -51,15 +49,11 @@ class SafeTimeGatheringFunction extends Function { */ class TimeConversionFunction extends Function { TimeConversionFunction() { - this.getQualifiedName() = "FileTimeToSystemTime" or - this.getQualifiedName() = "SystemTimeToFileTime" or - this.getQualifiedName() = "SystemTimeToTzSpecificLocalTime" or - this.getQualifiedName() = "SystemTimeToTzSpecificLocalTimeEx" or - this.getQualifiedName() = "TzSpecificLocalTimeToSystemTime" or - this.getQualifiedName() = "TzSpecificLocalTimeToSystemTimeEx" or - this.getQualifiedName() = "RtlLocalTimeToSystemTime" or - this.getQualifiedName() = "RtlTimeToSecondsSince1970" or - this.getQualifiedName() = "_mkgmtime" + this.getQualifiedName() = + ["FileTimeToSystemTime", "SystemTimeToFileTime", "SystemTimeToTzSpecificLocalTime", + "SystemTimeToTzSpecificLocalTimeEx", "TzSpecificLocalTimeToSystemTime", + "TzSpecificLocalTimeToSystemTimeEx", "RtlLocalTimeToSystemTime", + "RtlTimeToSecondsSince1970", "_mkgmtime"] } } diff --git a/cpp/ql/src/Microsoft/SAL.qll b/cpp/ql/src/Microsoft/SAL.qll index b5185b3c908..46fedbb5d80 100644 --- a/cpp/ql/src/Microsoft/SAL.qll +++ b/cpp/ql/src/Microsoft/SAL.qll @@ -10,13 +10,8 @@ import cpp */ class SALMacro extends Macro { SALMacro() { - exists(string filename | filename = this.getFile().getBaseName() | - filename = "sal.h" or - filename = "specstrings_strict.h" or - filename = "specstrings.h" or - filename = "w32p.h" or - filename = "minwindef.h" - ) and + this.getFile().getBaseName() = + ["sal.h", "specstrings_strict.h", "specstrings.h", "w32p.h", "minwindef.h"] and ( // Dialect for Windows 8 and above this.getName().matches("\\_%\\_") @@ -58,10 +53,7 @@ class SALAnnotation extends MacroInvocation { */ class SALCheckReturn extends SALAnnotation { SALCheckReturn() { - exists(SALMacro m | m = this.getMacro() | - m.getName() = "_Check_return_" or - m.getName() = "_Must_inspect_result_" - ) + this.getMacro().(SALMacro).getName() = ["_Check_return_", "_Must_inspect_result_"] } } diff --git a/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql b/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql index 473f0f72f12..bfb3a2fbb81 100644 --- a/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql +++ b/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql @@ -56,7 +56,7 @@ class VarargsFunction extends Function { } string normalTerminator(int cnt) { - (result = "0" or result = "-1") and + result = ["0", "-1"] and cnt = trailingArgValueCount(result) and 2 * cnt > totalCount() and not exists(FunctionCall fc, int index | diff --git a/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql b/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql index fc47d04c2c5..367c6ac7700 100644 --- a/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql +++ b/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql @@ -66,19 +66,14 @@ class IFStream extends Type { */ class CinVariable extends NamespaceVariable { CinVariable() { - ( - getName() = "cin" or - getName() = "wcin" - ) and - getNamespace().getName() = "std" + this.hasQualifiedName("std", ["cin", "wcin"]) } } /** A call to `std::operator>>`. */ class OperatorRShiftCall extends FunctionCall { OperatorRShiftCall() { - getTarget().getNamespace().getName() = "std" and - getTarget().hasName("operator>>") + getTarget().hasQualifiedName("std", "operator>>") } /* diff --git a/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql b/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql index 71601ec2181..4316fe229b2 100644 --- a/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql +++ b/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql @@ -14,12 +14,7 @@ import cpp predicate potentiallyDangerousFunction(Function f, string message) { exists(string name | f.hasGlobalName(name) | - ( - name = "gmtime" or - name = "localtime" or - name = "ctime" or - name = "asctime" - ) and + name = ["gmtime", "localtime", "ctime", "asctime"] and message = "Call to " + name + " is potentially dangerous" ) } diff --git a/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.ql b/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.ql index 269e7e33b59..95790298347 100644 --- a/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.ql +++ b/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.ql @@ -19,12 +19,7 @@ predicate worldWritableCreation(FileCreationExpr fc, int mode) { } predicate setWorldWritable(FunctionCall fc, int mode) { - exists(string name | fc.getTarget().getName() = name | - name = "chmod" or - name = "fchmod" or - name = "_chmod" or - name = "_wchmod" - ) and + fc.getTarget().getName() = ["chmod", "fchmod", "_chmod", "_wchmod"] and mode = fc.getArgument(1).getValue().toInt() and sets(mode, s_iwoth()) } diff --git a/cpp/ql/src/Security/CWE/CWE-732/FilePermissions.qll b/cpp/ql/src/Security/CWE/CWE-732/FilePermissions.qll index bb9c5b12f98..d62f3e6a6da 100644 --- a/cpp/ql/src/Security/CWE/CWE-732/FilePermissions.qll +++ b/cpp/ql/src/Security/CWE/CWE-732/FilePermissions.qll @@ -31,11 +31,7 @@ predicate sets(int mask, int fields) { mask.bitAnd(fields) != 0 } * one of the `umask` family of functions. */ private int umask(FunctionCall fc) { - exists(string name | name = fc.getTarget().getName() | - name = "umask" or - name = "_umask" or - name = "_umask_s" - ) and + fc.getTarget().getName() = ["umask", "_umask", "_umask_s"] and result = fc.getArgument(0).getValue().toInt() } @@ -89,11 +85,7 @@ abstract class FileCreationExpr extends FunctionCall { class OpenCreationExpr extends FileCreationExpr { OpenCreationExpr() { - exists(string name | name = this.getTarget().getName() | - name = "open" or - name = "_open" or - name = "_wopen" - ) and + this.getTarget().getName() = ["open", "_open", "_wopen"] and sets(this.getArgument(1).getValue().toInt(), o_creat()) } @@ -134,14 +126,9 @@ private int fopenMode() { class FopenCreationExpr extends FileCreationExpr { FopenCreationExpr() { - exists(string name | name = this.getTarget().getName() | - name = "fopen" or - name = "_wfopen" or - name = "fsopen" or - name = "_wfsopen" - ) and + this.getTarget().getName() = ["fopen", "_wfopen", "fsopen", "_wfsopen"] and exists(string mode | - (mode = "w" or mode = "a") and + mode = ["w", "a"] and this.getArgument(1).getValue().matches(mode + "%") ) } diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 53.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 53.ql index db8ad52e1f3..a01e0c16bd4 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 53.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 53.ql @@ -18,6 +18,6 @@ import cpp from File f where - (f.getExtension().toLowerCase() = "h" or f.getExtension().toLowerCase() = "hpp") and + f.getExtension().toLowerCase() = ["h", "hpp"] and f.getExtension() != "h" select f, "AV Rule 53: Header files will always have a file name extension of .h." diff --git a/cpp/ql/src/jsf/4.12 Templates/AV Rule 104.ql b/cpp/ql/src/jsf/4.12 Templates/AV Rule 104.ql index bc1ebf8c1d9..0a608f1dbe9 100644 --- a/cpp/ql/src/jsf/4.12 Templates/AV Rule 104.ql +++ b/cpp/ql/src/jsf/4.12 Templates/AV Rule 104.ql @@ -21,8 +21,8 @@ import cpp */ class WarningLateTemplateSpecialization extends CompilerWarning { WarningLateTemplateSpecialization() { - this.getTag() = "partial_spec_after_instantiation" or - this.getTag() = "partial_spec_after_instantiation_ambiguous" + this.getTag() = + ["partial_spec_after_instantiation", "partial_spec_after_instantiation_ambiguous"] } } diff --git a/cpp/ql/src/semmle/code/cpp/commons/Environment.qll b/cpp/ql/src/semmle/code/cpp/commons/Environment.qll index f3f1759dd5c..3da19977f33 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Environment.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Environment.qll @@ -29,7 +29,7 @@ private predicate readsEnvironment(Expr read, string sourceDescription) { exists(FunctionCall call, string name | read = call and call.getTarget().hasGlobalOrStdName(name) and - (name = "getenv" or name = "secure_getenv" or name = "_wgetenv") and + name = ["getenv", "secure_getenv", "_wgetenv"] and sourceDescription = name ) } diff --git a/cpp/ql/src/semmle/code/cpp/commons/Printf.qll b/cpp/ql/src/semmle/code/cpp/commons/Printf.qll index 55cfd1c59ce..e441dd66adc 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Printf.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Printf.qll @@ -9,10 +9,7 @@ import semmle.code.cpp.models.interfaces.FormattingFunction import semmle.code.cpp.models.implementations.Printf class PrintfFormatAttribute extends FormatAttribute { - PrintfFormatAttribute() { - getArchetype() = "printf" or - getArchetype() = "__printf__" - } + PrintfFormatAttribute() { getArchetype() = ["printf", "__printf__"] } } /** @@ -601,12 +598,12 @@ class FormatLiteral extends Literal { or len = "l" and result = this.getLongType() or - (len = "ll" or len = "L" or len = "q") and + len = ["ll", "L", "q"] and result instanceof LongLongType or len = "j" and result = this.getIntmax_t() or - (len = "z" or len = "Z") and + len = ["z", "Z"] and (result = this.getSize_t() or result = this.getSsize_t()) or len = "t" and result = this.getPtrdiff_t() @@ -639,12 +636,12 @@ class FormatLiteral extends Literal { or len = "l" and result = this.getLongType() or - (len = "ll" or len = "L" or len = "q") and + len = ["ll", "L", "q"] and result instanceof LongLongType or len = "j" and result = this.getIntmax_t() or - (len = "z" or len = "Z") and + len = ["z", "Z"] and (result = this.getSize_t() or result = this.getSsize_t()) or len = "t" and result = this.getPtrdiff_t() @@ -670,9 +667,7 @@ class FormatLiteral extends Literal { FloatingPointType getFloatingPointConversion(int n) { exists(string len | len = this.getLength(n) and - if len = "L" or len = "ll" - then result instanceof LongDoubleType - else result instanceof DoubleType + if len = ["L", "ll"] then result instanceof LongDoubleType else result instanceof DoubleType ) } @@ -689,7 +684,7 @@ class FormatLiteral extends Literal { or len = "l" and base = this.getLongType() or - (len = "ll" or len = "L") and + len = ["ll", "L"] and base instanceof LongLongType or len = "q" and base instanceof LongLongType @@ -736,12 +731,12 @@ class FormatLiteral extends Literal { exists(string len, string conv | this.parseConvSpec(n, _, _, _, _, _, len, conv) and ( - (conv = "c" or conv = "C") and + conv = ["c", "C"] and len = "h" and result instanceof PlainCharType or - (conv = "c" or conv = "C") and - (len = "l" or len = "w") and + conv = ["c", "C"] and + len = ["l", "w"] and result = getWideCharType() or conv = "c" and @@ -781,12 +776,12 @@ class FormatLiteral extends Literal { exists(string len, string conv | this.parseConvSpec(n, _, _, _, _, _, len, conv) and ( - (conv = "s" or conv = "S") and + conv = ["s", "S"] and len = "h" and result.(PointerType).getBaseType() instanceof PlainCharType or - (conv = "s" or conv = "S") and - (len = "l" or len = "w") and + conv = ["s", "S"] and + len = ["l", "w"] and result.(PointerType).getBaseType() = getWideCharType() or conv = "s" and @@ -823,10 +818,7 @@ class FormatLiteral extends Literal { private Type getConversionType9(int n) { this.getConversionChar(n) = "Z" and - ( - this.getLength(n) = "l" or - this.getLength(n) = "w" - ) and + this.getLength(n) = ["l", "w"] and exists(Type t | t.getName() = "UNICODE_STRING" and result.(PointerType).getBaseType() = t @@ -979,10 +971,7 @@ class FormatLiteral extends Literal { len = (afterdot.maximum(1) + 6).maximum(1 + 1 + dot + afterdot + 1 + 1 + 3) ) // (e.g. "-1.59203e-319") or - ( - this.getConversionChar(n).toLowerCase() = "d" or - this.getConversionChar(n).toLowerCase() = "i" - ) and + this.getConversionChar(n).toLowerCase() = ["d", "i"] and // e.g. -2^31 = "-2147483648" exists(int sizeBits | sizeBits = diff --git a/cpp/ql/src/semmle/code/cpp/commons/Strcat.qll b/cpp/ql/src/semmle/code/cpp/commons/Strcat.qll index dce086bdd4b..5226f9876fe 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Strcat.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Strcat.qll @@ -8,14 +8,13 @@ import cpp */ class StrcatFunction extends Function { StrcatFunction() { - exists(string name | name = getName() | - name = "strcat" or // strcat(dst, src) - name = "strncat" or // strncat(dst, src, max_amount) - name = "wcscat" or // wcscat(dst, src) - name = "_mbscat" or // _mbscat(dst, src) - name = "wcsncat" or // wcsncat(dst, src, max_amount) - name = "_mbsncat" or // _mbsncat(dst, src, max_amount) - name = "_mbsncat_l" // _mbsncat_l(dst, src, max_amount, locale) - ) + // strcat(dst, src) + // strncat(dst, src, max_amount) + // wcscat(dst, src) + // _mbscat(dst, src) + // wcsncat(dst, src, max_amount) + // _mbsncat(dst, src, max_amount) + // _mbsncat_l(dst, src, max_amount, locale) + getName() = ["strcat", "strncat", "wcscat", "_mbscat", "wcsncat", "_mbsncat", "_mbsncat_l"] } } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Gets.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Gets.qll index d3c8d2a7f6f..d22f2f37680 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Gets.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Gets.qll @@ -16,11 +16,10 @@ import semmle.code.cpp.models.interfaces.FlowSource class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction, SideEffectFunction, RemoteFlowFunction { GetsFunction() { - exists(string name | hasGlobalOrStdName(name) | - name = "gets" or // gets(str) - name = "fgets" or // fgets(str, num, stream) - name = "fgetws" // fgetws(wstr, num, stream) - ) + // gets(str) + // fgets(str, num, stream) + // fgetws(wstr, num, stream) + hasGlobalOrStdName(["gets", "fgets", "fgetws"]) } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/IdentityFunction.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/IdentityFunction.qll index 865a74b5571..decce4dce70 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/IdentityFunction.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/IdentityFunction.qll @@ -4,16 +4,11 @@ import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.SideEffect /** - * The standard function templates `std::move` and `std::identity` + * The standard function templates `std::move` and `std::forward`. */ class IdentityFunction extends DataFlowFunction, SideEffectFunction, AliasFunction { IdentityFunction() { - this.getNamespace().getParentNamespace() instanceof GlobalNamespace and - this.getNamespace().getName() = "std" and - ( - this.getName() = "move" or - this.getName() = "forward" - ) + this.hasQualifiedName("std", ["move", "forward"]) } override predicate hasOnlySpecificReadSideEffects() { any() } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll index 9a15b823041..8de648d91b3 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll @@ -13,43 +13,26 @@ import semmle.code.cpp.models.interfaces.SideEffect */ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction { StrcpyFunction() { - exists(string name | name = getName() | - // strcpy(dst, src) - name = "strcpy" - or - // wcscpy(dst, src) - name = "wcscpy" - or - // _mbscpy(dst, src) - name = "_mbscpy" - or - ( - name = "strcpy_s" or // strcpy_s(dst, max_amount, src) - name = "wcscpy_s" or // wcscpy_s(dst, max_amount, src) - name = "_mbscpy_s" // _mbscpy_s(dst, max_amount, src) - ) and - // exclude the 2-parameter template versions - // that find the size of a fixed size destination buffer. - getNumberOfParameters() = 3 - or - // strncpy(dst, src, max_amount) - name = "strncpy" - or - // _strncpy_l(dst, src, max_amount, locale) - name = "_strncpy_l" - or - // wcsncpy(dst, src, max_amount) - name = "wcsncpy" - or - // _wcsncpy_l(dst, src, max_amount, locale) - name = "_wcsncpy_l" - or - // _mbsncpy(dst, src, max_amount) - name = "_mbsncpy" - or - // _mbsncpy_l(dst, src, max_amount, locale) - name = "_mbsncpy_l" - ) + // strcpy(dst, src) + // wcscpy(dst, src) + // _mbscpy(dst, src) + // strncpy(dst, src, max_amount) + // _strncpy_l(dst, src, max_amount, locale) + // wcsncpy(dst, src, max_amount) + // _wcsncpy_l(dst, src, max_amount, locale) + // _mbsncpy(dst, src, max_amount) + // _mbsncpy_l(dst, src, max_amount, locale) + getName() = + ["strcpy", "wcscpy", "_mbscpy", "strncpy", "_strncpy_l", "wcsncpy", "_wcsncpy_l", "_mbsncpy", + "_mbsncpy_l"] + or + // strcpy_s(dst, max_amount, src) + // wcscpy_s(dst, max_amount, src) + // _mbscpy_s(dst, max_amount, src) + getName() = ["strcpy_s", "wcscpy_s", "_mbscpy_s"] and + // exclude the 2-parameter template versions + // that find the size of a fixed size destination buffer. + getNumberOfParameters() = 3 } /** diff --git a/cpp/ql/src/semmle/code/cpp/security/BufferWrite.qll b/cpp/ql/src/semmle/code/cpp/security/BufferWrite.qll index 7525b1f0d68..02328f707a9 100644 --- a/cpp/ql/src/semmle/code/cpp/security/BufferWrite.qll +++ b/cpp/ql/src/semmle/code/cpp/security/BufferWrite.qll @@ -354,11 +354,10 @@ class SnprintfBW extends BufferWriteCall { */ class GetsBW extends BufferWriteCall { GetsBW() { - exists(TopLevelFunction fn, string name | fn = getTarget() and name = fn.getName() | - name = "gets" or // gets(dst) - name = "fgets" or // fgets(dst, max_amount, src_stream) - name = "fgetws" // fgetws(dst, max_amount, src_stream) - ) + // gets(dst) + // fgets(dst, max_amount, src_stream) + // fgetws(dst, max_amount, src_stream) + getTarget().(TopLevelFunction).getName() = ["gets", "fgets", "fgetws"] } /** diff --git a/cpp/ql/src/semmle/code/cpp/security/FileWrite.qll b/cpp/ql/src/semmle/code/cpp/security/FileWrite.qll index f4c52801118..9f63ce99c0b 100644 --- a/cpp/ql/src/semmle/code/cpp/security/FileWrite.qll +++ b/cpp/ql/src/semmle/code/cpp/security/FileWrite.qll @@ -123,9 +123,7 @@ class WriteFunctionCall extends ChainedOutputCall { private predicate fileStreamChain(ChainedOutputCall out, Expr source, Expr dest) { source = out.getSource() and dest = out.getEndDest() and - exists(string nme | nme = "basic_ofstream" or nme = "basic_fstream" | - dest.getUnderlyingType().(Class).getSimpleName() = nme - ) + dest.getUnderlyingType().(Class).getSimpleName() = ["basic_ofstream", "basic_fstream"] } /** @@ -139,15 +137,7 @@ private predicate fileWrite(Call write, Expr source, Expr dest) { // named functions name = "fwrite" and s = 0 and d = 3 or - ( - name = "fputs" or - name = "fputws" or - name = "fputc" or - name = "fputwc" or - name = "putc" or - name = "putwc" or - name = "putw" - ) and + name = ["fputs", "fputws", "fputc", "fputwc", "putc", "putwc", "putw"] and s = 0 and d = 1 ) diff --git a/cpp/ql/src/semmle/code/cpp/security/OutputWrite.qll b/cpp/ql/src/semmle/code/cpp/security/OutputWrite.qll index cac3891d5ff..97635d92dbd 100644 --- a/cpp/ql/src/semmle/code/cpp/security/OutputWrite.qll +++ b/cpp/ql/src/semmle/code/cpp/security/OutputWrite.qll @@ -48,10 +48,7 @@ private predicate outputFile(Expr e) { name = e.(VariableAccess).getTarget().(GlobalVariable).toString() or name = e.findRootCause().(Macro).getName() ) and - ( - name = "stdout" or - name = "stderr" - ) + name = ["stdout", "stderr"] ) } diff --git a/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll b/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll index 06cf4c456ce..8c4783611b5 100644 --- a/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll @@ -252,11 +252,10 @@ private predicate insideFunctionValueMoveTo(Element src, Element dest) { copyValueBetweenArguments(c.getTarget(), sourceArg, destArg) and // Only consider copies from `printf`-like functions if the format is a string ( - exists(FormattingFunctionCall ffc, FormatLiteral format, string argFormat | + exists(FormattingFunctionCall ffc, FormatLiteral format | ffc = c and format = ffc.getFormat() and - format.getConversionChar(sourceArg - ffc.getTarget().getNumberOfParameters()) = argFormat and - (argFormat = "s" or argFormat = "S") + format.getConversionChar(sourceArg - ffc.getTarget().getNumberOfParameters()) = ["s", "S"] ) or not exists(FormatLiteral fl | fl = c.(FormattingFunctionCall).getFormat()) @@ -273,12 +272,11 @@ private predicate insideFunctionValueMoveTo(Element src, Element dest) { dest = c ) or - exists(FormattingFunctionCall formattingSend, int arg, FormatLiteral format, string argFormat | + exists(FormattingFunctionCall formattingSend, int arg, FormatLiteral format | dest = formattingSend and formattingSend.getArgument(arg) = src and format = formattingSend.getFormat() and - format.getConversionChar(arg - formattingSend.getTarget().getNumberOfParameters()) = argFormat and - (argFormat = "s" or argFormat = "S" or argFormat = "@") + format.getConversionChar(arg - formattingSend.getTarget().getNumberOfParameters()) = ["s", "S", "@"] ) or // Expressions computed from tainted data are also tainted diff --git a/cpp/ql/src/semmle/uml/MagicDraw.qll b/cpp/ql/src/semmle/uml/MagicDraw.qll index 3cd4701a05d..cb8fb761c1f 100644 --- a/cpp/ql/src/semmle/uml/MagicDraw.qll +++ b/cpp/ql/src/semmle/uml/MagicDraw.qll @@ -65,15 +65,8 @@ class UMLElement extends XMLElement { */ class UMLType extends UMLElement { UMLType() { - exists(string type | - this.getName() = "packagedElement" and - this.getAttribute("type").getValue() = type and - ( - type = "uml:Class" or - type = "uml:Interface" or - type = "uml:PrimitiveType" - ) - ) + this.getName() = "packagedElement" and + this.getAttribute("type").getValue() = ["uml:Class", "uml:Interface", "uml:PrimitiveType"] } /** From 26544f322a9b36e67ea789800ed732068db76121 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Sun, 27 Sep 2020 20:00:00 +0200 Subject: [PATCH 196/411] C#: Update data-flow tests for `System.Threading.Tasks` --- .../dataflow/global/DataFlow.expected | 28 +-- .../dataflow/global/DataFlowPath.expected | 232 +++++++++--------- .../dataflow/global/GetAnOutNode.expected | 16 +- .../dataflow/global/GlobalDataFlow.cs | 10 +- .../dataflow/global/TaintTracking.expected | 28 +-- .../global/TaintTrackingPath.expected | 232 +++++++++--------- 6 files changed, 275 insertions(+), 271 deletions(-) diff --git a/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected b/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected index 0c73bf55b63..a1180149878 100644 --- a/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected @@ -37,20 +37,20 @@ | GlobalDataFlow.cs:214:15:214:20 | access to local variable sink24 | | GlobalDataFlow.cs:216:15:216:20 | access to local variable sink25 | | GlobalDataFlow.cs:218:15:218:20 | access to local variable sink26 | -| GlobalDataFlow.cs:239:15:239:20 | access to local variable sink41 | -| GlobalDataFlow.cs:241:15:241:20 | access to local variable sink42 | -| GlobalDataFlow.cs:255:15:255:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:260:15:260:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:265:15:265:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:270:15:270:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:275:15:275:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:280:15:280:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:285:15:285:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:312:15:312:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:318:15:318:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:324:15:324:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:399:15:399:20 | access to local variable sink11 | -| GlobalDataFlow.cs:422:41:422:46 | access to local variable sink20 | +| GlobalDataFlow.cs:240:15:240:20 | access to local variable sink41 | +| GlobalDataFlow.cs:242:15:242:20 | access to local variable sink42 | +| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:272:15:272:24 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:277:15:277:24 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:282:15:282:24 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:287:15:287:24 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:314:15:314:24 | access to parameter sinkParam8 | +| GlobalDataFlow.cs:320:15:320:24 | access to parameter sinkParam9 | +| GlobalDataFlow.cs:326:15:326:25 | access to parameter sinkParam11 | +| GlobalDataFlow.cs:401:15:401:20 | access to local variable sink11 | +| GlobalDataFlow.cs:424:41:424:46 | access to local variable sink20 | | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | | Splitting.cs:11:19:11:19 | access to local variable x | diff --git a/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected b/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected index fa8e90c97e9..0770e8c7c67 100644 --- a/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected +++ b/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected @@ -55,7 +55,7 @@ edges | GlobalDataFlow.cs:36:13:36:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:36:13:36:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:36:13:36:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:36:13:36:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:252:26:252:35 | sinkParam0 : String | +| GlobalDataFlow.cs:36:13:36:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | | GlobalDataFlow.cs:38:35:38:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:46:13:46:30 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:38:35:38:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:20:53:37 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:38:35:38:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:28:54:45 | access to property SinkProperty0 : String | @@ -64,7 +64,7 @@ edges | GlobalDataFlow.cs:38:35:38:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:38:35:38:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:38:35:38:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:38:35:38:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:258:26:258:35 | sinkParam1 : String | +| GlobalDataFlow.cs:38:35:38:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam1 : String | | GlobalDataFlow.cs:45:30:45:39 | sinkParam2 : String | GlobalDataFlow.cs:45:50:45:59 | access to parameter sinkParam2 | | GlobalDataFlow.cs:46:13:46:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:30:45:39 | sinkParam2 : String | | GlobalDataFlow.cs:46:13:46:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:20:53:37 | access to property SinkProperty0 : String | @@ -80,31 +80,31 @@ edges | GlobalDataFlow.cs:53:20:53:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:20:53:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:20:53:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:20:53:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:377:41:377:41 | x : String | +| GlobalDataFlow.cs:53:20:53:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:379:41:379:41 | x : String | | GlobalDataFlow.cs:54:15:54:15 | x : String | GlobalDataFlow.cs:54:24:54:24 | access to parameter x : String | -| GlobalDataFlow.cs:54:24:54:24 | access to parameter x : String | GlobalDataFlow.cs:268:26:268:35 | sinkParam4 : String | +| GlobalDataFlow.cs:54:24:54:24 | access to parameter x : String | GlobalDataFlow.cs:270:26:270:35 | sinkParam4 : String | | GlobalDataFlow.cs:54:28:54:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:44:55:61 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:28:54:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:56:28:56:45 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:28:54:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:28:54:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:28:54:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:28:54:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:377:41:377:41 | x : String | +| GlobalDataFlow.cs:54:28:54:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:379:41:379:41 | x : String | | GlobalDataFlow.cs:55:44:55:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:56:28:56:45 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:55:44:55:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:55:44:55:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:55:44:55:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:44:55:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:391:52:391:52 | x : String | +| GlobalDataFlow.cs:55:44:55:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:393:52:393:52 | x : String | | GlobalDataFlow.cs:56:28:56:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:56:28:56:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:56:28:56:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:56:28:56:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:391:52:391:52 | x : String | +| GlobalDataFlow.cs:56:28:56:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:393:52:393:52 | x : String | | GlobalDataFlow.cs:57:37:57:37 | x : String | GlobalDataFlow.cs:57:46:57:46 | access to parameter x : String | -| GlobalDataFlow.cs:57:46:57:46 | access to parameter x : String | GlobalDataFlow.cs:283:26:283:35 | sinkParam7 : String | +| GlobalDataFlow.cs:57:46:57:46 | access to parameter x : String | GlobalDataFlow.cs:285:26:285:35 | sinkParam7 : String | | GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:391:52:391:52 | x : String | +| GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:393:52:393:52 | x : String | | GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:422:9:422:11 | value : String | +| GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:424:9:424:11 | value : String | | GlobalDataFlow.cs:71:21:71:46 | call to method Return : String | GlobalDataFlow.cs:72:15:72:19 | access to local variable sink0 | | GlobalDataFlow.cs:71:21:71:46 | call to method Return : String | GlobalDataFlow.cs:73:94:73:98 | access to local variable sink0 : String | | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:21:71:46 | call to method Return : String | @@ -129,7 +129,7 @@ edges | GlobalDataFlow.cs:83:22:83:95 | call to method First : String | GlobalDataFlow.cs:84:15:84:20 | access to local variable sink14 | | GlobalDataFlow.cs:83:22:83:95 | call to method First : String | GlobalDataFlow.cs:85:59:85:64 | access to local variable sink14 : String | | GlobalDataFlow.cs:83:23:83:66 | (...) ... [[]] : String | GlobalDataFlow.cs:83:22:83:87 | call to method Select [[]] : String | -| GlobalDataFlow.cs:83:23:83:66 | (...) ... [[]] : String | GlobalDataFlow.cs:310:31:310:40 | sinkParam8 : String | +| GlobalDataFlow.cs:83:23:83:66 | (...) ... [[]] : String | GlobalDataFlow.cs:312:31:312:40 | sinkParam8 : String | | GlobalDataFlow.cs:83:57:83:66 | { ..., ... } [[]] : String | GlobalDataFlow.cs:83:23:83:66 | (...) ... [[]] : String | | GlobalDataFlow.cs:83:59:83:64 | access to local variable sink13 : String | GlobalDataFlow.cs:83:57:83:66 | { ..., ... } [[]] : String | | GlobalDataFlow.cs:85:22:85:128 | call to method Zip [[]] : String | GlobalDataFlow.cs:85:22:85:136 | call to method First : String | @@ -167,7 +167,7 @@ edges | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:208:44:208:61 | { ..., ... } [[]] : String | | GlobalDataFlow.cs:211:35:211:45 | sinkParam10 : String | GlobalDataFlow.cs:211:58:211:68 | access to parameter sinkParam10 | | GlobalDataFlow.cs:212:71:212:71 | x : String | GlobalDataFlow.cs:212:89:212:89 | access to parameter x : String | -| GlobalDataFlow.cs:212:89:212:89 | access to parameter x : String | GlobalDataFlow.cs:316:32:316:41 | sinkParam9 : String | +| GlobalDataFlow.cs:212:89:212:89 | access to parameter x : String | GlobalDataFlow.cs:318:32:318:41 | sinkParam9 : String | | GlobalDataFlow.cs:213:22:213:28 | access to local variable tainted [[]] : String | GlobalDataFlow.cs:211:35:211:45 | sinkParam10 : String | | GlobalDataFlow.cs:213:22:213:28 | access to local variable tainted [[]] : String | GlobalDataFlow.cs:213:22:213:39 | call to method Select [[]] : String | | GlobalDataFlow.cs:213:22:213:39 | call to method Select [[]] : String | GlobalDataFlow.cs:213:22:213:47 | call to method First : String | @@ -177,45 +177,45 @@ edges | GlobalDataFlow.cs:215:22:215:39 | call to method Select [[]] : String | GlobalDataFlow.cs:215:22:215:47 | call to method First : String | | GlobalDataFlow.cs:215:22:215:47 | call to method First : String | GlobalDataFlow.cs:216:15:216:20 | access to local variable sink25 | | GlobalDataFlow.cs:217:22:217:28 | access to local variable tainted [[]] : String | GlobalDataFlow.cs:217:22:217:49 | call to method Select [[]] : String | -| GlobalDataFlow.cs:217:22:217:28 | access to local variable tainted [[]] : String | GlobalDataFlow.cs:322:32:322:42 | sinkParam11 : String | +| GlobalDataFlow.cs:217:22:217:28 | access to local variable tainted [[]] : String | GlobalDataFlow.cs:324:32:324:42 | sinkParam11 : String | | GlobalDataFlow.cs:217:22:217:49 | call to method Select [[]] : String | GlobalDataFlow.cs:217:22:217:57 | call to method First : String | | GlobalDataFlow.cs:217:22:217:57 | call to method First : String | GlobalDataFlow.cs:218:15:218:20 | access to local variable sink26 | -| GlobalDataFlow.cs:238:37:238:50 | "taint source" : String | GlobalDataFlow.cs:239:15:239:20 | access to local variable sink41 | -| GlobalDataFlow.cs:238:37:238:50 | "taint source" : String | GlobalDataFlow.cs:241:15:241:20 | access to local variable sink42 | -| GlobalDataFlow.cs:252:26:252:35 | sinkParam0 : String | GlobalDataFlow.cs:254:16:254:25 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:252:26:252:35 | sinkParam0 : String | GlobalDataFlow.cs:255:15:255:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:254:16:254:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:252:26:252:35 | sinkParam0 : String | -| GlobalDataFlow.cs:258:26:258:35 | sinkParam1 : String | GlobalDataFlow.cs:260:15:260:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:263:26:263:35 | sinkParam3 : String | GlobalDataFlow.cs:265:15:265:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:268:26:268:35 | sinkParam4 : String | GlobalDataFlow.cs:270:15:270:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:273:26:273:35 | sinkParam5 : String | GlobalDataFlow.cs:275:15:275:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:278:26:278:35 | sinkParam6 : String | GlobalDataFlow.cs:280:15:280:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:283:26:283:35 | sinkParam7 : String | GlobalDataFlow.cs:285:15:285:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:310:31:310:40 | sinkParam8 : String | GlobalDataFlow.cs:312:15:312:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:316:32:316:41 | sinkParam9 : String | GlobalDataFlow.cs:318:15:318:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:322:32:322:42 | sinkParam11 : String | GlobalDataFlow.cs:324:15:324:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:336:16:336:29 | "taint source" : String | GlobalDataFlow.cs:154:21:154:25 | call to method Out : String | -| GlobalDataFlow.cs:336:16:336:29 | "taint source" : String | GlobalDataFlow.cs:190:22:190:42 | object creation of type Lazy [Value] : String | -| GlobalDataFlow.cs:341:9:341:26 | SSA def(x) : String | GlobalDataFlow.cs:157:20:157:24 | SSA def(sink7) : String | -| GlobalDataFlow.cs:341:13:341:26 | "taint source" : String | GlobalDataFlow.cs:341:9:341:26 | SSA def(x) : String | -| GlobalDataFlow.cs:346:9:346:26 | SSA def(x) : String | GlobalDataFlow.cs:160:20:160:24 | SSA def(sink8) : String | -| GlobalDataFlow.cs:346:13:346:26 | "taint source" : String | GlobalDataFlow.cs:346:9:346:26 | SSA def(x) : String | -| GlobalDataFlow.cs:352:22:352:35 | "taint source" : String | GlobalDataFlow.cs:162:22:162:31 | call to method OutYield [[]] : String | -| GlobalDataFlow.cs:377:41:377:41 | x : String | GlobalDataFlow.cs:379:11:379:11 | access to parameter x : String | -| GlobalDataFlow.cs:377:41:377:41 | x : String | GlobalDataFlow.cs:379:11:379:11 | access to parameter x : String | -| GlobalDataFlow.cs:379:11:379:11 | access to parameter x : String | GlobalDataFlow.cs:54:15:54:15 | x : String | -| GlobalDataFlow.cs:379:11:379:11 | access to parameter x : String | GlobalDataFlow.cs:263:26:263:35 | sinkParam3 : String | -| GlobalDataFlow.cs:391:52:391:52 | x : String | GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | -| GlobalDataFlow.cs:391:52:391:52 | x : String | GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | -| GlobalDataFlow.cs:391:52:391:52 | x : String | GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | -| GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | GlobalDataFlow.cs:57:37:57:37 | x : String | -| GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | GlobalDataFlow.cs:273:26:273:35 | sinkParam5 : String | -| GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | GlobalDataFlow.cs:278:26:278:35 | sinkParam6 : String | -| GlobalDataFlow.cs:396:39:396:45 | tainted : String | GlobalDataFlow.cs:399:15:399:20 | access to local variable sink11 | -| GlobalDataFlow.cs:396:39:396:45 | tainted : String | GlobalDataFlow.cs:400:16:400:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:400:16:400:21 | access to local variable sink11 : String | GlobalDataFlow.cs:164:22:164:43 | call to method TaintedParam : String | -| GlobalDataFlow.cs:422:9:422:11 | value : String | GlobalDataFlow.cs:422:41:422:46 | access to local variable sink20 | -| GlobalDataFlow.cs:433:22:433:35 | "taint source" : String | GlobalDataFlow.cs:198:22:198:32 | access to property OutProperty : String | +| GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | GlobalDataFlow.cs:240:15:240:20 | access to local variable sink41 | +| GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | GlobalDataFlow.cs:242:15:242:20 | access to local variable sink42 | +| GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | GlobalDataFlow.cs:256:16:256:25 | access to parameter sinkParam0 : String | +| GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:256:16:256:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | +| GlobalDataFlow.cs:260:26:260:35 | sinkParam1 : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:265:26:265:35 | sinkParam3 : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:270:26:270:35 | sinkParam4 : String | GlobalDataFlow.cs:272:15:272:24 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:275:26:275:35 | sinkParam5 : String | GlobalDataFlow.cs:277:15:277:24 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:280:26:280:35 | sinkParam6 : String | GlobalDataFlow.cs:282:15:282:24 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:285:26:285:35 | sinkParam7 : String | GlobalDataFlow.cs:287:15:287:24 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:312:31:312:40 | sinkParam8 : String | GlobalDataFlow.cs:314:15:314:24 | access to parameter sinkParam8 | +| GlobalDataFlow.cs:318:32:318:41 | sinkParam9 : String | GlobalDataFlow.cs:320:15:320:24 | access to parameter sinkParam9 | +| GlobalDataFlow.cs:324:32:324:42 | sinkParam11 : String | GlobalDataFlow.cs:326:15:326:25 | access to parameter sinkParam11 | +| GlobalDataFlow.cs:338:16:338:29 | "taint source" : String | GlobalDataFlow.cs:154:21:154:25 | call to method Out : String | +| GlobalDataFlow.cs:338:16:338:29 | "taint source" : String | GlobalDataFlow.cs:190:22:190:42 | object creation of type Lazy [Value] : String | +| GlobalDataFlow.cs:343:9:343:26 | SSA def(x) : String | GlobalDataFlow.cs:157:20:157:24 | SSA def(sink7) : String | +| GlobalDataFlow.cs:343:13:343:26 | "taint source" : String | GlobalDataFlow.cs:343:9:343:26 | SSA def(x) : String | +| GlobalDataFlow.cs:348:9:348:26 | SSA def(x) : String | GlobalDataFlow.cs:160:20:160:24 | SSA def(sink8) : String | +| GlobalDataFlow.cs:348:13:348:26 | "taint source" : String | GlobalDataFlow.cs:348:9:348:26 | SSA def(x) : String | +| GlobalDataFlow.cs:354:22:354:35 | "taint source" : String | GlobalDataFlow.cs:162:22:162:31 | call to method OutYield [[]] : String | +| GlobalDataFlow.cs:379:41:379:41 | x : String | GlobalDataFlow.cs:381:11:381:11 | access to parameter x : String | +| GlobalDataFlow.cs:379:41:379:41 | x : String | GlobalDataFlow.cs:381:11:381:11 | access to parameter x : String | +| GlobalDataFlow.cs:381:11:381:11 | access to parameter x : String | GlobalDataFlow.cs:54:15:54:15 | x : String | +| GlobalDataFlow.cs:381:11:381:11 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam3 : String | +| GlobalDataFlow.cs:393:52:393:52 | x : String | GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | +| GlobalDataFlow.cs:393:52:393:52 | x : String | GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | +| GlobalDataFlow.cs:393:52:393:52 | x : String | GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | +| GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | GlobalDataFlow.cs:57:37:57:37 | x : String | +| GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:35 | sinkParam5 : String | +| GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | GlobalDataFlow.cs:280:26:280:35 | sinkParam6 : String | +| GlobalDataFlow.cs:398:39:398:45 | tainted : String | GlobalDataFlow.cs:401:15:401:20 | access to local variable sink11 | +| GlobalDataFlow.cs:398:39:398:45 | tainted : String | GlobalDataFlow.cs:402:16:402:21 | access to local variable sink11 : String | +| GlobalDataFlow.cs:402:16:402:21 | access to local variable sink11 : String | GlobalDataFlow.cs:164:22:164:43 | call to method TaintedParam : String | +| GlobalDataFlow.cs:424:9:424:11 | value : String | GlobalDataFlow.cs:424:41:424:46 | access to local variable sink20 | +| GlobalDataFlow.cs:435:22:435:35 | "taint source" : String | GlobalDataFlow.cs:198:22:198:32 | access to property OutProperty : String | | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | @@ -367,52 +367,52 @@ nodes | GlobalDataFlow.cs:217:22:217:49 | call to method Select [[]] : String | semmle.label | call to method Select [[]] : String | | GlobalDataFlow.cs:217:22:217:57 | call to method First : String | semmle.label | call to method First : String | | GlobalDataFlow.cs:218:15:218:20 | access to local variable sink26 | semmle.label | access to local variable sink26 | -| GlobalDataFlow.cs:238:37:238:50 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:239:15:239:20 | access to local variable sink41 | semmle.label | access to local variable sink41 | -| GlobalDataFlow.cs:241:15:241:20 | access to local variable sink42 | semmle.label | access to local variable sink42 | -| GlobalDataFlow.cs:252:26:252:35 | sinkParam0 : String | semmle.label | sinkParam0 : String | -| GlobalDataFlow.cs:254:16:254:25 | access to parameter sinkParam0 : String | semmle.label | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:255:15:255:24 | access to parameter sinkParam0 | semmle.label | access to parameter sinkParam0 | -| GlobalDataFlow.cs:258:26:258:35 | sinkParam1 : String | semmle.label | sinkParam1 : String | -| GlobalDataFlow.cs:260:15:260:24 | access to parameter sinkParam1 | semmle.label | access to parameter sinkParam1 | -| GlobalDataFlow.cs:263:26:263:35 | sinkParam3 : String | semmle.label | sinkParam3 : String | -| GlobalDataFlow.cs:265:15:265:24 | access to parameter sinkParam3 | semmle.label | access to parameter sinkParam3 | -| GlobalDataFlow.cs:268:26:268:35 | sinkParam4 : String | semmle.label | sinkParam4 : String | -| GlobalDataFlow.cs:270:15:270:24 | access to parameter sinkParam4 | semmle.label | access to parameter sinkParam4 | -| GlobalDataFlow.cs:273:26:273:35 | sinkParam5 : String | semmle.label | sinkParam5 : String | -| GlobalDataFlow.cs:275:15:275:24 | access to parameter sinkParam5 | semmle.label | access to parameter sinkParam5 | -| GlobalDataFlow.cs:278:26:278:35 | sinkParam6 : String | semmle.label | sinkParam6 : String | -| GlobalDataFlow.cs:280:15:280:24 | access to parameter sinkParam6 | semmle.label | access to parameter sinkParam6 | -| GlobalDataFlow.cs:283:26:283:35 | sinkParam7 : String | semmle.label | sinkParam7 : String | -| GlobalDataFlow.cs:285:15:285:24 | access to parameter sinkParam7 | semmle.label | access to parameter sinkParam7 | -| GlobalDataFlow.cs:310:31:310:40 | sinkParam8 : String | semmle.label | sinkParam8 : String | -| GlobalDataFlow.cs:312:15:312:24 | access to parameter sinkParam8 | semmle.label | access to parameter sinkParam8 | -| GlobalDataFlow.cs:316:32:316:41 | sinkParam9 : String | semmle.label | sinkParam9 : String | -| GlobalDataFlow.cs:318:15:318:24 | access to parameter sinkParam9 | semmle.label | access to parameter sinkParam9 | -| GlobalDataFlow.cs:322:32:322:42 | sinkParam11 : String | semmle.label | sinkParam11 : String | -| GlobalDataFlow.cs:324:15:324:25 | access to parameter sinkParam11 | semmle.label | access to parameter sinkParam11 | -| GlobalDataFlow.cs:336:16:336:29 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:341:9:341:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | -| GlobalDataFlow.cs:341:13:341:26 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:346:9:346:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | -| GlobalDataFlow.cs:346:13:346:26 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:352:22:352:35 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:377:41:377:41 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:377:41:377:41 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:379:11:379:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:379:11:379:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:391:52:391:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:391:52:391:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:391:52:391:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:396:39:396:45 | tainted : String | semmle.label | tainted : String | -| GlobalDataFlow.cs:399:15:399:20 | access to local variable sink11 | semmle.label | access to local variable sink11 | -| GlobalDataFlow.cs:400:16:400:21 | access to local variable sink11 : String | semmle.label | access to local variable sink11 : String | -| GlobalDataFlow.cs:422:9:422:11 | value : String | semmle.label | value : String | -| GlobalDataFlow.cs:422:41:422:46 | access to local variable sink20 | semmle.label | access to local variable sink20 | -| GlobalDataFlow.cs:433:22:433:35 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:240:15:240:20 | access to local variable sink41 | semmle.label | access to local variable sink41 | +| GlobalDataFlow.cs:242:15:242:20 | access to local variable sink42 | semmle.label | access to local variable sink42 | +| GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | semmle.label | sinkParam0 : String | +| GlobalDataFlow.cs:256:16:256:25 | access to parameter sinkParam0 : String | semmle.label | access to parameter sinkParam0 : String | +| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam0 | semmle.label | access to parameter sinkParam0 | +| GlobalDataFlow.cs:260:26:260:35 | sinkParam1 : String | semmle.label | sinkParam1 : String | +| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam1 | semmle.label | access to parameter sinkParam1 | +| GlobalDataFlow.cs:265:26:265:35 | sinkParam3 : String | semmle.label | sinkParam3 : String | +| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam3 | semmle.label | access to parameter sinkParam3 | +| GlobalDataFlow.cs:270:26:270:35 | sinkParam4 : String | semmle.label | sinkParam4 : String | +| GlobalDataFlow.cs:272:15:272:24 | access to parameter sinkParam4 | semmle.label | access to parameter sinkParam4 | +| GlobalDataFlow.cs:275:26:275:35 | sinkParam5 : String | semmle.label | sinkParam5 : String | +| GlobalDataFlow.cs:277:15:277:24 | access to parameter sinkParam5 | semmle.label | access to parameter sinkParam5 | +| GlobalDataFlow.cs:280:26:280:35 | sinkParam6 : String | semmle.label | sinkParam6 : String | +| GlobalDataFlow.cs:282:15:282:24 | access to parameter sinkParam6 | semmle.label | access to parameter sinkParam6 | +| GlobalDataFlow.cs:285:26:285:35 | sinkParam7 : String | semmle.label | sinkParam7 : String | +| GlobalDataFlow.cs:287:15:287:24 | access to parameter sinkParam7 | semmle.label | access to parameter sinkParam7 | +| GlobalDataFlow.cs:312:31:312:40 | sinkParam8 : String | semmle.label | sinkParam8 : String | +| GlobalDataFlow.cs:314:15:314:24 | access to parameter sinkParam8 | semmle.label | access to parameter sinkParam8 | +| GlobalDataFlow.cs:318:32:318:41 | sinkParam9 : String | semmle.label | sinkParam9 : String | +| GlobalDataFlow.cs:320:15:320:24 | access to parameter sinkParam9 | semmle.label | access to parameter sinkParam9 | +| GlobalDataFlow.cs:324:32:324:42 | sinkParam11 : String | semmle.label | sinkParam11 : String | +| GlobalDataFlow.cs:326:15:326:25 | access to parameter sinkParam11 | semmle.label | access to parameter sinkParam11 | +| GlobalDataFlow.cs:338:16:338:29 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:343:9:343:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | +| GlobalDataFlow.cs:343:13:343:26 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:348:9:348:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | +| GlobalDataFlow.cs:348:13:348:26 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:354:22:354:35 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:379:41:379:41 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:379:41:379:41 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:381:11:381:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:381:11:381:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:393:52:393:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:393:52:393:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:393:52:393:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:398:39:398:45 | tainted : String | semmle.label | tainted : String | +| GlobalDataFlow.cs:401:15:401:20 | access to local variable sink11 | semmle.label | access to local variable sink11 | +| GlobalDataFlow.cs:402:16:402:21 | access to local variable sink11 : String | semmle.label | access to local variable sink11 : String | +| GlobalDataFlow.cs:424:9:424:11 | value : String | semmle.label | value : String | +| GlobalDataFlow.cs:424:41:424:46 | access to local variable sink20 | semmle.label | access to local variable sink20 | +| GlobalDataFlow.cs:435:22:435:35 | "taint source" : String | semmle.label | "taint source" : String | | Splitting.cs:3:28:3:34 | tainted : String | semmle.label | tainted : String | | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | semmle.label | [b (line 3): false] call to method Return : String | | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | semmle.label | [b (line 3): true] call to method Return : String | @@ -441,17 +441,17 @@ nodes | GlobalDataFlow.cs:19:15:19:29 | access to field SinkField0 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:19:15:19:29 | access to field SinkField0 | access to field SinkField0 | | GlobalDataFlow.cs:72:15:72:19 | access to local variable sink0 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:72:15:72:19 | access to local variable sink0 | access to local variable sink0 | | GlobalDataFlow.cs:74:15:74:19 | access to local variable sink1 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:74:15:74:19 | access to local variable sink1 | access to local variable sink1 | -| GlobalDataFlow.cs:191:15:191:20 | access to local variable sink10 | GlobalDataFlow.cs:336:16:336:29 | "taint source" : String | GlobalDataFlow.cs:191:15:191:20 | access to local variable sink10 | access to local variable sink10 | -| GlobalDataFlow.cs:399:15:399:20 | access to local variable sink11 | GlobalDataFlow.cs:396:39:396:45 | tainted : String | GlobalDataFlow.cs:399:15:399:20 | access to local variable sink11 | access to local variable sink11 | -| GlobalDataFlow.cs:163:15:163:20 | access to local variable sink12 | GlobalDataFlow.cs:352:22:352:35 | "taint source" : String | GlobalDataFlow.cs:163:15:163:20 | access to local variable sink12 | access to local variable sink12 | +| GlobalDataFlow.cs:191:15:191:20 | access to local variable sink10 | GlobalDataFlow.cs:338:16:338:29 | "taint source" : String | GlobalDataFlow.cs:191:15:191:20 | access to local variable sink10 | access to local variable sink10 | +| GlobalDataFlow.cs:401:15:401:20 | access to local variable sink11 | GlobalDataFlow.cs:398:39:398:45 | tainted : String | GlobalDataFlow.cs:401:15:401:20 | access to local variable sink11 | access to local variable sink11 | +| GlobalDataFlow.cs:163:15:163:20 | access to local variable sink12 | GlobalDataFlow.cs:354:22:354:35 | "taint source" : String | GlobalDataFlow.cs:163:15:163:20 | access to local variable sink12 | access to local variable sink12 | | GlobalDataFlow.cs:82:15:82:20 | access to local variable sink13 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:82:15:82:20 | access to local variable sink13 | access to local variable sink13 | | GlobalDataFlow.cs:84:15:84:20 | access to local variable sink14 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:84:15:84:20 | access to local variable sink14 | access to local variable sink14 | | GlobalDataFlow.cs:86:15:86:20 | access to local variable sink15 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:86:15:86:20 | access to local variable sink15 | access to local variable sink15 | | GlobalDataFlow.cs:88:15:88:20 | access to local variable sink16 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:88:15:88:20 | access to local variable sink16 | access to local variable sink16 | -| GlobalDataFlow.cs:199:15:199:20 | access to local variable sink19 | GlobalDataFlow.cs:433:22:433:35 | "taint source" : String | GlobalDataFlow.cs:199:15:199:20 | access to local variable sink19 | access to local variable sink19 | +| GlobalDataFlow.cs:199:15:199:20 | access to local variable sink19 | GlobalDataFlow.cs:435:22:435:35 | "taint source" : String | GlobalDataFlow.cs:199:15:199:20 | access to local variable sink19 | access to local variable sink19 | | GlobalDataFlow.cs:77:15:77:19 | access to local variable sink2 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:77:15:77:19 | access to local variable sink2 | access to local variable sink2 | -| GlobalDataFlow.cs:422:41:422:46 | access to local variable sink20 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:422:41:422:46 | access to local variable sink20 | access to local variable sink20 | -| GlobalDataFlow.cs:165:15:165:20 | access to local variable sink23 | GlobalDataFlow.cs:396:39:396:45 | tainted : String | GlobalDataFlow.cs:165:15:165:20 | access to local variable sink23 | access to local variable sink23 | +| GlobalDataFlow.cs:424:41:424:46 | access to local variable sink20 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:424:41:424:46 | access to local variable sink20 | access to local variable sink20 | +| GlobalDataFlow.cs:165:15:165:20 | access to local variable sink23 | GlobalDataFlow.cs:398:39:398:45 | tainted : String | GlobalDataFlow.cs:165:15:165:20 | access to local variable sink23 | access to local variable sink23 | | GlobalDataFlow.cs:214:15:214:20 | access to local variable sink24 | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:214:15:214:20 | access to local variable sink24 | access to local variable sink24 | | GlobalDataFlow.cs:216:15:216:20 | access to local variable sink25 | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:216:15:216:20 | access to local variable sink25 | access to local variable sink25 | | GlobalDataFlow.cs:218:15:218:20 | access to local variable sink26 | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:218:15:218:20 | access to local variable sink26 | access to local variable sink26 | @@ -470,27 +470,27 @@ nodes | Capture.cs:195:15:195:20 | access to local variable sink38 | Capture.cs:125:25:125:31 | tainted : String | Capture.cs:195:15:195:20 | access to local variable sink38 | access to local variable sink38 | | GlobalDataFlow.cs:137:15:137:19 | access to local variable sink4 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:137:15:137:19 | access to local variable sink4 | access to local variable sink4 | | Capture.cs:122:15:122:20 | access to local variable sink40 | Capture.cs:115:26:115:39 | "taint source" : String | Capture.cs:122:15:122:20 | access to local variable sink40 | access to local variable sink40 | -| GlobalDataFlow.cs:239:15:239:20 | access to local variable sink41 | GlobalDataFlow.cs:238:37:238:50 | "taint source" : String | GlobalDataFlow.cs:239:15:239:20 | access to local variable sink41 | access to local variable sink41 | -| GlobalDataFlow.cs:241:15:241:20 | access to local variable sink42 | GlobalDataFlow.cs:238:37:238:50 | "taint source" : String | GlobalDataFlow.cs:241:15:241:20 | access to local variable sink42 | access to local variable sink42 | +| GlobalDataFlow.cs:240:15:240:20 | access to local variable sink41 | GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | GlobalDataFlow.cs:240:15:240:20 | access to local variable sink41 | access to local variable sink41 | +| GlobalDataFlow.cs:242:15:242:20 | access to local variable sink42 | GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | GlobalDataFlow.cs:242:15:242:20 | access to local variable sink42 | access to local variable sink42 | | GlobalDataFlow.cs:145:15:145:19 | access to local variable sink5 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:145:15:145:19 | access to local variable sink5 | access to local variable sink5 | -| GlobalDataFlow.cs:155:15:155:19 | access to local variable sink6 | GlobalDataFlow.cs:336:16:336:29 | "taint source" : String | GlobalDataFlow.cs:155:15:155:19 | access to local variable sink6 | access to local variable sink6 | -| GlobalDataFlow.cs:158:15:158:19 | access to local variable sink7 | GlobalDataFlow.cs:341:13:341:26 | "taint source" : String | GlobalDataFlow.cs:158:15:158:19 | access to local variable sink7 | access to local variable sink7 | -| GlobalDataFlow.cs:161:15:161:19 | access to local variable sink8 | GlobalDataFlow.cs:346:13:346:26 | "taint source" : String | GlobalDataFlow.cs:161:15:161:19 | access to local variable sink8 | access to local variable sink8 | +| GlobalDataFlow.cs:155:15:155:19 | access to local variable sink6 | GlobalDataFlow.cs:338:16:338:29 | "taint source" : String | GlobalDataFlow.cs:155:15:155:19 | access to local variable sink6 | access to local variable sink6 | +| GlobalDataFlow.cs:158:15:158:19 | access to local variable sink7 | GlobalDataFlow.cs:343:13:343:26 | "taint source" : String | GlobalDataFlow.cs:158:15:158:19 | access to local variable sink7 | access to local variable sink7 | +| GlobalDataFlow.cs:161:15:161:19 | access to local variable sink8 | GlobalDataFlow.cs:348:13:348:26 | "taint source" : String | GlobalDataFlow.cs:161:15:161:19 | access to local variable sink8 | access to local variable sink8 | | GlobalDataFlow.cs:182:15:182:19 | access to local variable sink9 | GlobalDataFlow.cs:180:35:180:48 | "taint source" : String | GlobalDataFlow.cs:182:15:182:19 | access to local variable sink9 | access to local variable sink9 | | Splitting.cs:11:19:11:19 | access to local variable x | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:11:19:11:19 | access to local variable x | access to local variable x | | Splitting.cs:34:19:34:19 | access to local variable x | Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:34:19:34:19 | access to local variable x | access to local variable x | | Capture.cs:57:27:57:32 | access to parameter sink39 | Capture.cs:7:20:7:26 | tainted : String | Capture.cs:57:27:57:32 | access to parameter sink39 | access to parameter sink39 | -| GlobalDataFlow.cs:255:15:255:24 | access to parameter sinkParam0 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:255:15:255:24 | access to parameter sinkParam0 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:260:15:260:24 | access to parameter sinkParam1 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:260:15:260:24 | access to parameter sinkParam1 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam0 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam0 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam1 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam1 | access to parameter sinkParam1 | | GlobalDataFlow.cs:211:58:211:68 | access to parameter sinkParam10 | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:211:58:211:68 | access to parameter sinkParam10 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:324:15:324:25 | access to parameter sinkParam11 | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:324:15:324:25 | access to parameter sinkParam11 | access to parameter sinkParam11 | +| GlobalDataFlow.cs:326:15:326:25 | access to parameter sinkParam11 | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:326:15:326:25 | access to parameter sinkParam11 | access to parameter sinkParam11 | | GlobalDataFlow.cs:45:50:45:59 | access to parameter sinkParam2 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:45:50:45:59 | access to parameter sinkParam2 | access to parameter sinkParam2 | -| GlobalDataFlow.cs:265:15:265:24 | access to parameter sinkParam3 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:265:15:265:24 | access to parameter sinkParam3 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:270:15:270:24 | access to parameter sinkParam4 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:270:15:270:24 | access to parameter sinkParam4 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:275:15:275:24 | access to parameter sinkParam5 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:275:15:275:24 | access to parameter sinkParam5 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:280:15:280:24 | access to parameter sinkParam6 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:280:15:280:24 | access to parameter sinkParam6 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:285:15:285:24 | access to parameter sinkParam7 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:285:15:285:24 | access to parameter sinkParam7 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:312:15:312:24 | access to parameter sinkParam8 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:312:15:312:24 | access to parameter sinkParam8 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:318:15:318:24 | access to parameter sinkParam9 | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:318:15:318:24 | access to parameter sinkParam9 | access to parameter sinkParam9 | +| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam3 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam3 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:272:15:272:24 | access to parameter sinkParam4 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:272:15:272:24 | access to parameter sinkParam4 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:277:15:277:24 | access to parameter sinkParam5 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:277:15:277:24 | access to parameter sinkParam5 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:282:15:282:24 | access to parameter sinkParam6 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:282:15:282:24 | access to parameter sinkParam6 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:287:15:287:24 | access to parameter sinkParam7 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:287:15:287:24 | access to parameter sinkParam7 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:314:15:314:24 | access to parameter sinkParam8 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:314:15:314:24 | access to parameter sinkParam8 | access to parameter sinkParam8 | +| GlobalDataFlow.cs:320:15:320:24 | access to parameter sinkParam9 | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:320:15:320:24 | access to parameter sinkParam9 | access to parameter sinkParam9 | | Splitting.cs:21:28:21:32 | access to parameter value | Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:21:28:21:32 | access to parameter value | access to parameter value | | GlobalDataFlow.cs:27:15:27:32 | access to property SinkProperty0 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:27:15:27:32 | access to property SinkProperty0 | access to property SinkProperty0 | diff --git a/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected b/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected index 088eefba975..730e18b8726 100644 --- a/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected +++ b/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected @@ -186,13 +186,15 @@ | GlobalDataFlow.cs:231:19:231:49 | call to method Select | yield return | GlobalDataFlow.cs:231:19:231:49 | call to method Select | | GlobalDataFlow.cs:231:19:231:57 | call to method First | return | GlobalDataFlow.cs:231:19:231:57 | call to method First | | GlobalDataFlow.cs:231:37:231:48 | [implicit call] delegate creation of type Func | return | GlobalDataFlow.cs:231:37:231:48 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:238:22:238:51 | call to method Run | return | GlobalDataFlow.cs:238:22:238:51 | call to method Run | -| GlobalDataFlow.cs:238:31:238:50 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:238:31:238:50 | [output] (...) => ... | -| GlobalDataFlow.cs:244:24:244:41 | call to method Run | return | GlobalDataFlow.cs:244:24:244:41 | call to method Run | -| GlobalDataFlow.cs:244:33:244:40 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:244:33:244:40 | [output] (...) => ... | -| GlobalDataFlow.cs:295:17:295:38 | call to method ApplyFunc | return | GlobalDataFlow.cs:295:17:295:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:384:16:384:19 | delegate call | return | GlobalDataFlow.cs:384:16:384:19 | delegate call | -| GlobalDataFlow.cs:449:44:449:47 | delegate call | return | GlobalDataFlow.cs:449:44:449:47 | delegate call | +| GlobalDataFlow.cs:238:20:238:49 | call to method Run | return | GlobalDataFlow.cs:238:20:238:49 | call to method Run | +| GlobalDataFlow.cs:238:29:238:48 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:238:29:238:48 | [output] (...) => ... | +| GlobalDataFlow.cs:239:22:239:32 | access to property Result | return | GlobalDataFlow.cs:239:22:239:32 | access to property Result | +| GlobalDataFlow.cs:245:16:245:33 | call to method Run | return | GlobalDataFlow.cs:245:16:245:33 | call to method Run | +| GlobalDataFlow.cs:245:25:245:32 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:245:25:245:32 | [output] (...) => ... | +| GlobalDataFlow.cs:246:24:246:34 | access to property Result | return | GlobalDataFlow.cs:246:24:246:34 | access to property Result | +| GlobalDataFlow.cs:297:17:297:38 | call to method ApplyFunc | return | GlobalDataFlow.cs:297:17:297:38 | call to method ApplyFunc | +| GlobalDataFlow.cs:386:16:386:19 | delegate call | return | GlobalDataFlow.cs:386:16:386:19 | delegate call | +| GlobalDataFlow.cs:451:44:451:47 | delegate call | return | GlobalDataFlow.cs:451:44:451:47 | delegate call | | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | return | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return | return | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return | | Splitting.cs:20:22:20:30 | call to method Return | return | Splitting.cs:20:22:20:30 | call to method Return | diff --git a/csharp/ql/test/library-tests/dataflow/global/GlobalDataFlow.cs b/csharp/ql/test/library-tests/dataflow/global/GlobalDataFlow.cs index 897f56d24e5..f62f0915a21 100644 --- a/csharp/ql/test/library-tests/dataflow/global/GlobalDataFlow.cs +++ b/csharp/ql/test/library-tests/dataflow/global/GlobalDataFlow.cs @@ -235,15 +235,17 @@ public class DataFlow public async void M3() { // async await, tainted - var sink41 = Task.Run(() => "taint source"); + var task = Task.Run(() => "taint source"); + var sink41 = task.Result; Check(sink41); - var sink42 = await sink41; + var sink42 = await task; Check(sink42); // async await, not tainted - var nonSink0 = Task.Run(() => ""); + task = Task.Run(() => ""); + var nonSink0 = task.Result; Check(nonSink0); - var nonSink1 = await nonSink0; + var nonSink1 = await task; Check(nonSink1); } diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected b/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected index fa619f3ddac..fd045c5e8d5 100644 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected +++ b/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected @@ -41,20 +41,20 @@ | GlobalDataFlow.cs:214:15:214:20 | access to local variable sink24 | | GlobalDataFlow.cs:216:15:216:20 | access to local variable sink25 | | GlobalDataFlow.cs:218:15:218:20 | access to local variable sink26 | -| GlobalDataFlow.cs:239:15:239:20 | access to local variable sink41 | -| GlobalDataFlow.cs:241:15:241:20 | access to local variable sink42 | -| GlobalDataFlow.cs:255:15:255:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:260:15:260:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:265:15:265:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:270:15:270:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:275:15:275:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:280:15:280:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:285:15:285:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:312:15:312:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:318:15:318:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:324:15:324:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:399:15:399:20 | access to local variable sink11 | -| GlobalDataFlow.cs:422:41:422:46 | access to local variable sink20 | +| GlobalDataFlow.cs:240:15:240:20 | access to local variable sink41 | +| GlobalDataFlow.cs:242:15:242:20 | access to local variable sink42 | +| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:272:15:272:24 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:277:15:277:24 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:282:15:282:24 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:287:15:287:24 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:314:15:314:24 | access to parameter sinkParam8 | +| GlobalDataFlow.cs:320:15:320:24 | access to parameter sinkParam9 | +| GlobalDataFlow.cs:326:15:326:25 | access to parameter sinkParam11 | +| GlobalDataFlow.cs:401:15:401:20 | access to local variable sink11 | +| GlobalDataFlow.cs:424:41:424:46 | access to local variable sink20 | | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | | Splitting.cs:11:19:11:19 | access to local variable x | diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected index 6dccf5b7da1..33fa1d1750b 100644 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected +++ b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected @@ -55,7 +55,7 @@ edges | GlobalDataFlow.cs:36:13:36:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:36:13:36:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:36:13:36:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:36:13:36:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:252:26:252:35 | sinkParam0 : String | +| GlobalDataFlow.cs:36:13:36:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | | GlobalDataFlow.cs:38:35:38:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:46:13:46:30 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:38:35:38:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:20:53:37 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:38:35:38:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:28:54:45 | access to property SinkProperty0 : String | @@ -64,7 +64,7 @@ edges | GlobalDataFlow.cs:38:35:38:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:38:35:38:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:38:35:38:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:38:35:38:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:258:26:258:35 | sinkParam1 : String | +| GlobalDataFlow.cs:38:35:38:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam1 : String | | GlobalDataFlow.cs:45:30:45:39 | sinkParam2 : String | GlobalDataFlow.cs:45:50:45:59 | access to parameter sinkParam2 | | GlobalDataFlow.cs:46:13:46:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:30:45:39 | sinkParam2 : String | | GlobalDataFlow.cs:46:13:46:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:20:53:37 | access to property SinkProperty0 : String | @@ -80,31 +80,31 @@ edges | GlobalDataFlow.cs:53:20:53:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:20:53:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:20:53:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:20:53:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:377:41:377:41 | x : String | +| GlobalDataFlow.cs:53:20:53:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:379:41:379:41 | x : String | | GlobalDataFlow.cs:54:15:54:15 | x : String | GlobalDataFlow.cs:54:24:54:24 | access to parameter x : String | -| GlobalDataFlow.cs:54:24:54:24 | access to parameter x : String | GlobalDataFlow.cs:268:26:268:35 | sinkParam4 : String | +| GlobalDataFlow.cs:54:24:54:24 | access to parameter x : String | GlobalDataFlow.cs:270:26:270:35 | sinkParam4 : String | | GlobalDataFlow.cs:54:28:54:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:44:55:61 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:28:54:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:56:28:56:45 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:28:54:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:28:54:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:28:54:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:28:54:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:377:41:377:41 | x : String | +| GlobalDataFlow.cs:54:28:54:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:379:41:379:41 | x : String | | GlobalDataFlow.cs:55:44:55:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:56:28:56:45 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:55:44:55:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:55:44:55:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:55:44:55:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:44:55:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:391:52:391:52 | x : String | +| GlobalDataFlow.cs:55:44:55:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:393:52:393:52 | x : String | | GlobalDataFlow.cs:56:28:56:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:56:28:56:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:56:28:56:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:56:28:56:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:391:52:391:52 | x : String | +| GlobalDataFlow.cs:56:28:56:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:393:52:393:52 | x : String | | GlobalDataFlow.cs:57:37:57:37 | x : String | GlobalDataFlow.cs:57:46:57:46 | access to parameter x : String | -| GlobalDataFlow.cs:57:46:57:46 | access to parameter x : String | GlobalDataFlow.cs:283:26:283:35 | sinkParam7 : String | +| GlobalDataFlow.cs:57:46:57:46 | access to parameter x : String | GlobalDataFlow.cs:285:26:285:35 | sinkParam7 : String | | GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:391:52:391:52 | x : String | +| GlobalDataFlow.cs:58:35:58:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:393:52:393:52 | x : String | | GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:422:9:422:11 | value : String | +| GlobalDataFlow.cs:65:22:65:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:424:9:424:11 | value : String | | GlobalDataFlow.cs:71:21:71:46 | call to method Return : String | GlobalDataFlow.cs:72:15:72:19 | access to local variable sink0 | | GlobalDataFlow.cs:71:21:71:46 | call to method Return : String | GlobalDataFlow.cs:73:94:73:98 | access to local variable sink0 : String | | GlobalDataFlow.cs:71:28:71:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:71:21:71:46 | call to method Return : String | @@ -133,7 +133,7 @@ edges | GlobalDataFlow.cs:83:22:83:95 | call to method First : String | GlobalDataFlow.cs:95:15:95:20 | access to local variable sink21 | | GlobalDataFlow.cs:83:22:83:95 | call to method First : String | GlobalDataFlow.cs:98:15:98:20 | access to local variable sink22 | | GlobalDataFlow.cs:83:23:83:66 | (...) ... [[]] : String | GlobalDataFlow.cs:83:22:83:87 | call to method Select [[]] : String | -| GlobalDataFlow.cs:83:23:83:66 | (...) ... [[]] : String | GlobalDataFlow.cs:310:31:310:40 | sinkParam8 : String | +| GlobalDataFlow.cs:83:23:83:66 | (...) ... [[]] : String | GlobalDataFlow.cs:312:31:312:40 | sinkParam8 : String | | GlobalDataFlow.cs:83:57:83:66 | { ..., ... } [[]] : String | GlobalDataFlow.cs:83:23:83:66 | (...) ... [[]] : String | | GlobalDataFlow.cs:83:59:83:64 | access to local variable sink13 : String | GlobalDataFlow.cs:83:57:83:66 | { ..., ... } [[]] : String | | GlobalDataFlow.cs:85:22:85:128 | call to method Zip [[]] : String | GlobalDataFlow.cs:85:22:85:136 | call to method First : String | @@ -174,7 +174,7 @@ edges | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:208:44:208:61 | { ..., ... } [[]] : String | | GlobalDataFlow.cs:211:35:211:45 | sinkParam10 : String | GlobalDataFlow.cs:211:58:211:68 | access to parameter sinkParam10 | | GlobalDataFlow.cs:212:71:212:71 | x : String | GlobalDataFlow.cs:212:89:212:89 | access to parameter x : String | -| GlobalDataFlow.cs:212:89:212:89 | access to parameter x : String | GlobalDataFlow.cs:316:32:316:41 | sinkParam9 : String | +| GlobalDataFlow.cs:212:89:212:89 | access to parameter x : String | GlobalDataFlow.cs:318:32:318:41 | sinkParam9 : String | | GlobalDataFlow.cs:213:22:213:28 | access to local variable tainted [[]] : String | GlobalDataFlow.cs:211:35:211:45 | sinkParam10 : String | | GlobalDataFlow.cs:213:22:213:28 | access to local variable tainted [[]] : String | GlobalDataFlow.cs:213:22:213:39 | call to method Select [[]] : String | | GlobalDataFlow.cs:213:22:213:39 | call to method Select [[]] : String | GlobalDataFlow.cs:213:22:213:47 | call to method First : String | @@ -184,45 +184,45 @@ edges | GlobalDataFlow.cs:215:22:215:39 | call to method Select [[]] : String | GlobalDataFlow.cs:215:22:215:47 | call to method First : String | | GlobalDataFlow.cs:215:22:215:47 | call to method First : String | GlobalDataFlow.cs:216:15:216:20 | access to local variable sink25 | | GlobalDataFlow.cs:217:22:217:28 | access to local variable tainted [[]] : String | GlobalDataFlow.cs:217:22:217:49 | call to method Select [[]] : String | -| GlobalDataFlow.cs:217:22:217:28 | access to local variable tainted [[]] : String | GlobalDataFlow.cs:322:32:322:42 | sinkParam11 : String | +| GlobalDataFlow.cs:217:22:217:28 | access to local variable tainted [[]] : String | GlobalDataFlow.cs:324:32:324:42 | sinkParam11 : String | | GlobalDataFlow.cs:217:22:217:49 | call to method Select [[]] : String | GlobalDataFlow.cs:217:22:217:57 | call to method First : String | | GlobalDataFlow.cs:217:22:217:57 | call to method First : String | GlobalDataFlow.cs:218:15:218:20 | access to local variable sink26 | -| GlobalDataFlow.cs:238:37:238:50 | "taint source" : String | GlobalDataFlow.cs:239:15:239:20 | access to local variable sink41 | -| GlobalDataFlow.cs:238:37:238:50 | "taint source" : String | GlobalDataFlow.cs:241:15:241:20 | access to local variable sink42 | -| GlobalDataFlow.cs:252:26:252:35 | sinkParam0 : String | GlobalDataFlow.cs:254:16:254:25 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:252:26:252:35 | sinkParam0 : String | GlobalDataFlow.cs:255:15:255:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:254:16:254:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:252:26:252:35 | sinkParam0 : String | -| GlobalDataFlow.cs:258:26:258:35 | sinkParam1 : String | GlobalDataFlow.cs:260:15:260:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:263:26:263:35 | sinkParam3 : String | GlobalDataFlow.cs:265:15:265:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:268:26:268:35 | sinkParam4 : String | GlobalDataFlow.cs:270:15:270:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:273:26:273:35 | sinkParam5 : String | GlobalDataFlow.cs:275:15:275:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:278:26:278:35 | sinkParam6 : String | GlobalDataFlow.cs:280:15:280:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:283:26:283:35 | sinkParam7 : String | GlobalDataFlow.cs:285:15:285:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:310:31:310:40 | sinkParam8 : String | GlobalDataFlow.cs:312:15:312:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:316:32:316:41 | sinkParam9 : String | GlobalDataFlow.cs:318:15:318:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:322:32:322:42 | sinkParam11 : String | GlobalDataFlow.cs:324:15:324:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:336:16:336:29 | "taint source" : String | GlobalDataFlow.cs:154:21:154:25 | call to method Out : String | -| GlobalDataFlow.cs:336:16:336:29 | "taint source" : String | GlobalDataFlow.cs:190:22:190:42 | object creation of type Lazy [Value] : String | -| GlobalDataFlow.cs:341:9:341:26 | SSA def(x) : String | GlobalDataFlow.cs:157:20:157:24 | SSA def(sink7) : String | -| GlobalDataFlow.cs:341:13:341:26 | "taint source" : String | GlobalDataFlow.cs:341:9:341:26 | SSA def(x) : String | -| GlobalDataFlow.cs:346:9:346:26 | SSA def(x) : String | GlobalDataFlow.cs:160:20:160:24 | SSA def(sink8) : String | -| GlobalDataFlow.cs:346:13:346:26 | "taint source" : String | GlobalDataFlow.cs:346:9:346:26 | SSA def(x) : String | -| GlobalDataFlow.cs:352:22:352:35 | "taint source" : String | GlobalDataFlow.cs:162:22:162:31 | call to method OutYield [[]] : String | -| GlobalDataFlow.cs:377:41:377:41 | x : String | GlobalDataFlow.cs:379:11:379:11 | access to parameter x : String | -| GlobalDataFlow.cs:377:41:377:41 | x : String | GlobalDataFlow.cs:379:11:379:11 | access to parameter x : String | -| GlobalDataFlow.cs:379:11:379:11 | access to parameter x : String | GlobalDataFlow.cs:54:15:54:15 | x : String | -| GlobalDataFlow.cs:379:11:379:11 | access to parameter x : String | GlobalDataFlow.cs:263:26:263:35 | sinkParam3 : String | -| GlobalDataFlow.cs:391:52:391:52 | x : String | GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | -| GlobalDataFlow.cs:391:52:391:52 | x : String | GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | -| GlobalDataFlow.cs:391:52:391:52 | x : String | GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | -| GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | GlobalDataFlow.cs:57:37:57:37 | x : String | -| GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | GlobalDataFlow.cs:273:26:273:35 | sinkParam5 : String | -| GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | GlobalDataFlow.cs:278:26:278:35 | sinkParam6 : String | -| GlobalDataFlow.cs:396:39:396:45 | tainted : String | GlobalDataFlow.cs:399:15:399:20 | access to local variable sink11 | -| GlobalDataFlow.cs:396:39:396:45 | tainted : String | GlobalDataFlow.cs:400:16:400:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:400:16:400:21 | access to local variable sink11 : String | GlobalDataFlow.cs:164:22:164:43 | call to method TaintedParam : String | -| GlobalDataFlow.cs:422:9:422:11 | value : String | GlobalDataFlow.cs:422:41:422:46 | access to local variable sink20 | -| GlobalDataFlow.cs:433:22:433:35 | "taint source" : String | GlobalDataFlow.cs:198:22:198:32 | access to property OutProperty : String | +| GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | GlobalDataFlow.cs:240:15:240:20 | access to local variable sink41 | +| GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | GlobalDataFlow.cs:242:15:242:20 | access to local variable sink42 | +| GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | GlobalDataFlow.cs:256:16:256:25 | access to parameter sinkParam0 : String | +| GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:256:16:256:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | +| GlobalDataFlow.cs:260:26:260:35 | sinkParam1 : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:265:26:265:35 | sinkParam3 : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:270:26:270:35 | sinkParam4 : String | GlobalDataFlow.cs:272:15:272:24 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:275:26:275:35 | sinkParam5 : String | GlobalDataFlow.cs:277:15:277:24 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:280:26:280:35 | sinkParam6 : String | GlobalDataFlow.cs:282:15:282:24 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:285:26:285:35 | sinkParam7 : String | GlobalDataFlow.cs:287:15:287:24 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:312:31:312:40 | sinkParam8 : String | GlobalDataFlow.cs:314:15:314:24 | access to parameter sinkParam8 | +| GlobalDataFlow.cs:318:32:318:41 | sinkParam9 : String | GlobalDataFlow.cs:320:15:320:24 | access to parameter sinkParam9 | +| GlobalDataFlow.cs:324:32:324:42 | sinkParam11 : String | GlobalDataFlow.cs:326:15:326:25 | access to parameter sinkParam11 | +| GlobalDataFlow.cs:338:16:338:29 | "taint source" : String | GlobalDataFlow.cs:154:21:154:25 | call to method Out : String | +| GlobalDataFlow.cs:338:16:338:29 | "taint source" : String | GlobalDataFlow.cs:190:22:190:42 | object creation of type Lazy [Value] : String | +| GlobalDataFlow.cs:343:9:343:26 | SSA def(x) : String | GlobalDataFlow.cs:157:20:157:24 | SSA def(sink7) : String | +| GlobalDataFlow.cs:343:13:343:26 | "taint source" : String | GlobalDataFlow.cs:343:9:343:26 | SSA def(x) : String | +| GlobalDataFlow.cs:348:9:348:26 | SSA def(x) : String | GlobalDataFlow.cs:160:20:160:24 | SSA def(sink8) : String | +| GlobalDataFlow.cs:348:13:348:26 | "taint source" : String | GlobalDataFlow.cs:348:9:348:26 | SSA def(x) : String | +| GlobalDataFlow.cs:354:22:354:35 | "taint source" : String | GlobalDataFlow.cs:162:22:162:31 | call to method OutYield [[]] : String | +| GlobalDataFlow.cs:379:41:379:41 | x : String | GlobalDataFlow.cs:381:11:381:11 | access to parameter x : String | +| GlobalDataFlow.cs:379:41:379:41 | x : String | GlobalDataFlow.cs:381:11:381:11 | access to parameter x : String | +| GlobalDataFlow.cs:381:11:381:11 | access to parameter x : String | GlobalDataFlow.cs:54:15:54:15 | x : String | +| GlobalDataFlow.cs:381:11:381:11 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam3 : String | +| GlobalDataFlow.cs:393:52:393:52 | x : String | GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | +| GlobalDataFlow.cs:393:52:393:52 | x : String | GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | +| GlobalDataFlow.cs:393:52:393:52 | x : String | GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | +| GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | GlobalDataFlow.cs:57:37:57:37 | x : String | +| GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:35 | sinkParam5 : String | +| GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | GlobalDataFlow.cs:280:26:280:35 | sinkParam6 : String | +| GlobalDataFlow.cs:398:39:398:45 | tainted : String | GlobalDataFlow.cs:401:15:401:20 | access to local variable sink11 | +| GlobalDataFlow.cs:398:39:398:45 | tainted : String | GlobalDataFlow.cs:402:16:402:21 | access to local variable sink11 : String | +| GlobalDataFlow.cs:402:16:402:21 | access to local variable sink11 : String | GlobalDataFlow.cs:164:22:164:43 | call to method TaintedParam : String | +| GlobalDataFlow.cs:424:9:424:11 | value : String | GlobalDataFlow.cs:424:41:424:46 | access to local variable sink20 | +| GlobalDataFlow.cs:435:22:435:35 | "taint source" : String | GlobalDataFlow.cs:198:22:198:32 | access to property OutProperty : String | | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | @@ -381,52 +381,52 @@ nodes | GlobalDataFlow.cs:217:22:217:49 | call to method Select [[]] : String | semmle.label | call to method Select [[]] : String | | GlobalDataFlow.cs:217:22:217:57 | call to method First : String | semmle.label | call to method First : String | | GlobalDataFlow.cs:218:15:218:20 | access to local variable sink26 | semmle.label | access to local variable sink26 | -| GlobalDataFlow.cs:238:37:238:50 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:239:15:239:20 | access to local variable sink41 | semmle.label | access to local variable sink41 | -| GlobalDataFlow.cs:241:15:241:20 | access to local variable sink42 | semmle.label | access to local variable sink42 | -| GlobalDataFlow.cs:252:26:252:35 | sinkParam0 : String | semmle.label | sinkParam0 : String | -| GlobalDataFlow.cs:254:16:254:25 | access to parameter sinkParam0 : String | semmle.label | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:255:15:255:24 | access to parameter sinkParam0 | semmle.label | access to parameter sinkParam0 | -| GlobalDataFlow.cs:258:26:258:35 | sinkParam1 : String | semmle.label | sinkParam1 : String | -| GlobalDataFlow.cs:260:15:260:24 | access to parameter sinkParam1 | semmle.label | access to parameter sinkParam1 | -| GlobalDataFlow.cs:263:26:263:35 | sinkParam3 : String | semmle.label | sinkParam3 : String | -| GlobalDataFlow.cs:265:15:265:24 | access to parameter sinkParam3 | semmle.label | access to parameter sinkParam3 | -| GlobalDataFlow.cs:268:26:268:35 | sinkParam4 : String | semmle.label | sinkParam4 : String | -| GlobalDataFlow.cs:270:15:270:24 | access to parameter sinkParam4 | semmle.label | access to parameter sinkParam4 | -| GlobalDataFlow.cs:273:26:273:35 | sinkParam5 : String | semmle.label | sinkParam5 : String | -| GlobalDataFlow.cs:275:15:275:24 | access to parameter sinkParam5 | semmle.label | access to parameter sinkParam5 | -| GlobalDataFlow.cs:278:26:278:35 | sinkParam6 : String | semmle.label | sinkParam6 : String | -| GlobalDataFlow.cs:280:15:280:24 | access to parameter sinkParam6 | semmle.label | access to parameter sinkParam6 | -| GlobalDataFlow.cs:283:26:283:35 | sinkParam7 : String | semmle.label | sinkParam7 : String | -| GlobalDataFlow.cs:285:15:285:24 | access to parameter sinkParam7 | semmle.label | access to parameter sinkParam7 | -| GlobalDataFlow.cs:310:31:310:40 | sinkParam8 : String | semmle.label | sinkParam8 : String | -| GlobalDataFlow.cs:312:15:312:24 | access to parameter sinkParam8 | semmle.label | access to parameter sinkParam8 | -| GlobalDataFlow.cs:316:32:316:41 | sinkParam9 : String | semmle.label | sinkParam9 : String | -| GlobalDataFlow.cs:318:15:318:24 | access to parameter sinkParam9 | semmle.label | access to parameter sinkParam9 | -| GlobalDataFlow.cs:322:32:322:42 | sinkParam11 : String | semmle.label | sinkParam11 : String | -| GlobalDataFlow.cs:324:15:324:25 | access to parameter sinkParam11 | semmle.label | access to parameter sinkParam11 | -| GlobalDataFlow.cs:336:16:336:29 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:341:9:341:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | -| GlobalDataFlow.cs:341:13:341:26 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:346:9:346:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | -| GlobalDataFlow.cs:346:13:346:26 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:352:22:352:35 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:377:41:377:41 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:377:41:377:41 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:379:11:379:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:379:11:379:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:391:52:391:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:391:52:391:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:391:52:391:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:393:11:393:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:396:39:396:45 | tainted : String | semmle.label | tainted : String | -| GlobalDataFlow.cs:399:15:399:20 | access to local variable sink11 | semmle.label | access to local variable sink11 | -| GlobalDataFlow.cs:400:16:400:21 | access to local variable sink11 : String | semmle.label | access to local variable sink11 : String | -| GlobalDataFlow.cs:422:9:422:11 | value : String | semmle.label | value : String | -| GlobalDataFlow.cs:422:41:422:46 | access to local variable sink20 | semmle.label | access to local variable sink20 | -| GlobalDataFlow.cs:433:22:433:35 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:240:15:240:20 | access to local variable sink41 | semmle.label | access to local variable sink41 | +| GlobalDataFlow.cs:242:15:242:20 | access to local variable sink42 | semmle.label | access to local variable sink42 | +| GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | semmle.label | sinkParam0 : String | +| GlobalDataFlow.cs:256:16:256:25 | access to parameter sinkParam0 : String | semmle.label | access to parameter sinkParam0 : String | +| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam0 | semmle.label | access to parameter sinkParam0 | +| GlobalDataFlow.cs:260:26:260:35 | sinkParam1 : String | semmle.label | sinkParam1 : String | +| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam1 | semmle.label | access to parameter sinkParam1 | +| GlobalDataFlow.cs:265:26:265:35 | sinkParam3 : String | semmle.label | sinkParam3 : String | +| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam3 | semmle.label | access to parameter sinkParam3 | +| GlobalDataFlow.cs:270:26:270:35 | sinkParam4 : String | semmle.label | sinkParam4 : String | +| GlobalDataFlow.cs:272:15:272:24 | access to parameter sinkParam4 | semmle.label | access to parameter sinkParam4 | +| GlobalDataFlow.cs:275:26:275:35 | sinkParam5 : String | semmle.label | sinkParam5 : String | +| GlobalDataFlow.cs:277:15:277:24 | access to parameter sinkParam5 | semmle.label | access to parameter sinkParam5 | +| GlobalDataFlow.cs:280:26:280:35 | sinkParam6 : String | semmle.label | sinkParam6 : String | +| GlobalDataFlow.cs:282:15:282:24 | access to parameter sinkParam6 | semmle.label | access to parameter sinkParam6 | +| GlobalDataFlow.cs:285:26:285:35 | sinkParam7 : String | semmle.label | sinkParam7 : String | +| GlobalDataFlow.cs:287:15:287:24 | access to parameter sinkParam7 | semmle.label | access to parameter sinkParam7 | +| GlobalDataFlow.cs:312:31:312:40 | sinkParam8 : String | semmle.label | sinkParam8 : String | +| GlobalDataFlow.cs:314:15:314:24 | access to parameter sinkParam8 | semmle.label | access to parameter sinkParam8 | +| GlobalDataFlow.cs:318:32:318:41 | sinkParam9 : String | semmle.label | sinkParam9 : String | +| GlobalDataFlow.cs:320:15:320:24 | access to parameter sinkParam9 | semmle.label | access to parameter sinkParam9 | +| GlobalDataFlow.cs:324:32:324:42 | sinkParam11 : String | semmle.label | sinkParam11 : String | +| GlobalDataFlow.cs:326:15:326:25 | access to parameter sinkParam11 | semmle.label | access to parameter sinkParam11 | +| GlobalDataFlow.cs:338:16:338:29 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:343:9:343:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | +| GlobalDataFlow.cs:343:13:343:26 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:348:9:348:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | +| GlobalDataFlow.cs:348:13:348:26 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:354:22:354:35 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:379:41:379:41 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:379:41:379:41 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:381:11:381:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:381:11:381:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:393:52:393:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:393:52:393:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:393:52:393:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:395:11:395:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:398:39:398:45 | tainted : String | semmle.label | tainted : String | +| GlobalDataFlow.cs:401:15:401:20 | access to local variable sink11 | semmle.label | access to local variable sink11 | +| GlobalDataFlow.cs:402:16:402:21 | access to local variable sink11 : String | semmle.label | access to local variable sink11 : String | +| GlobalDataFlow.cs:424:9:424:11 | value : String | semmle.label | value : String | +| GlobalDataFlow.cs:424:41:424:46 | access to local variable sink20 | semmle.label | access to local variable sink20 | +| GlobalDataFlow.cs:435:22:435:35 | "taint source" : String | semmle.label | "taint source" : String | | Splitting.cs:3:28:3:34 | tainted : String | semmle.label | tainted : String | | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | semmle.label | [b (line 3): false] call to method Return : String | | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | semmle.label | [b (line 3): true] call to method Return : String | @@ -479,32 +479,32 @@ nodes | GlobalDataFlow.cs:98:15:98:20 | access to local variable sink22 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:98:15:98:20 | access to local variable sink22 | access to local variable sink22 | | GlobalDataFlow.cs:137:15:137:19 | access to local variable sink4 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:137:15:137:19 | access to local variable sink4 | access to local variable sink4 | | GlobalDataFlow.cs:145:15:145:19 | access to local variable sink5 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:145:15:145:19 | access to local variable sink5 | access to local variable sink5 | -| GlobalDataFlow.cs:155:15:155:19 | access to local variable sink6 | GlobalDataFlow.cs:336:16:336:29 | "taint source" : String | GlobalDataFlow.cs:155:15:155:19 | access to local variable sink6 | access to local variable sink6 | -| GlobalDataFlow.cs:158:15:158:19 | access to local variable sink7 | GlobalDataFlow.cs:341:13:341:26 | "taint source" : String | GlobalDataFlow.cs:158:15:158:19 | access to local variable sink7 | access to local variable sink7 | -| GlobalDataFlow.cs:161:15:161:19 | access to local variable sink8 | GlobalDataFlow.cs:346:13:346:26 | "taint source" : String | GlobalDataFlow.cs:161:15:161:19 | access to local variable sink8 | access to local variable sink8 | -| GlobalDataFlow.cs:163:15:163:20 | access to local variable sink12 | GlobalDataFlow.cs:352:22:352:35 | "taint source" : String | GlobalDataFlow.cs:163:15:163:20 | access to local variable sink12 | access to local variable sink12 | -| GlobalDataFlow.cs:165:15:165:20 | access to local variable sink23 | GlobalDataFlow.cs:396:39:396:45 | tainted : String | GlobalDataFlow.cs:165:15:165:20 | access to local variable sink23 | access to local variable sink23 | +| GlobalDataFlow.cs:155:15:155:19 | access to local variable sink6 | GlobalDataFlow.cs:338:16:338:29 | "taint source" : String | GlobalDataFlow.cs:155:15:155:19 | access to local variable sink6 | access to local variable sink6 | +| GlobalDataFlow.cs:158:15:158:19 | access to local variable sink7 | GlobalDataFlow.cs:343:13:343:26 | "taint source" : String | GlobalDataFlow.cs:158:15:158:19 | access to local variable sink7 | access to local variable sink7 | +| GlobalDataFlow.cs:161:15:161:19 | access to local variable sink8 | GlobalDataFlow.cs:348:13:348:26 | "taint source" : String | GlobalDataFlow.cs:161:15:161:19 | access to local variable sink8 | access to local variable sink8 | +| GlobalDataFlow.cs:163:15:163:20 | access to local variable sink12 | GlobalDataFlow.cs:354:22:354:35 | "taint source" : String | GlobalDataFlow.cs:163:15:163:20 | access to local variable sink12 | access to local variable sink12 | +| GlobalDataFlow.cs:165:15:165:20 | access to local variable sink23 | GlobalDataFlow.cs:398:39:398:45 | tainted : String | GlobalDataFlow.cs:165:15:165:20 | access to local variable sink23 | access to local variable sink23 | | GlobalDataFlow.cs:182:15:182:19 | access to local variable sink9 | GlobalDataFlow.cs:180:35:180:48 | "taint source" : String | GlobalDataFlow.cs:182:15:182:19 | access to local variable sink9 | access to local variable sink9 | -| GlobalDataFlow.cs:191:15:191:20 | access to local variable sink10 | GlobalDataFlow.cs:336:16:336:29 | "taint source" : String | GlobalDataFlow.cs:191:15:191:20 | access to local variable sink10 | access to local variable sink10 | -| GlobalDataFlow.cs:199:15:199:20 | access to local variable sink19 | GlobalDataFlow.cs:433:22:433:35 | "taint source" : String | GlobalDataFlow.cs:199:15:199:20 | access to local variable sink19 | access to local variable sink19 | +| GlobalDataFlow.cs:191:15:191:20 | access to local variable sink10 | GlobalDataFlow.cs:338:16:338:29 | "taint source" : String | GlobalDataFlow.cs:191:15:191:20 | access to local variable sink10 | access to local variable sink10 | +| GlobalDataFlow.cs:199:15:199:20 | access to local variable sink19 | GlobalDataFlow.cs:435:22:435:35 | "taint source" : String | GlobalDataFlow.cs:199:15:199:20 | access to local variable sink19 | access to local variable sink19 | | GlobalDataFlow.cs:211:58:211:68 | access to parameter sinkParam10 | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:211:58:211:68 | access to parameter sinkParam10 | access to parameter sinkParam10 | | GlobalDataFlow.cs:214:15:214:20 | access to local variable sink24 | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:214:15:214:20 | access to local variable sink24 | access to local variable sink24 | | GlobalDataFlow.cs:216:15:216:20 | access to local variable sink25 | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:216:15:216:20 | access to local variable sink25 | access to local variable sink25 | | GlobalDataFlow.cs:218:15:218:20 | access to local variable sink26 | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:218:15:218:20 | access to local variable sink26 | access to local variable sink26 | -| GlobalDataFlow.cs:239:15:239:20 | access to local variable sink41 | GlobalDataFlow.cs:238:37:238:50 | "taint source" : String | GlobalDataFlow.cs:239:15:239:20 | access to local variable sink41 | access to local variable sink41 | -| GlobalDataFlow.cs:241:15:241:20 | access to local variable sink42 | GlobalDataFlow.cs:238:37:238:50 | "taint source" : String | GlobalDataFlow.cs:241:15:241:20 | access to local variable sink42 | access to local variable sink42 | -| GlobalDataFlow.cs:255:15:255:24 | access to parameter sinkParam0 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:255:15:255:24 | access to parameter sinkParam0 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:260:15:260:24 | access to parameter sinkParam1 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:260:15:260:24 | access to parameter sinkParam1 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:265:15:265:24 | access to parameter sinkParam3 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:265:15:265:24 | access to parameter sinkParam3 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:270:15:270:24 | access to parameter sinkParam4 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:270:15:270:24 | access to parameter sinkParam4 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:275:15:275:24 | access to parameter sinkParam5 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:275:15:275:24 | access to parameter sinkParam5 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:280:15:280:24 | access to parameter sinkParam6 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:280:15:280:24 | access to parameter sinkParam6 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:285:15:285:24 | access to parameter sinkParam7 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:285:15:285:24 | access to parameter sinkParam7 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:312:15:312:24 | access to parameter sinkParam8 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:312:15:312:24 | access to parameter sinkParam8 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:318:15:318:24 | access to parameter sinkParam9 | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:318:15:318:24 | access to parameter sinkParam9 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:324:15:324:25 | access to parameter sinkParam11 | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:324:15:324:25 | access to parameter sinkParam11 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:399:15:399:20 | access to local variable sink11 | GlobalDataFlow.cs:396:39:396:45 | tainted : String | GlobalDataFlow.cs:399:15:399:20 | access to local variable sink11 | access to local variable sink11 | -| GlobalDataFlow.cs:422:41:422:46 | access to local variable sink20 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:422:41:422:46 | access to local variable sink20 | access to local variable sink20 | +| GlobalDataFlow.cs:240:15:240:20 | access to local variable sink41 | GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | GlobalDataFlow.cs:240:15:240:20 | access to local variable sink41 | access to local variable sink41 | +| GlobalDataFlow.cs:242:15:242:20 | access to local variable sink42 | GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | GlobalDataFlow.cs:242:15:242:20 | access to local variable sink42 | access to local variable sink42 | +| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam0 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam0 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam1 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam1 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam3 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam3 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:272:15:272:24 | access to parameter sinkParam4 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:272:15:272:24 | access to parameter sinkParam4 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:277:15:277:24 | access to parameter sinkParam5 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:277:15:277:24 | access to parameter sinkParam5 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:282:15:282:24 | access to parameter sinkParam6 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:282:15:282:24 | access to parameter sinkParam6 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:287:15:287:24 | access to parameter sinkParam7 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:287:15:287:24 | access to parameter sinkParam7 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:314:15:314:24 | access to parameter sinkParam8 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:314:15:314:24 | access to parameter sinkParam8 | access to parameter sinkParam8 | +| GlobalDataFlow.cs:320:15:320:24 | access to parameter sinkParam9 | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:320:15:320:24 | access to parameter sinkParam9 | access to parameter sinkParam9 | +| GlobalDataFlow.cs:326:15:326:25 | access to parameter sinkParam11 | GlobalDataFlow.cs:208:46:208:59 | "taint source" : String | GlobalDataFlow.cs:326:15:326:25 | access to parameter sinkParam11 | access to parameter sinkParam11 | +| GlobalDataFlow.cs:401:15:401:20 | access to local variable sink11 | GlobalDataFlow.cs:398:39:398:45 | tainted : String | GlobalDataFlow.cs:401:15:401:20 | access to local variable sink11 | access to local variable sink11 | +| GlobalDataFlow.cs:424:41:424:46 | access to local variable sink20 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:424:41:424:46 | access to local variable sink20 | access to local variable sink20 | | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | [b (line 3): false] access to local variable x | | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | [b (line 3): true] access to local variable x | | Splitting.cs:11:19:11:19 | access to local variable x | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:11:19:11:19 | access to local variable x | access to local variable x | From c0b251ad9ef07561fc5ebda9285a843e40bff912 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Sun, 27 Sep 2020 19:43:41 +0200 Subject: [PATCH 197/411] C#: Precise data-flow for `System.Threading.Tasks` --- .../csharp/dataflow/LibraryTypeDataFlow.qll | 133 ++++++++------ .../dataflow/internal/DataFlowPrivate.qll | 19 +- .../internal/TaintTrackingPrivate.qll | 4 + .../dataflow/global/DataFlowPath.expected | 14 +- .../global/TaintTrackingPath.expected | 14 +- .../library/LibraryTypeDataFlow.expected | 172 +++++++++--------- 6 files changed, 206 insertions(+), 150 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll index fac6c60343e..5b63c2c9726 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll @@ -34,6 +34,8 @@ private newtype TAccessPath = or tail = AccessPath::singleton(_) and head instanceof ElementContent + or + tail = AccessPath::element() } /** An access path. */ @@ -1658,7 +1660,6 @@ class SystemThreadingTasksTaskFlow extends LibraryTypeDataFlow, SystemThreadingT ( m.hasName("ContinueWith") and sourceAp = AccessPath::empty() and - sinkAp = AccessPath::empty() and ( // flow from supplied state to supplied delegate exists(ConstructedDelegateType delegate, int i, int j, int k | @@ -1670,7 +1671,8 @@ class SystemThreadingTasksTaskFlow extends LibraryTypeDataFlow, SystemThreadingT ) and delegate.getTypeArgument(k) instanceof ObjectType and source = TCallableFlowSourceArg(i) and - sink = getDelegateFlowSinkArg(m, j, k) + sink = getDelegateFlowSinkArg(m, j, k) and + sinkAp = AccessPath::empty() ) or // flow out of supplied function @@ -1678,36 +1680,35 @@ class SystemThreadingTasksTaskFlow extends LibraryTypeDataFlow, SystemThreadingT m.getParameter(i).getType() = func and func.getUnboundGeneric() instanceof SystemFuncDelegateType and source = getDelegateFlowSourceArg(m, i) and - sink = TCallableFlowSinkReturn() + sink = TCallableFlowSinkReturn() and + sinkAp = AccessPath::property(any(SystemThreadingTasksTaskTClass c).getResultProperty()) ) ) or m.hasName("FromResult") and + source = TCallableFlowSourceArg(0) and sourceAp = AccessPath::empty() and - sinkAp = AccessPath::empty() and - ( - source = TCallableFlowSourceArg(0) and - sink = TCallableFlowSinkReturn() - ) + sink = TCallableFlowSinkReturn() and + sinkAp = AccessPath::property(any(SystemThreadingTasksTaskTClass c).getResultProperty()) or m.hasName("Run") and + m.getReturnType() = any(SystemThreadingTasksTaskTClass c).getAConstructedGeneric() and + m.(UnboundGenericMethod).getNumberOfTypeParameters() = 1 and + source = TCallableFlowSourceDelegateArg(0) and sourceAp = AccessPath::empty() and - sinkAp = AccessPath::empty() and - ( - m.getReturnType() = any(SystemThreadingTasksTaskTClass c).getAConstructedGeneric() and - m.(UnboundGenericMethod).getNumberOfTypeParameters() = 1 and - source = TCallableFlowSourceDelegateArg(0) and - sink = TCallableFlowSinkReturn() - ) + sink = TCallableFlowSinkReturn() and + sinkAp = AccessPath::property(any(SystemThreadingTasksTaskTClass c).getResultProperty()) or m.getName().regexpMatch("WhenAll|WhenAny") and - sinkAp = AccessPath::empty() and - ( - m.getReturnType() = any(SystemThreadingTasksTaskTClass c).getAConstructedGeneric() and - m.(UnboundGenericMethod).getNumberOfTypeParameters() = 1 and - source = getFlowSourceArg(m, _, sourceAp) and - sink = TCallableFlowSinkReturn() - ) + m.getReturnType() = any(SystemThreadingTasksTaskTClass c).getAConstructedGeneric() and + m.(UnboundGenericMethod).getNumberOfTypeParameters() = 1 and + source = getFlowSourceArg(m, _, _) and + sourceAp = AccessPath::properties(any(SystemThreadingTasksTaskTClass c).getResultProperty()) and + sink = TCallableFlowSinkReturn() and + sinkAp = + AccessPath::cons(any(PropertyContent c | + c.getProperty() = any(SystemThreadingTasksTaskTClass tc).getResultProperty() + ), AccessPath::element()) ) } } @@ -1717,32 +1718,38 @@ class SystemThreadingTasksTaskTFlow extends LibraryTypeDataFlow { SystemThreadingTasksTaskTFlow() { this instanceof SystemThreadingTasksTaskTClass } override predicate callableFlow( - CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, - boolean preservesValue + CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp, + SourceDeclarationCallable c, boolean preservesValue ) { ( - constructorFlow(source, sink, c) + constructorFlow(source, sourceAp, sink, sinkAp, c) or - methodFlow(source, sink, c) - or - exists(Property p | - propertyFlow(p) and - source = TCallableFlowSourceQualifier() and - sink = TCallableFlowSinkReturn() and - c = p.getGetter() - ) + methodFlow(source, sourceAp, sink, sinkAp, c) ) and preservesValue = true + or + exists(Property p | + p = this.(SystemThreadingTasksTaskTClass).getResultProperty() and + source = TCallableFlowSourceQualifier() and + sourceAp = AccessPath::empty() and + sink = TCallableFlowSinkReturn() and + sinkAp = AccessPath::empty() and + c = p.getGetter() and + preservesValue = false + ) } - private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) { + private predicate constructorFlow( + CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp, + Constructor c + ) { // flow from supplied function into constructed Task c.getDeclaringType() = this and - ( - c.getParameter(0).getType() = any(SystemFuncDelegateType t).getAConstructedGeneric() and - source = TCallableFlowSourceDelegateArg(0) and - sink = TCallableFlowSinkReturn() - ) + c.getParameter(0).getType() = any(SystemFuncDelegateType t).getAConstructedGeneric() and + source = TCallableFlowSourceDelegateArg(0) and + sourceAp = AccessPath::empty() and + sink = TCallableFlowSinkReturn() and + sinkAp = AccessPath::property(this.(SystemThreadingTasksTaskTClass).getResultProperty()) or // flow from supplied state to supplied delegate c.getDeclaringType() = this and @@ -1752,12 +1759,15 @@ class SystemThreadingTasksTaskTFlow extends LibraryTypeDataFlow { func.getUnboundGeneric().(SystemFuncDelegateType).getNumberOfTypeParameters() = 2 and func.getTypeArgument(0) instanceof ObjectType and source = TCallableFlowSourceArg(1) and - sink = getDelegateFlowSinkArg(c, 0, 0) + sourceAp = AccessPath::empty() and + sink = getDelegateFlowSinkArg(c, 0, 0) and + sinkAp = AccessPath::empty() ) } private predicate methodFlow( - CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m + CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp, + SourceDeclarationMethod m ) { m.getDeclaringType() = this and m.hasName("ContinueWith") and @@ -1774,13 +1784,17 @@ class SystemThreadingTasksTaskTFlow extends LibraryTypeDataFlow { delegate.getTypeArgument(j) instanceof ObjectType and m.getParameter(k).getType() instanceof ObjectType and source = TCallableFlowSourceArg(k) and - sink = getDelegateFlowSinkArg(m, i, j) + sourceAp = AccessPath::empty() and + sink = getDelegateFlowSinkArg(m, i, j) and + sinkAp = AccessPath::empty() ) or // flow from this task to supplied delegate delegate.getTypeArgument(j) = this and source = TCallableFlowSourceQualifier() and - sink = getDelegateFlowSinkArg(m, i, j) + sourceAp = AccessPath::empty() and + sink = getDelegateFlowSinkArg(m, i, j) and + sinkAp = AccessPath::empty() ) or // flow out of supplied function @@ -1788,14 +1802,12 @@ class SystemThreadingTasksTaskTFlow extends LibraryTypeDataFlow { m.getParameter(i).getType() = func and func.getUnboundGeneric() instanceof SystemFuncDelegateType and source = getDelegateFlowSourceArg(m, i) and - sink = TCallableFlowSinkReturn() + sourceAp = AccessPath::empty() and + sink = TCallableFlowSinkReturn() and + sinkAp = AccessPath::property(this.(SystemThreadingTasksTaskTClass).getResultProperty()) ) ) } - - private predicate propertyFlow(Property p) { - p = this.(SystemThreadingTasksTaskTClass).getResultProperty() - } } /** Data flow for `System.Threading.Tasks.TaskFactory`(``). */ @@ -1806,15 +1818,16 @@ class SystemThreadingTasksFactoryFlow extends LibraryTypeDataFlow { } override predicate callableFlow( - CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, - boolean preservesValue + CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp, + SourceDeclarationCallable c, boolean preservesValue ) { - methodFlow(source, sink, c) and + methodFlow(source, sourceAp, sink, sinkAp, c) and preservesValue = true } private predicate methodFlow( - CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m + CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp, + SourceDeclarationMethod m ) { m.getDeclaringType() = this and ( @@ -1831,7 +1844,9 @@ class SystemThreadingTasksFactoryFlow extends LibraryTypeDataFlow { delegate.getUnboundGeneric() instanceof SystemFuncDelegateType ) and source = TCallableFlowSourceArg(i) and - sink = getDelegateFlowSinkArg(m, j, k) + sourceAp = AccessPath::empty() and + sink = getDelegateFlowSinkArg(m, j, k) and + sinkAp = AccessPath::empty() ) or // flow out of supplied function @@ -1839,7 +1854,9 @@ class SystemThreadingTasksFactoryFlow extends LibraryTypeDataFlow { m.getParameter(i).getType() = func and func.getUnboundGeneric() instanceof SystemFuncDelegateType and source = getDelegateFlowSourceArg(m, i) and - sink = TCallableFlowSinkReturn() + sourceAp = AccessPath::empty() and + sink = TCallableFlowSinkReturn() and + sinkAp = AccessPath::property(any(SystemThreadingTasksTaskTClass c).getResultProperty()) ) ) or @@ -1855,7 +1872,9 @@ class SystemThreadingTasksFactoryFlow extends LibraryTypeDataFlow { ) and delegate.getTypeArgument(k) instanceof ObjectType and source = TCallableFlowSourceArg(i) and - sink = getDelegateFlowSinkArg(m, j, k) + sourceAp = AccessPath::empty() and + sink = getDelegateFlowSinkArg(m, j, k) and + sinkAp = AccessPath::empty() ) or // flow out of supplied function @@ -1863,7 +1882,9 @@ class SystemThreadingTasksFactoryFlow extends LibraryTypeDataFlow { m.getParameter(i).getType() = func and func.getUnboundGeneric() instanceof SystemFuncDelegateType and source = getDelegateFlowSourceArg(m, i) and - sink = TCallableFlowSinkReturn() + sourceAp = AccessPath::empty() and + sink = TCallableFlowSinkReturn() and + sinkAp = AccessPath::property(any(SystemThreadingTasksTaskTClass c).getResultProperty()) ) ) ) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 5702fce60e4..a2a1cd9e9fe 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -16,6 +16,7 @@ private import semmle.code.csharp.dispatch.Dispatch private import semmle.code.csharp.frameworks.EntityFramework private import semmle.code.csharp.frameworks.NHibernate private import semmle.code.csharp.frameworks.system.Collections +private import semmle.code.csharp.frameworks.system.threading.Tasks abstract class NodeImpl extends Node { /** Do not call: use `getEnclosingCallable()` instead. */ @@ -154,10 +155,6 @@ module LocalFlow { scope = e2 and isSuccessor = true or - e1 = e2.(AwaitExpr).getExpr() and - scope = e2 and - isSuccessor = true - or // An `=` expression, where the result of the expression is used e2 = any(AssignExpr ae | @@ -679,6 +676,11 @@ private module Cached { storeStepLibrary(node1, c, node2) } + pragma[nomagic] + private PropertyContent getResultContent() { + result.getProperty() = any(SystemThreadingTasksTaskTClass c_).getResultProperty() + } + /** * Holds if data can flow from `node1` to `node2` via a read of content `c`. */ @@ -699,6 +701,10 @@ private module Cached { node2.(SsaDefinitionNode).getDefinition() = def and c instanceof ElementContent ) + or + x.hasNodePath(node1, node2) and + node2.asExpr().(AwaitExpr).getExpr() = node1.asExpr() and + c = getResultContent() ) or readStepLibrary(node1, c, node2) @@ -2180,6 +2186,11 @@ private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration isSuccessor = true and arrayRead(e1, e2) and scope = e2 + or + exactScope = false and + e1 = e2.(AwaitExpr).getExpr() and + scope = e2 and + isSuccessor = true } override predicate candidateDef( diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll index 820975809f8..04af24087af 100755 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll @@ -95,6 +95,10 @@ private class LocalTaintExprStepConfiguration extends ControlFlowReachabilityCon scope = e2 and isSuccessor = true ) + or + e1 = e2.(AwaitExpr).getExpr() and + scope = e2 and + isSuccessor = true ) } } diff --git a/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected b/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected index 0770e8c7c67..32251581ce6 100644 --- a/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected +++ b/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected @@ -180,8 +180,13 @@ edges | GlobalDataFlow.cs:217:22:217:28 | access to local variable tainted [[]] : String | GlobalDataFlow.cs:324:32:324:42 | sinkParam11 : String | | GlobalDataFlow.cs:217:22:217:49 | call to method Select [[]] : String | GlobalDataFlow.cs:217:22:217:57 | call to method First : String | | GlobalDataFlow.cs:217:22:217:57 | call to method First : String | GlobalDataFlow.cs:218:15:218:20 | access to local variable sink26 | -| GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | GlobalDataFlow.cs:240:15:240:20 | access to local variable sink41 | -| GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | GlobalDataFlow.cs:242:15:242:20 | access to local variable sink42 | +| GlobalDataFlow.cs:238:20:238:49 | call to method Run [Result] : String | GlobalDataFlow.cs:239:22:239:25 | access to local variable task [Result] : String | +| GlobalDataFlow.cs:238:20:238:49 | call to method Run [Result] : String | GlobalDataFlow.cs:241:28:241:31 | access to local variable task [Result] : String | +| GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | GlobalDataFlow.cs:238:20:238:49 | call to method Run [Result] : String | +| GlobalDataFlow.cs:239:22:239:25 | access to local variable task [Result] : String | GlobalDataFlow.cs:239:22:239:32 | access to property Result : String | +| GlobalDataFlow.cs:239:22:239:32 | access to property Result : String | GlobalDataFlow.cs:240:15:240:20 | access to local variable sink41 | +| GlobalDataFlow.cs:241:22:241:31 | await ... : String | GlobalDataFlow.cs:242:15:242:20 | access to local variable sink42 | +| GlobalDataFlow.cs:241:28:241:31 | access to local variable task [Result] : String | GlobalDataFlow.cs:241:22:241:31 | await ... : String | | GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | GlobalDataFlow.cs:256:16:256:25 | access to parameter sinkParam0 : String | | GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam0 | | GlobalDataFlow.cs:256:16:256:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | @@ -367,8 +372,13 @@ nodes | GlobalDataFlow.cs:217:22:217:49 | call to method Select [[]] : String | semmle.label | call to method Select [[]] : String | | GlobalDataFlow.cs:217:22:217:57 | call to method First : String | semmle.label | call to method First : String | | GlobalDataFlow.cs:218:15:218:20 | access to local variable sink26 | semmle.label | access to local variable sink26 | +| GlobalDataFlow.cs:238:20:238:49 | call to method Run [Result] : String | semmle.label | call to method Run [Result] : String | | GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:239:22:239:25 | access to local variable task [Result] : String | semmle.label | access to local variable task [Result] : String | +| GlobalDataFlow.cs:239:22:239:32 | access to property Result : String | semmle.label | access to property Result : String | | GlobalDataFlow.cs:240:15:240:20 | access to local variable sink41 | semmle.label | access to local variable sink41 | +| GlobalDataFlow.cs:241:22:241:31 | await ... : String | semmle.label | await ... : String | +| GlobalDataFlow.cs:241:28:241:31 | access to local variable task [Result] : String | semmle.label | access to local variable task [Result] : String | | GlobalDataFlow.cs:242:15:242:20 | access to local variable sink42 | semmle.label | access to local variable sink42 | | GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | semmle.label | sinkParam0 : String | | GlobalDataFlow.cs:256:16:256:25 | access to parameter sinkParam0 : String | semmle.label | access to parameter sinkParam0 : String | diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected index 33fa1d1750b..32a2e9749e7 100644 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected +++ b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected @@ -187,8 +187,13 @@ edges | GlobalDataFlow.cs:217:22:217:28 | access to local variable tainted [[]] : String | GlobalDataFlow.cs:324:32:324:42 | sinkParam11 : String | | GlobalDataFlow.cs:217:22:217:49 | call to method Select [[]] : String | GlobalDataFlow.cs:217:22:217:57 | call to method First : String | | GlobalDataFlow.cs:217:22:217:57 | call to method First : String | GlobalDataFlow.cs:218:15:218:20 | access to local variable sink26 | -| GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | GlobalDataFlow.cs:240:15:240:20 | access to local variable sink41 | -| GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | GlobalDataFlow.cs:242:15:242:20 | access to local variable sink42 | +| GlobalDataFlow.cs:238:20:238:49 | call to method Run [Result] : String | GlobalDataFlow.cs:239:22:239:25 | access to local variable task [Result] : String | +| GlobalDataFlow.cs:238:20:238:49 | call to method Run [Result] : String | GlobalDataFlow.cs:241:28:241:31 | access to local variable task [Result] : String | +| GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | GlobalDataFlow.cs:238:20:238:49 | call to method Run [Result] : String | +| GlobalDataFlow.cs:239:22:239:25 | access to local variable task [Result] : String | GlobalDataFlow.cs:239:22:239:32 | access to property Result : String | +| GlobalDataFlow.cs:239:22:239:32 | access to property Result : String | GlobalDataFlow.cs:240:15:240:20 | access to local variable sink41 | +| GlobalDataFlow.cs:241:22:241:31 | await ... : String | GlobalDataFlow.cs:242:15:242:20 | access to local variable sink42 | +| GlobalDataFlow.cs:241:28:241:31 | access to local variable task [Result] : String | GlobalDataFlow.cs:241:22:241:31 | await ... : String | | GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | GlobalDataFlow.cs:256:16:256:25 | access to parameter sinkParam0 : String | | GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam0 | | GlobalDataFlow.cs:256:16:256:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | @@ -381,8 +386,13 @@ nodes | GlobalDataFlow.cs:217:22:217:49 | call to method Select [[]] : String | semmle.label | call to method Select [[]] : String | | GlobalDataFlow.cs:217:22:217:57 | call to method First : String | semmle.label | call to method First : String | | GlobalDataFlow.cs:218:15:218:20 | access to local variable sink26 | semmle.label | access to local variable sink26 | +| GlobalDataFlow.cs:238:20:238:49 | call to method Run [Result] : String | semmle.label | call to method Run [Result] : String | | GlobalDataFlow.cs:238:35:238:48 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:239:22:239:25 | access to local variable task [Result] : String | semmle.label | access to local variable task [Result] : String | +| GlobalDataFlow.cs:239:22:239:32 | access to property Result : String | semmle.label | access to property Result : String | | GlobalDataFlow.cs:240:15:240:20 | access to local variable sink41 | semmle.label | access to local variable sink41 | +| GlobalDataFlow.cs:241:22:241:31 | await ... : String | semmle.label | await ... : String | +| GlobalDataFlow.cs:241:28:241:31 | access to local variable task [Result] : String | semmle.label | access to local variable task [Result] : String | | GlobalDataFlow.cs:242:15:242:20 | access to local variable sink42 | semmle.label | access to local variable sink42 | | GlobalDataFlow.cs:254:26:254:35 | sinkParam0 : String | semmle.label | sinkParam0 : String | | GlobalDataFlow.cs:256:16:256:25 | access to parameter sinkParam0 : String | semmle.label | access to parameter sinkParam0 : String | diff --git a/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected b/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected index b2c649eab75..72dc7c72060 100644 --- a/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected @@ -598,25 +598,10 @@ callableFlow | System.Threading.Tasks.Task.ContinueWith(Action, object, TaskContinuationOptions) | argument 1 -> parameter 1 of argument 0 | true | | System.Threading.Tasks.Task.ContinueWith(Action, object, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | | System.Threading.Tasks.Task.ContinueWith(Func, object) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task.ContinueWith(Func, object) | output from argument 0 -> return | true | | System.Threading.Tasks.Task.ContinueWith(Func, object, CancellationToken) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task.ContinueWith(Func, object, CancellationToken) | output from argument 0 -> return | true | | System.Threading.Tasks.Task.ContinueWith(Func, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task.ContinueWith(Func, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 0 -> return | true | | System.Threading.Tasks.Task.ContinueWith(Func, object, TaskContinuationOptions) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task.ContinueWith(Func, object, TaskContinuationOptions) | output from argument 0 -> return | true | | System.Threading.Tasks.Task.ContinueWith(Func, object, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task.ContinueWith(Func, object, TaskScheduler) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task.ContinueWith(Func) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task.ContinueWith(Func, CancellationToken) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task.ContinueWith(Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task.ContinueWith(Func, TaskContinuationOptions) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task.ContinueWith(Func, TaskScheduler) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task.FromResult(TResult) | argument 0 -> return | true | -| System.Threading.Tasks.Task.Run(Func) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task.Run(Func, CancellationToken) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task.Run(Func>) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task.Run(Func>, CancellationToken) | output from argument 0 -> return | true | | System.Threading.Tasks.Task.Task(Action, object) | argument 1 -> parameter 0 of argument 0 | true | | System.Threading.Tasks.Task.Task(Action, object, CancellationToken) | argument 1 -> parameter 0 of argument 0 | true | | System.Threading.Tasks.Task.Task(Action, object, CancellationToken, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | @@ -637,127 +622,61 @@ callableFlow | System.Threading.Tasks.Task<>.ContinueWith(Action>, TaskContinuationOptions) | qualifier -> parameter 0 of argument 0 | true | | System.Threading.Tasks.Task<>.ContinueWith(Action>, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | | System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object) | qualifier -> parameter 0 of argument 0 | true | | System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, CancellationToken) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, CancellationToken) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, CancellationToken) | qualifier -> parameter 0 of argument 0 | true | | System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | | System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, TaskContinuationOptions) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, TaskContinuationOptions) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, TaskContinuationOptions) | qualifier -> parameter 0 of argument 0 | true | | System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, TaskScheduler) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, CancellationToken) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, CancellationToken) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, TaskContinuationOptions) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, TaskContinuationOptions) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, TaskScheduler) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | | System.Threading.Tasks.Task<>.Task(Func, object) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.Task(Func, object) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.Task(Func, object, CancellationToken) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.Task(Func, object, CancellationToken) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.Task(Func, object, CancellationToken, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.Task(Func, object, CancellationToken, TaskCreationOptions) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.Task(Func, object, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.Task(Func, object, TaskCreationOptions) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.Task(Func) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.Task(Func, CancellationToken) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.Task(Func, CancellationToken, TaskCreationOptions) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.Task(Func, TaskCreationOptions) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.get_Result() | qualifier -> return | true | +| System.Threading.Tasks.Task<>.get_Result() | qualifier -> return | false | | System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, CancellationToken) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, CancellationToken) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, TaskContinuationOptions) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, TaskContinuationOptions) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Action) | argument 0 -> parameter 0 of argument 1 | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Action, CancellationToken) | argument 0 -> parameter 0 of argument 1 | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Action, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 0 -> parameter 0 of argument 1 | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Action, TaskContinuationOptions) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, CancellationToken) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, TaskContinuationOptions) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, TResult>) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, TResult>) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, TResult>, CancellationToken) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, TResult>, CancellationToken) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, TResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, TResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, TResult>, TaskContinuationOptions) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, TResult>, TaskContinuationOptions) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Action>) | argument 0 -> parameter 0 of argument 1 | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Action>, CancellationToken) | argument 0 -> parameter 0 of argument 1 | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Action>, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 0 -> parameter 0 of argument 1 | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Action>, TaskContinuationOptions) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, CancellationToken) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, TaskContinuationOptions) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory.StartNew(Action, object) | argument 1 -> parameter 0 of argument 0 | true | | System.Threading.Tasks.TaskFactory.StartNew(Action, object, CancellationToken) | argument 1 -> parameter 0 of argument 0 | true | | System.Threading.Tasks.TaskFactory.StartNew(Action, object, CancellationToken, TaskCreationOptions, TaskScheduler) | argument 1 -> parameter 0 of argument 0 | true | | System.Threading.Tasks.TaskFactory.StartNew(Action, object, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | | System.Threading.Tasks.TaskFactory.StartNew(Func, object) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory.StartNew(Func, object) | output from argument 0 -> return | true | | System.Threading.Tasks.TaskFactory.StartNew(Func, object, CancellationToken) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory.StartNew(Func, object, CancellationToken) | output from argument 0 -> return | true | | System.Threading.Tasks.TaskFactory.StartNew(Func, object, CancellationToken, TaskCreationOptions, TaskScheduler) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory.StartNew(Func, object, CancellationToken, TaskCreationOptions, TaskScheduler) | output from argument 0 -> return | true | | System.Threading.Tasks.TaskFactory.StartNew(Func, object, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory.StartNew(Func, object, TaskCreationOptions) | output from argument 0 -> return | true | -| System.Threading.Tasks.TaskFactory.StartNew(Func) | output from argument 0 -> return | true | -| System.Threading.Tasks.TaskFactory.StartNew(Func, CancellationToken) | output from argument 0 -> return | true | -| System.Threading.Tasks.TaskFactory.StartNew(Func, CancellationToken, TaskCreationOptions, TaskScheduler) | output from argument 0 -> return | true | -| System.Threading.Tasks.TaskFactory.StartNew(Func, TaskCreationOptions) | output from argument 0 -> return | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, CancellationToken) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, TaskContinuationOptions) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, CancellationToken) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, CancellationToken) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, TaskContinuationOptions) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, TaskContinuationOptions) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, CancellationToken) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, TaskContinuationOptions) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, TResult>) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, TResult>) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, TResult>, CancellationToken) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, TResult>, CancellationToken) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, TResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, TResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, TResult>, TaskContinuationOptions) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, TResult>, TaskContinuationOptions) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory<>.StartNew(Func, object) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object) | output from argument 0 -> return | true | | System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, CancellationToken) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, CancellationToken) | output from argument 0 -> return | true | | System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, CancellationToken, TaskCreationOptions, TaskScheduler) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, CancellationToken, TaskCreationOptions, TaskScheduler) | output from argument 0 -> return | true | | System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, TaskCreationOptions) | output from argument 0 -> return | true | -| System.Threading.Tasks.TaskFactory<>.StartNew(Func) | output from argument 0 -> return | true | -| System.Threading.Tasks.TaskFactory<>.StartNew(Func, CancellationToken) | output from argument 0 -> return | true | -| System.Threading.Tasks.TaskFactory<>.StartNew(Func, CancellationToken, TaskCreationOptions, TaskScheduler) | output from argument 0 -> return | true | -| System.Threading.Tasks.TaskFactory<>.StartNew(Func, TaskCreationOptions) | output from argument 0 -> return | true | | System.Uri.ToString() | qualifier -> return | false | | System.Uri.Uri(string) | argument 0 -> return | false | | System.Uri.Uri(string, UriKind) | argument 0 -> return | false | @@ -1981,10 +1900,91 @@ callableFlowAccessPath | System.Text.StringBuilder.StringBuilder(string, int, int, int) | argument 0 [] -> return [[]] | true | | System.Text.StringBuilder.ToString() | qualifier [[]] -> return [] | false | | System.Text.StringBuilder.ToString(int, int) | qualifier [[]] -> return [] | false | -| System.Threading.Tasks.Task.WhenAll(IEnumerable>) | argument 0 [[]] -> return [] | true | -| System.Threading.Tasks.Task.WhenAll(params Task[]) | argument 0 [[]] -> return [] | true | -| System.Threading.Tasks.Task.WhenAny(IEnumerable>) | argument 0 [[]] -> return [] | true | -| System.Threading.Tasks.Task.WhenAny(params Task[]) | argument 0 [[]] -> return [] | true | +| System.Threading.Tasks.Task.ContinueWith(Func, object) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task.ContinueWith(Func, object, CancellationToken) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task.ContinueWith(Func, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task.ContinueWith(Func, object, TaskContinuationOptions) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task.ContinueWith(Func, object, TaskScheduler) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task.ContinueWith(Func) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task.ContinueWith(Func, CancellationToken) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task.ContinueWith(Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task.ContinueWith(Func, TaskContinuationOptions) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task.ContinueWith(Func, TaskScheduler) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task.FromResult(TResult) | argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task.Run(Func) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task.Run(Func, CancellationToken) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task.Run(Func>) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task.Run(Func>, CancellationToken) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task.WhenAll(IEnumerable>) | argument 0 [[], Result] -> return [Result, []] | true | +| System.Threading.Tasks.Task.WhenAll(params Task[]) | argument 0 [[], Result] -> return [Result, []] | true | +| System.Threading.Tasks.Task.WhenAny(IEnumerable>) | argument 0 [[], Result] -> return [Result, []] | true | +| System.Threading.Tasks.Task.WhenAny(params Task[]) | argument 0 [[], Result] -> return [Result, []] | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, CancellationToken) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, TaskContinuationOptions) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, TaskScheduler) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, CancellationToken) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, TaskContinuationOptions) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, TaskScheduler) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.Task(Func, object) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.Task(Func, object, CancellationToken) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.Task(Func, object, CancellationToken, TaskCreationOptions) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.Task(Func, object, TaskCreationOptions) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.Task(Func) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.Task(Func, CancellationToken) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.Task(Func, CancellationToken, TaskCreationOptions) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.Task(Func, TaskCreationOptions) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, CancellationToken) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, TaskContinuationOptions) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, CancellationToken) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, TaskContinuationOptions) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, TResult>) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, TResult>, CancellationToken) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, TResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, TResult>, TaskContinuationOptions) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, CancellationToken) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, TaskContinuationOptions) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.StartNew(Func, object) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.StartNew(Func, object, CancellationToken) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.StartNew(Func, object, CancellationToken, TaskCreationOptions, TaskScheduler) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.StartNew(Func, object, TaskCreationOptions) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.StartNew(Func) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.StartNew(Func, CancellationToken) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.StartNew(Func, CancellationToken, TaskCreationOptions, TaskScheduler) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory.StartNew(Func, TaskCreationOptions) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, CancellationToken) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, TaskContinuationOptions) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, CancellationToken) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, TaskContinuationOptions) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, CancellationToken) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, TaskContinuationOptions) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, TResult>) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, TResult>, CancellationToken) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, TResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, TResult>, TaskContinuationOptions) | output from argument 1 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, CancellationToken) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, CancellationToken, TaskCreationOptions, TaskScheduler) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, TaskCreationOptions) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.StartNew(Func) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.StartNew(Func, CancellationToken) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.StartNew(Func, CancellationToken, TaskCreationOptions, TaskScheduler) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.TaskFactory<>.StartNew(Func, TaskCreationOptions) | output from argument 0 [] -> return [Result] | true | clearsContent | System.Array.Clear() | qualifier | [] | | System.Array.Clear(Array, int, int) | qualifier | [] | From 856ad0769481947ddb582090fcb3069024c0f047 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sat, 3 Oct 2020 22:07:34 +0200 Subject: [PATCH 198/411] join-order improvement in NoSQL.qll --- .../ql/src/semmle/javascript/frameworks/NoSQL.qll | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll index f1ec213caf0..5f53ccff348 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll @@ -537,13 +537,13 @@ private module Mongoose { param = func.getLastParameter().getParameter(1) ) or - exists(API::Node f, string executor, int paramIndex | - executor = "then" and paramIndex = 0 + exists(API::Node f | + f = Query::getAMongooseQuery().getMember("then") and + param = f.getParameter(0).getParameter(0) or - executor = "exec" and paramIndex = 1 + f = Query::getAMongooseQuery().getMember("exec") and + param = f.getParameter(0).getParameter(1) | - f = Query::getAMongooseQuery().getMember(executor) and - param = f.getParameter(0).getParameter(paramIndex) and exists(DataFlow::MethodCallNode pred | // limitation: look at the previous method call Query::MethodSignatures::returnsDocumentQuery(pred.getMethodName(), asArray) and From 4d62033a159d50b3ec261aa632a5ebb7e0813fcc Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 5 Oct 2020 10:14:13 +0200 Subject: [PATCH 199/411] C#: Handle population of error types --- csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs index cc02b8e1799..b1186072c64 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs @@ -80,6 +80,7 @@ namespace Semmle.Extraction.CSharp.Entities case TypeKind.Enum: return Kinds.TypeKind.ENUM; case TypeKind.Delegate: return Kinds.TypeKind.DELEGATE; case TypeKind.Pointer: return Kinds.TypeKind.POINTER; + case TypeKind.Error: return Kinds.TypeKind.UNKNOWN; default: cx.ModelError(t, $"Unhandled type kind '{t.TypeKind}'"); return Kinds.TypeKind.UNKNOWN; From 3dabff6b171793df97b5ab126dfd14c7be7d0ef1 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 29 Sep 2020 11:08:22 +0100 Subject: [PATCH 200/411] JS: Recognize field types in untyped code --- .../ql/src/semmle/javascript/Extend.qll | 11 +++++++--- .../semmle/javascript/dataflow/DataFlow.qll | 7 ++++++- .../src/semmle/javascript/dataflow/Nodes.qll | 20 +++++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/Extend.qll b/javascript/ql/src/semmle/javascript/Extend.qll index 47124948797..5943aa78320 100644 --- a/javascript/ql/src/semmle/javascript/Extend.qll +++ b/javascript/ql/src/semmle/javascript/Extend.qll @@ -34,6 +34,13 @@ abstract class ExtendCall extends DataFlow::CallNode { } } +/** A version of `JQuery::dollarSource()` with fewer dependencies. */ +private DataFlow::SourceNode localDollar() { + result.accessesGlobal(["$", "jQuery"]) + or + result = DataFlow::moduleImport("jquery") +} + /** * An extend call of form `extend(true/false, dst, src1, src2, ...)`, where the true/false * argument is possibly omitted. @@ -47,9 +54,7 @@ private class ExtendCallWithFlag extends ExtendCall { name = "node.extend" ) or - // Match $.extend using the source of `$` only, as ExtendCall should not - // depend on type tracking. - this = JQuery::dollarSource().getAMemberCall("extend") + this = localDollar().getAMemberCall("extend") } /** diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 332a7bc4e6e..5f92ee821a9 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -228,7 +228,7 @@ module DataFlow { * * Doesn't take field types and function return types into account. */ - private JSDocTypeExpr getFallbackTypeAnnotation() { + private TypeAnnotation getFallbackTypeAnnotation() { exists(BindingPattern pattern | this = valueNode(pattern) and not ast_node_type(pattern, _) and @@ -236,6 +236,11 @@ module DataFlow { ) or result = getAPredecessor().getFallbackTypeAnnotation() + or + exists(DataFlow::ClassNode cls, string fieldName | + this = cls.getAReceiverNode().getAPropertyRead(fieldName) and + result = cls.getFieldTypeAnnotation(fieldName) + ) } /** diff --git a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll index b8327265f70..867cc428529 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll @@ -995,6 +995,13 @@ class ClassNode extends DataFlow::SourceNode { predicate hasQualifiedName(string name) { getAClassReference().flowsTo(AccessPath::getAnAssignmentTo(name)) } + + /** + * Gets the type annotation for the field `fieldName`, if any. + */ + TypeAnnotation getFieldTypeAnnotation(string fieldName) { + result = impl.getFieldTypeAnnotation(fieldName) + } } module ClassNode { @@ -1047,6 +1054,11 @@ module ClassNode { * of this node. */ abstract DataFlow::Node getASuperClassNode(); + + /** + * Gets the type annotation for the field `fieldName`, if any. + */ + TypeAnnotation getFieldTypeAnnotation(string fieldName) { none() } } /** @@ -1106,6 +1118,14 @@ module ClassNode { } override DataFlow::Node getASuperClassNode() { result = astNode.getSuperClass().flow() } + + override TypeAnnotation getFieldTypeAnnotation(string fieldName) { + exists(FieldDeclaration field | + field.getDeclaringClass() = astNode and + fieldName = field.getName() and + result = field.getTypeAnnotation() + ) + } } private DataFlow::PropRef getAPrototypeReferenceInFile(string name, File f) { From cad259fb83975edad339f9ec1f59e0f76be684c4 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 29 Sep 2020 12:01:38 +0100 Subject: [PATCH 201/411] JS: Use more types in DOM model --- javascript/ql/src/semmle/javascript/DOM.qll | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/DOM.qll b/javascript/ql/src/semmle/javascript/DOM.qll index c8c95d0f2ee..18d11e7bf51 100644 --- a/javascript/ql/src/semmle/javascript/DOM.qll +++ b/javascript/ql/src/semmle/javascript/DOM.qll @@ -347,7 +347,11 @@ module DOM { } /** Gets a data flow node that may refer to a value from the DOM. */ - DataFlow::SourceNode domValueRef() { result = domValueRef(DataFlow::TypeTracker::end()) } + DataFlow::SourceNode domValueRef() { + result = domValueRef(DataFlow::TypeTracker::end()) + or + result.hasUnderlyingType("Element") + } module LocationSource { /** @@ -419,5 +423,9 @@ module DOM { /** * Gets a reference to the 'document' object. */ - DataFlow::SourceNode documentRef() { result = documentRef(DataFlow::TypeTracker::end()) } + DataFlow::SourceNode documentRef() { + result = documentRef(DataFlow::TypeTracker::end()) + or + result.hasUnderlyingType("Document") + } } From 790d2ba0fce4c937d86acbfea54d520ae355ed68 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Sat, 3 Oct 2020 10:15:39 +0100 Subject: [PATCH 202/411] JS: Fix FPs from ParameterFieldAsPropWrite.getPropertyNameExpr --- javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 5f92ee821a9..8b6b1d5cb5f 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -709,7 +709,9 @@ module DataFlow { result = thisNode(prop.getDeclaringClass().getConstructor().getBody()) } - override Expr getPropertyNameExpr() { result = prop.getNameExpr() } + override Expr getPropertyNameExpr() { + none() // The parameter value is not the name of the field + } override string getPropertyName() { result = prop.getName() } From 8689a9b3b9bb350908d5fad4cd1918a51dea3a28 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 30 Sep 2020 15:30:56 +0100 Subject: [PATCH 203/411] JS: Fix a bad join order in barrierGuardBlocksNode --- .../javascript/dataflow/Configuration.qll | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll index d821f233e9e..337054a918a 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll @@ -420,6 +420,22 @@ private predicate barrierGuardBlocksSsaRefinement( ) } +/** + * Holds if the result of `guard` is used in the branching condition `cond`. + * + * `outcome` is bound to the outcome of `cond` for join-ordering purposes. + */ +pragma[noinline] +private predicate barrierGuardUsedInCondition(BarrierGuardNode guard, ConditionGuardNode cond, boolean outcome) { + barrierGuardIsRelevant(guard) and + outcome = cond.getOutcome() and + ( + cond.getTest() = guard.getEnclosingExpr() + or + cond.getTest().flow().getImmediatePredecessor+() = guard + ) +} + /** * Holds if data flow node `nd` acts as a barrier for data flow, possibly due to aliasing * through an access path. @@ -435,14 +451,9 @@ private predicate barrierGuardBlocksNode(BarrierGuardNode guard, DataFlow::Node ) or // 2) `nd` is an instance of an access path `p`, and dominated by a barrier for `p` - barrierGuardIsRelevant(guard) and exists(AccessPath p, BasicBlock bb, ConditionGuardNode cond, boolean outcome | nd = DataFlow::valueNode(p.getAnInstanceIn(bb)) and - ( - guard.getEnclosingExpr() = cond.getTest() or - guard = cond.getTest().flow().getImmediatePredecessor+() - ) and - outcome = cond.getOutcome() and + barrierGuardUsedInCondition(guard, cond, outcome) and barrierGuardBlocksAccessPath(guard, outcome, p, label) and cond.dominates(bb) ) From 488a55b9dd6263947d37fee616a262501a59a2e6 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 5 Oct 2020 10:39:32 +0100 Subject: [PATCH 204/411] C++: Autoformat. --- cpp/ql/src/Critical/SizeCheck2.ql | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cpp/ql/src/Critical/SizeCheck2.ql b/cpp/ql/src/Critical/SizeCheck2.ql index fc51be1b1aa..1b7e1347c30 100644 --- a/cpp/ql/src/Critical/SizeCheck2.ql +++ b/cpp/ql/src/Critical/SizeCheck2.ql @@ -15,9 +15,7 @@ import cpp class Allocation extends FunctionCall { - Allocation() { - this.getTarget().hasGlobalOrStdName(["malloc", "calloc", "realloc"]) - } + Allocation() { this.getTarget().hasGlobalOrStdName(["malloc", "calloc", "realloc"]) } private string getName() { this.getTarget().hasGlobalOrStdName(result) } From fee99105da0194473d2d4fdfe20b3121e314a77e Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Mon, 5 Oct 2020 11:53:58 +0100 Subject: [PATCH 205/411] JS: Remove tslint dependency --- .../extractor/lib/typescript/package.json | 3 +- javascript/extractor/lib/typescript/yarn.lock | 223 ------------------ 2 files changed, 1 insertion(+), 225 deletions(-) diff --git a/javascript/extractor/lib/typescript/package.json b/javascript/extractor/lib/typescript/package.json index 0fa2d78d7d5..3b0c3b596bb 100644 --- a/javascript/extractor/lib/typescript/package.json +++ b/javascript/extractor/lib/typescript/package.json @@ -12,7 +12,6 @@ "watch": "tsc -p . -w --sourceMap" }, "devDependencies": { - "@types/node": "12.7.11", - "tslint": "^5.9.1" + "@types/node": "12.7.11" } } diff --git a/javascript/extractor/lib/typescript/yarn.lock b/javascript/extractor/lib/typescript/yarn.lock index 42c9f33d41c..80bdf6b91e2 100644 --- a/javascript/extractor/lib/typescript/yarn.lock +++ b/javascript/extractor/lib/typescript/yarn.lock @@ -6,229 +6,6 @@ version "12.7.11" resolved node-12.7.11.tgz#be879b52031cfb5d295b047f5462d8ef1a716446 -ansi-regex@^2.0.0: - version "2.1.1" - resolved ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df - -ansi-styles@^2.2.1: - version "2.2.1" - resolved ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe - -ansi-styles@^3.1.0: - version "3.2.0" - resolved ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88 - dependencies: - color-convert "^1.9.0" - -argparse@^1.0.7: - version "1.0.9" - resolved argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86 - dependencies: - sprintf-js "~1.0.2" - -babel-code-frame@^6.22.0: - version "6.26.0" - resolved babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -balanced-match@^1.0.0: - version "1.0.0" - resolved balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767 - -brace-expansion@^1.1.7: - version "1.1.8" - resolved brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292 - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -builtin-modules@^1.1.1: - version "1.1.1" - resolved builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f - -chalk@^1.1.3: - version "1.1.3" - resolved chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98 - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.3.0: - version "2.3.0" - resolved chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba - dependencies: - ansi-styles "^3.1.0" - escape-string-regexp "^1.0.5" - supports-color "^4.0.0" - -color-convert@^1.9.0: - version "1.9.1" - resolved color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed - dependencies: - color-name "^1.1.1" - -color-name@^1.1.1: - version "1.1.3" - resolved color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25 - -commander@^2.12.1: - version "2.13.0" - resolved commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c - -concat-map@0.0.1: - version "0.0.1" - resolved concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b - -diff@^3.2.0: - version "3.4.0" - resolved diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c - -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4 - -esprima@^4.0.0: - version "4.0.0" - resolved esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804 - -esutils@^2.0.2: - version "2.0.2" - resolved esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b - -fs.realpath@^1.0.0: - version "1.0.0" - resolved fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f - -glob@^7.1.1: - version "7.1.2" - resolved glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15 - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -has-ansi@^2.0.0: - version "2.0.0" - resolved has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91 - dependencies: - ansi-regex "^2.0.0" - -has-flag@^2.0.0: - version "2.0.0" - resolved has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51 - -inflight@^1.0.4: - version "1.0.6" - resolved inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9 - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.3" - resolved inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de - -js-tokens@^3.0.2: - version "3.0.2" - resolved js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b - -js-yaml@^3.7.0: - version "3.10.0" - resolved js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -minimatch@^3.0.4: - version "3.0.4" - resolved minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083 - dependencies: - brace-expansion "^1.1.7" - -once@^1.3.0: - version "1.4.0" - resolved once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1 - dependencies: - wrappy "1" - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f - -path-parse@^1.0.5: - version "1.0.5" - resolved path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1 - -resolve@^1.3.2: - version "1.5.0" - resolved resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36 - dependencies: - path-parse "^1.0.5" - -semver@^5.3.0: - version "5.5.0" - resolved semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab - -sprintf-js@~1.0.2: - version "1.0.3" - resolved sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c - -strip-ansi@^3.0.0: - version "3.0.1" - resolved strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf - dependencies: - ansi-regex "^2.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7 - -supports-color@^4.0.0: - version "4.5.0" - resolved supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b - dependencies: - has-flag "^2.0.0" - -tslib@^1.8.0, tslib@^1.8.1: - version "1.9.0" - resolved tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8 - -tslint@^5.9.1: - version "5.9.1" - resolved tslint-5.9.1.tgz#1255f87a3ff57eb0b0e1f0e610a8b4748046c9ae - dependencies: - babel-code-frame "^6.22.0" - builtin-modules "^1.1.1" - chalk "^2.3.0" - commander "^2.12.1" - diff "^3.2.0" - glob "^7.1.1" - js-yaml "^3.7.0" - minimatch "^3.0.4" - resolve "^1.3.2" - semver "^5.3.0" - tslib "^1.8.0" - tsutils "^2.12.1" - -tsutils@^2.12.1: - version "2.19.1" - resolved tsutils-2.19.1.tgz#76d7ebdea9d7a7bf4a05f50ead3701b0168708d7 - dependencies: - tslib "^1.8.1" - typescript@4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.2.tgz#7ea7c88777c723c681e33bf7988be5d008d05ac2" - -wrappy@1: - version "1.0.2" - resolved wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f From 6c87b08c69d10ecebc2889c5d4c1c4ffa09518f3 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 5 Oct 2020 12:54:11 +0200 Subject: [PATCH 206/411] C++: Respond to review comments: - ArgumentNode is now abstract - PrimaryArgumentNode is now an OperandNode. - ArgumentIndirectionNode is now merged into SideEffectArgumentNode. --- .../ir/dataflow/internal/DataFlowPrivate.qll | 50 ++++++------------- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 15 ------ .../dataflow/fields/ir-path-flow.expected | 6 +-- 3 files changed, 18 insertions(+), 53 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 482b9d6cb7b..243a2870481 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -5,23 +5,15 @@ private import DataFlowDispatch /** * A data flow node that occurs as the argument of a call and is passed as-is - * to the callable. Instance arguments (`this` pointer) are also included. + * to the callable. Instance arguments (`this` pointer) and read side effects + * on parameters are also included. */ -class ArgumentNode extends Node { - ArgumentNode() { - // To avoid making this class abstract, we enumerate its values here. - this instanceof PrimaryArgumentNode or - this instanceof SideEffectArgumentNode - } - +abstract class ArgumentNode extends OperandNode { /** * Holds if this argument occurs at the given position in the given call. * The instance argument is considered to have index `-1`. */ - predicate argumentOf(DataFlowCall call, int pos) { - this.(PrimaryArgumentNode).argumentOf(call, pos) or - this.(SideEffectArgumentNode).argumentOf(call, pos) - } + abstract predicate argumentOf(DataFlowCall call, int pos); /** Gets the call in which this node is an argument. */ DataFlowCall getCall() { this.argumentOf(result, _) } @@ -31,17 +23,15 @@ class ArgumentNode extends Node { * A data flow node that occurs as the argument to a call, or an * implicit `this` pointer argument. */ -private class PrimaryArgumentNode extends InstructionNode { - PrimaryArgumentNode() { exists(CallInstruction call | instr = call.getAnArgument()) } +private class PrimaryArgumentNode extends ArgumentNode { + override ArgumentOperand op; - /** - * Holds if this argument occurs at the given position in the given call. - * The instance argument is considered to have index `-1`. - */ - predicate argumentOf(DataFlowCall call, int pos) { - instr = call.getPositionalArgument(pos) + PrimaryArgumentNode() { exists(CallInstruction call | op = call.getAnArgumentOperand()) } + + override predicate argumentOf(DataFlowCall call, int pos) { + op = call.getPositionalArgumentOperand(pos) or - instr = call.getThisArgument() and pos = -1 + op = call.getThisArgumentOperand() and pos = -1 } } @@ -49,26 +39,18 @@ private class PrimaryArgumentNode extends InstructionNode { * A data flow node representing the read side effect of a call on a * specific parameter. */ -private class SideEffectArgumentNode extends OperandNode { +private class SideEffectArgumentNode extends ArgumentNode { override SideEffectOperand op; ReadSideEffectInstruction read; - SideEffectArgumentNode() { - exists(CallInstruction call | - read.getPrimaryInstruction() = call and - op = read.getSideEffectOperand() - ) - } + SideEffectArgumentNode() { op = read.getSideEffectOperand() } - /** - * Holds if this argument occurs at the given position in the given call. - * See `getArgumentPosOfSideEffect` for a describing of how read side effects - * are assigned an argument position. - */ - predicate argumentOf(DataFlowCall call, int pos) { + override predicate argumentOf(DataFlowCall call, int pos) { read.getPrimaryInstruction() = call and pos = getArgumentPosOfSideEffect(read.getIndex()) } + + override string toString() { result = "Argument " + read.getIndex() + " indirection" } } private newtype TReturnKind = diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 054c42721af..1270b8d67da 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -505,21 +505,6 @@ class DefinitionByReferenceNode extends InstructionNode { } } -/** - * A node representing the memory pointed to by a function argument. - * - * This class exists only in order to override `toString`, which would - * otherwise be the default implementation inherited from `OperandNode`. - */ -private class ArgumentIndirectionNode extends OperandNode { - override SideEffectOperand op; - ReadSideEffectInstruction read; - - ArgumentIndirectionNode() { read.getSideEffectOperand() = op } - - override string toString() { result = "Argument " + read.getIndex() + " indirection" } -} - /** * A `Node` corresponding to a variable in the program, as opposed to the * value of that variable at some particular point. This can be used for diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected index ed5153da336..ed18d6a633e 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected @@ -1,7 +1,7 @@ edges | A.cpp:55:5:55:5 | set output argument [c] | A.cpp:56:13:56:15 | call to get | | A.cpp:55:12:55:19 | (C *)... | A.cpp:55:5:55:5 | set output argument [c] | -| A.cpp:55:12:55:19 | new | A.cpp:55:12:55:19 | (C *)... | +| A.cpp:55:12:55:19 | new | A.cpp:55:5:55:5 | set output argument [c] | | A.cpp:57:11:57:24 | B output argument [c] | A.cpp:57:28:57:30 | call to get | | A.cpp:57:17:57:23 | new | A.cpp:57:11:57:24 | B output argument [c] | | A.cpp:98:12:98:18 | new | A.cpp:100:5:100:13 | Store | @@ -19,12 +19,11 @@ edges | A.cpp:143:7:143:31 | Chi [b] | A.cpp:151:12:151:24 | D output argument [b] | | A.cpp:143:7:143:31 | Store | A.cpp:143:7:143:31 | Chi [b] | | A.cpp:143:25:143:31 | new | A.cpp:143:7:143:31 | Store | -| A.cpp:150:12:150:18 | new | A.cpp:151:18:151:18 | b | +| A.cpp:150:12:150:18 | new | A.cpp:151:12:151:24 | D output argument [b] | | A.cpp:151:12:151:24 | Chi [b] | A.cpp:152:13:152:13 | b | | A.cpp:151:12:151:24 | D output argument [b] | A.cpp:151:12:151:24 | Chi [b] | | A.cpp:151:18:151:18 | Chi [c] | A.cpp:154:13:154:13 | c | | A.cpp:151:18:151:18 | D output argument [c] | A.cpp:151:18:151:18 | Chi [c] | -| A.cpp:151:18:151:18 | b | A.cpp:151:12:151:24 | D output argument [b] | | C.cpp:18:12:18:18 | C output argument [s1] | C.cpp:27:8:27:11 | *#this [s1] | | C.cpp:18:12:18:18 | C output argument [s3] | C.cpp:27:8:27:11 | *#this [s3] | | C.cpp:22:12:22:21 | Chi [s1] | C.cpp:24:5:24:25 | Chi [s1] | @@ -229,7 +228,6 @@ nodes | A.cpp:151:12:151:24 | D output argument [b] | semmle.label | D output argument [b] | | A.cpp:151:18:151:18 | Chi [c] | semmle.label | Chi [c] | | A.cpp:151:18:151:18 | D output argument [c] | semmle.label | D output argument [c] | -| A.cpp:151:18:151:18 | b | semmle.label | b | | A.cpp:152:13:152:13 | b | semmle.label | b | | A.cpp:154:13:154:13 | c | semmle.label | c | | C.cpp:18:12:18:18 | C output argument [s1] | semmle.label | C output argument [s1] | From 591c17d7cf6cc458d387773d7a64e9039d7743a3 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 5 Oct 2020 12:22:08 +0100 Subject: [PATCH 207/411] C++: Rearrange comments. --- cpp/ql/src/semmle/code/cpp/commons/Strcat.qll | 16 +++++------ .../cpp/models/implementations/Strcpy.qll | 28 +++++++++---------- .../semmle/code/cpp/security/BufferWrite.qll | 8 +++--- 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/commons/Strcat.qll b/cpp/ql/src/semmle/code/cpp/commons/Strcat.qll index 5226f9876fe..28408b82ffa 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Strcat.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Strcat.qll @@ -8,13 +8,13 @@ import cpp */ class StrcatFunction extends Function { StrcatFunction() { - // strcat(dst, src) - // strncat(dst, src, max_amount) - // wcscat(dst, src) - // _mbscat(dst, src) - // wcsncat(dst, src, max_amount) - // _mbsncat(dst, src, max_amount) - // _mbsncat_l(dst, src, max_amount, locale) - getName() = ["strcat", "strncat", "wcscat", "_mbscat", "wcsncat", "_mbsncat", "_mbsncat_l"] + getName() = + ["strcat", // strcat(dst, src) + "strncat", // strncat(dst, src, max_amount) + "wcscat", // wcscat(dst, src) + "_mbscat", // _mbscat(dst, src) + "wcsncat", // wcsncat(dst, src, max_amount) + "_mbsncat", // _mbsncat(dst, src, max_amount) + "_mbsncat_l"] // _mbsncat_l(dst, src, max_amount, locale) } } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll index 8de648d91b3..d0b3f92fa0f 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll @@ -13,23 +13,21 @@ import semmle.code.cpp.models.interfaces.SideEffect */ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction { StrcpyFunction() { - // strcpy(dst, src) - // wcscpy(dst, src) - // _mbscpy(dst, src) - // strncpy(dst, src, max_amount) - // _strncpy_l(dst, src, max_amount, locale) - // wcsncpy(dst, src, max_amount) - // _wcsncpy_l(dst, src, max_amount, locale) - // _mbsncpy(dst, src, max_amount) - // _mbsncpy_l(dst, src, max_amount, locale) getName() = - ["strcpy", "wcscpy", "_mbscpy", "strncpy", "_strncpy_l", "wcsncpy", "_wcsncpy_l", "_mbsncpy", - "_mbsncpy_l"] + ["strcpy", // strcpy(dst, src) + "wcscpy", // wcscpy(dst, src) + "_mbscpy", // _mbscpy(dst, src) + "strncpy", // strncpy(dst, src, max_amount) + "_strncpy_l", // _strncpy_l(dst, src, max_amount, locale) + "wcsncpy", // wcsncpy(dst, src, max_amount) + "_wcsncpy_l", // _wcsncpy_l(dst, src, max_amount, locale) + "_mbsncpy", // _mbsncpy(dst, src, max_amount) + "_mbsncpy_l"] // _mbsncpy_l(dst, src, max_amount, locale) or - // strcpy_s(dst, max_amount, src) - // wcscpy_s(dst, max_amount, src) - // _mbscpy_s(dst, max_amount, src) - getName() = ["strcpy_s", "wcscpy_s", "_mbscpy_s"] and + getName() = + ["strcpy_s", // strcpy_s(dst, max_amount, src) + "wcscpy_s", // wcscpy_s(dst, max_amount, src) + "_mbscpy_s"] and // _mbscpy_s(dst, max_amount, src) // exclude the 2-parameter template versions // that find the size of a fixed size destination buffer. getNumberOfParameters() = 3 diff --git a/cpp/ql/src/semmle/code/cpp/security/BufferWrite.qll b/cpp/ql/src/semmle/code/cpp/security/BufferWrite.qll index 02328f707a9..f06b0180c23 100644 --- a/cpp/ql/src/semmle/code/cpp/security/BufferWrite.qll +++ b/cpp/ql/src/semmle/code/cpp/security/BufferWrite.qll @@ -354,10 +354,10 @@ class SnprintfBW extends BufferWriteCall { */ class GetsBW extends BufferWriteCall { GetsBW() { - // gets(dst) - // fgets(dst, max_amount, src_stream) - // fgetws(dst, max_amount, src_stream) - getTarget().(TopLevelFunction).getName() = ["gets", "fgets", "fgetws"] + getTarget().(TopLevelFunction).getName() = + ["gets", // gets(dst) + "fgets", // fgets(dst, max_amount, src_stream) + "fgetws"] // fgetws(dst, max_amount, src_stream) } /** From 855d2b50d70c97e9ea4e7007e71ee54bf71bfc3b Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 5 Oct 2020 13:00:51 +0100 Subject: [PATCH 208/411] C++: Correct test comments. --- cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp index ac0aa9da6cd..0347af6d20a 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/map.cpp @@ -102,7 +102,7 @@ void test_map() std::map m1, m2, m3, m4, m5, m6; sink(m1.insert(std::make_pair("abc", "def")).first); - sink(m2.insert(std::make_pair("abc", source())).first); // tainted [NOT DETECTED] + sink(m2.insert(std::make_pair("abc", source())).first); // tainted sink(m3.insert(std::make_pair(source(), "def")).first); // tainted [NOT DETECTED] sink(m4.insert(m4.begin(), std::pair("abc", source()))); // tainted sink(m5.insert_or_assign("abc", source()).first); // tainted @@ -254,7 +254,7 @@ void test_unordered_map() std::unordered_map m1, m2, m3, m4, m5, m6; sink(m1.insert(std::make_pair("abc", "def")).first); - sink(m2.insert(std::make_pair("abc", source())).first); // tainted [NOT DETECTED] + sink(m2.insert(std::make_pair("abc", source())).first); // tainted sink(m3.insert(std::make_pair(source(), "def")).first); // tainted [NOT DETECTED] sink(m4.insert(m4.begin(), std::pair("abc", source()))); // tainted sink(m5.insert_or_assign("abc", source()).first); // tainted From d162c3d8c619ead910355180223234eaebac10b6 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 5 Oct 2020 14:29:57 +0200 Subject: [PATCH 209/411] C++: Accept more test changes --- .../CWE/CWE-079/semmle/CgiXss/CgiXss.expected | 14 ++++++-------- .../UncontrolledProcessOperation.expected | 2 ++ .../CWE/CWE-134/semmle/argv/argvLocal.expected | 13 +++---------- ...controlledFormatStringThroughGlobalVar.expected | 2 ++ .../TaintedAllocationSize.expected | 14 ++++++-------- 5 files changed, 19 insertions(+), 26 deletions(-) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected index 17bb67fdc08..31a218c03fa 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected @@ -4,12 +4,10 @@ edges | search.c:14:24:14:28 | query | search.c:17:8:17:12 | query | | search.c:22:24:22:28 | query | search.c:23:39:23:43 | query | | search.c:22:24:22:28 | query | search.c:23:39:23:43 | query | -| search.c:41:21:41:26 | call to getenv | search.c:45:17:45:25 | raw_query | -| search.c:41:21:41:26 | call to getenv | search.c:45:17:45:25 | raw_query | -| search.c:41:21:41:26 | call to getenv | search.c:47:17:47:25 | raw_query | -| search.c:41:21:41:26 | call to getenv | search.c:47:17:47:25 | raw_query | -| search.c:45:17:45:25 | raw_query | search.c:14:24:14:28 | query | -| search.c:47:17:47:25 | raw_query | search.c:22:24:22:28 | query | +| search.c:41:21:41:26 | call to getenv | search.c:14:24:14:28 | query | +| search.c:41:21:41:26 | call to getenv | search.c:14:24:14:28 | query | +| search.c:41:21:41:26 | call to getenv | search.c:22:24:22:28 | query | +| search.c:41:21:41:26 | call to getenv | search.c:22:24:22:28 | query | nodes | search.c:14:24:14:28 | query | semmle.label | query | | search.c:17:8:17:12 | (const char *)... | semmle.label | (const char *)... | @@ -23,8 +21,8 @@ nodes | search.c:23:39:23:43 | query | semmle.label | query | | search.c:41:21:41:26 | call to getenv | semmle.label | call to getenv | | search.c:41:21:41:26 | call to getenv | semmle.label | call to getenv | -| search.c:45:17:45:25 | raw_query | semmle.label | raw_query | -| search.c:47:17:47:25 | raw_query | semmle.label | raw_query | +| search.c:45:5:45:15 | Arg(0) | semmle.label | Arg(0) | +| search.c:47:5:47:15 | Arg(0) | semmle.label | Arg(0) | #select | search.c:17:8:17:12 | query | search.c:41:21:41:26 | call to getenv | search.c:17:8:17:12 | query | Cross-site scripting vulnerability due to $@. | search.c:41:21:41:26 | call to getenv | this query data | | search.c:23:39:23:43 | query | search.c:41:21:41:26 | call to getenv | search.c:23:39:23:43 | query | Cross-site scripting vulnerability due to $@. | search.c:41:21:41:26 | call to getenv | this query data | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected index 5c46a7c8193..5b537d44080 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected @@ -32,8 +32,10 @@ nodes | test.cpp:31:10:31:16 | command | semmle.label | command | | test.cpp:31:10:31:16 | command | semmle.label | command | | test.cpp:31:10:31:16 | command | semmle.label | command | +| test.cpp:42:7:42:16 | Arg(0) | semmle.label | Arg(0) | | test.cpp:42:18:42:23 | call to getenv | semmle.label | call to getenv | | test.cpp:42:18:42:34 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:43:7:43:16 | Arg(0) | semmle.label | Arg(0) | | test.cpp:43:18:43:23 | call to getenv | semmle.label | call to getenv | | test.cpp:43:18:43:34 | (const char *)... | semmle.label | (const char *)... | | test.cpp:56:12:56:17 | buffer | semmle.label | buffer | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected index 20a501b9f09..ea59c15da13 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected @@ -67,8 +67,6 @@ edges | argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | printWrapper output argument | @@ -81,8 +79,6 @@ edges | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | printWrapper output argument | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | printWrapper output argument | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | (const char *)... | @@ -93,18 +89,15 @@ edges | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | -| argvLocal.c:117:15:117:16 | array to pointer conversion | argvLocal.c:117:15:117:16 | printWrapper output argument | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | (const char *)... | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | i4 | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | i4 | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | printWrapper output argument | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | (const char *)... | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | ... ++ | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | -- ... | | argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | -- ... | -| argvLocal.c:122:15:122:16 | i4 | argvLocal.c:122:15:122:16 | printWrapper output argument | | argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | (const char *)... | | argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | ... ++ | | argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | -- ... | @@ -115,8 +108,6 @@ edges | argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | printWrapper output argument | @@ -129,7 +120,6 @@ edges | argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | -| argvLocal.c:128:15:128:16 | array to pointer conversion | argvLocal.c:128:15:128:16 | printWrapper output argument | | argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:131:9:131:14 | (const char *)... | | argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:131:9:131:14 | ... + ... | | argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:132:15:132:20 | ... + ... | @@ -224,6 +214,7 @@ nodes | argvLocal.c:116:9:116:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:116:9:116:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:116:9:116:10 | i3 | semmle.label | i3 | +| argvLocal.c:117:2:117:13 | Arg(0) | semmle.label | Arg(0) | | argvLocal.c:117:15:117:16 | Argument 0 indirection | semmle.label | Argument 0 indirection | | argvLocal.c:117:15:117:16 | array to pointer conversion | semmle.label | array to pointer conversion | | argvLocal.c:117:15:117:16 | array to pointer conversion | semmle.label | array to pointer conversion | @@ -232,6 +223,7 @@ nodes | argvLocal.c:121:9:121:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:121:9:121:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 | +| argvLocal.c:122:2:122:13 | Arg(0) | semmle.label | Arg(0) | | argvLocal.c:122:15:122:16 | Argument 0 indirection | semmle.label | Argument 0 indirection | | argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 | | argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 | @@ -242,6 +234,7 @@ nodes | argvLocal.c:127:9:127:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:127:9:127:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:127:9:127:10 | i5 | semmle.label | i5 | +| argvLocal.c:128:2:128:13 | Arg(0) | semmle.label | Arg(0) | | argvLocal.c:128:15:128:16 | Argument 0 indirection | semmle.label | Argument 0 indirection | | argvLocal.c:128:15:128:16 | array to pointer conversion | semmle.label | array to pointer conversion | | argvLocal.c:128:15:128:16 | array to pointer conversion | semmle.label | array to pointer conversion | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected index ce9b93783af..42fe8a15f20 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected @@ -36,6 +36,7 @@ nodes | globalVars.c:12:2:12:15 | Store | semmle.label | Store | | globalVars.c:15:21:15:23 | val | semmle.label | val | | globalVars.c:16:2:16:12 | Store | semmle.label | Store | +| globalVars.c:24:2:24:9 | Arg(0) | semmle.label | Arg(0) | | globalVars.c:24:11:24:14 | argv | semmle.label | argv | | globalVars.c:24:11:24:14 | argv | semmle.label | argv | | globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... | @@ -46,6 +47,7 @@ nodes | globalVars.c:30:15:30:18 | copy | semmle.label | copy | | globalVars.c:30:15:30:18 | copy | semmle.label | copy | | globalVars.c:30:15:30:18 | copy | semmle.label | copy | +| globalVars.c:35:2:35:9 | Arg(0) | semmle.label | Arg(0) | | globalVars.c:35:11:35:14 | copy | semmle.label | copy | | globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... | | globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected index 4103ac6e6f6..8160b481dee 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected @@ -47,18 +47,16 @@ edges | test.cpp:214:23:214:23 | s | test.cpp:215:21:215:21 | s | | test.cpp:220:21:220:21 | s | test.cpp:221:21:221:21 | s | | test.cpp:220:21:220:21 | s | test.cpp:221:21:221:21 | s | +| test.cpp:227:24:227:29 | call to getenv | test.cpp:214:23:214:23 | s | +| test.cpp:227:24:227:29 | call to getenv | test.cpp:220:21:220:21 | s | | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | (size_t)... | | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | -| test.cpp:227:24:227:29 | call to getenv | test.cpp:235:11:235:20 | (size_t)... | -| test.cpp:227:24:227:29 | call to getenv | test.cpp:237:10:237:19 | (size_t)... | +| test.cpp:227:24:227:37 | (const char *)... | test.cpp:214:23:214:23 | s | +| test.cpp:227:24:227:37 | (const char *)... | test.cpp:220:21:220:21 | s | | test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | (size_t)... | | test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | local_size | | test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | local_size | -| test.cpp:227:24:227:37 | (const char *)... | test.cpp:235:11:235:20 | (size_t)... | -| test.cpp:227:24:227:37 | (const char *)... | test.cpp:237:10:237:19 | (size_t)... | -| test.cpp:235:11:235:20 | (size_t)... | test.cpp:214:23:214:23 | s | -| test.cpp:237:10:237:19 | (size_t)... | test.cpp:220:21:220:21 | s | | test.cpp:241:2:241:32 | Chi [array content] | test.cpp:279:17:279:20 | get_size output argument [array content] | | test.cpp:241:2:241:32 | Chi [array content] | test.cpp:295:18:295:21 | get_size output argument [array content] | | test.cpp:241:2:241:32 | Store | test.cpp:241:2:241:32 | Chi [array content] | @@ -143,8 +141,8 @@ nodes | test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size | | test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size | | test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size | -| test.cpp:235:11:235:20 | (size_t)... | semmle.label | (size_t)... | -| test.cpp:237:10:237:19 | (size_t)... | semmle.label | (size_t)... | +| test.cpp:235:2:235:9 | Arg(0) | semmle.label | Arg(0) | +| test.cpp:237:2:237:8 | Arg(0) | semmle.label | Arg(0) | | test.cpp:241:2:241:32 | Chi [array content] | semmle.label | Chi [array content] | | test.cpp:241:2:241:32 | Store | semmle.label | Store | | test.cpp:241:18:241:23 | call to getenv | semmle.label | call to getenv | From 3b70064606a0df939af48900f6b0fcae2c4707b3 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 5 Oct 2020 14:45:14 +0200 Subject: [PATCH 210/411] C#: Improve data flow summary for System.Lazy<> --- .../semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll | 7 +++++++ .../dataflow/library/LibraryTypeDataFlow.expected | 1 + 2 files changed, 8 insertions(+) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll index fac6c60343e..b7d94baa435 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll @@ -718,6 +718,13 @@ class SystemLazyFlow extends LibraryTypeDataFlow, SystemLazyClass { sink = TCallableFlowSinkReturn() and sinkAp = AccessPath::property(this.getValueProperty()) ) + or + preservesValue = false and + c = this.getValueProperty().getGetter() and + source = TCallableFlowSourceQualifier() and + sourceAp = AccessPath::empty() and + sink = TCallableFlowSinkReturn() and + sinkAp = AccessPath::empty() } } diff --git a/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected b/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected index b2c649eab75..a144979b77c 100644 --- a/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected @@ -442,6 +442,7 @@ callableFlow | System.Int32.TryParse(string, NumberStyles, IFormatProvider, out int) | argument 0 -> return | false | | System.Int32.TryParse(string, out int) | argument 0 -> argument 1 | false | | System.Int32.TryParse(string, out int) | argument 0 -> return | false | +| System.Lazy<>.get_Value() | qualifier -> return | false | | System.Linq.Enumerable.Aggregate(IEnumerable, TAccumulate, Func, Func) | argument 1 -> parameter 0 of argument 2 | true | | System.Linq.Enumerable.Aggregate(IEnumerable, TAccumulate, Func, Func) | output from argument 2 -> parameter 0 of argument 3 | true | | System.Linq.Enumerable.Aggregate(IEnumerable, TAccumulate, Func, Func) | output from argument 3 -> return | true | From 2753a4f3791cce90de765210480257dfd3c57fbc Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 5 Oct 2020 15:11:04 +0200 Subject: [PATCH 211/411] Apply suggestions from code review Co-authored-by: Max Schaefer <54907921+max-schaefer@users.noreply.github.com> --- javascript/ql/src/semmle/javascript/ApiGraphs.qll | 2 +- javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index eb84658ea15..3ee6e0e95da 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -302,7 +302,7 @@ module API { /** Gets a data-flow node that defines this entry point. */ abstract DataFlow::Node getARhs(); - /** Gets a API-node for this entry point. */ + /** Gets an API-graph node for this entry point. */ API::Node getNode() { result = root().getASuccessor(this) } } diff --git a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll index 5f53ccff348..91a62e5b1f4 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll @@ -33,13 +33,13 @@ private module MongoDB { not result.getAnImmediateUse().(DataFlow::ParameterNode).getName() = "db" // mongodb v2 provides a `Db` here } - /** Gets an api node that refers to a `connect` callback. */ + /** Gets an API-graph node that refers to a `connect` callback. */ private API::Node getAMongoDbCallback() { result = getAMongoClient().getMember("connect").getLastParameter() } /** - * Gets an API node that may refer to a MongoDB database connection. + * Gets an API-graph node that may refer to a MongoDB database connection. */ private API::Node getAMongoDb() { result = getAMongoClient().getMember("db").getReturn() @@ -183,7 +183,7 @@ private module Mongoose { */ private class MongooseFunction extends API::Node { /** - * Gets the API node for the result from this function (if the function returns a Query). + * Gets the API-graph node for the result from this function (if the function returns a `Query`). */ abstract API::Node getQueryReturn(); @@ -237,7 +237,7 @@ private module Mongoose { } /** - * Gets a API node referring to a Mongoose Model object. + * Gets a API-graph node referring to a Mongoose Model object. */ private API::Node getModelObject() { result = getAMongooseInstance().getMember("model").getReturn() From e95aefe0b2f5f9ac061c5322b7cb70cc97d4ac82 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 5 Oct 2020 15:13:33 +0200 Subject: [PATCH 212/411] C++: Now that PrimaryArgumentNode is an OperandNode we want a specialized toString on it --- .../code/cpp/ir/dataflow/internal/DataFlowPrivate.qll | 6 ++++++ .../Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected | 4 ++-- .../UncontrolledProcessOperation.expected | 4 ++-- .../Security/CWE/CWE-134/semmle/argv/argvLocal.expected | 6 +++--- .../UncontrolledFormatStringThroughGlobalVar.expected | 4 ++-- .../TaintedAllocationSize/TaintedAllocationSize.expected | 4 ++-- 6 files changed, 17 insertions(+), 11 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 243a2870481..359550995c3 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -33,6 +33,12 @@ private class PrimaryArgumentNode extends ArgumentNode { or op = call.getThisArgumentOperand() and pos = -1 } + + override string toString() { + result = "Argument " + op.(PositionalArgumentOperand).getIndex() + or + op instanceof ThisArgumentOperand and result = "this" + } } /** diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected index 31a218c03fa..20bb97a9f66 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected @@ -21,8 +21,8 @@ nodes | search.c:23:39:23:43 | query | semmle.label | query | | search.c:41:21:41:26 | call to getenv | semmle.label | call to getenv | | search.c:41:21:41:26 | call to getenv | semmle.label | call to getenv | -| search.c:45:5:45:15 | Arg(0) | semmle.label | Arg(0) | -| search.c:47:5:47:15 | Arg(0) | semmle.label | Arg(0) | +| search.c:45:5:45:15 | Argument 0 | semmle.label | Argument 0 | +| search.c:47:5:47:15 | Argument 0 | semmle.label | Argument 0 | #select | search.c:17:8:17:12 | query | search.c:41:21:41:26 | call to getenv | search.c:17:8:17:12 | query | Cross-site scripting vulnerability due to $@. | search.c:41:21:41:26 | call to getenv | this query data | | search.c:23:39:23:43 | query | search.c:41:21:41:26 | call to getenv | search.c:23:39:23:43 | query | Cross-site scripting vulnerability due to $@. | search.c:41:21:41:26 | call to getenv | this query data | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected index 5b537d44080..94c1e3383fe 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected @@ -32,10 +32,10 @@ nodes | test.cpp:31:10:31:16 | command | semmle.label | command | | test.cpp:31:10:31:16 | command | semmle.label | command | | test.cpp:31:10:31:16 | command | semmle.label | command | -| test.cpp:42:7:42:16 | Arg(0) | semmle.label | Arg(0) | +| test.cpp:42:7:42:16 | Argument 0 | semmle.label | Argument 0 | | test.cpp:42:18:42:23 | call to getenv | semmle.label | call to getenv | | test.cpp:42:18:42:34 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:43:7:43:16 | Arg(0) | semmle.label | Arg(0) | +| test.cpp:43:7:43:16 | Argument 0 | semmle.label | Argument 0 | | test.cpp:43:18:43:23 | call to getenv | semmle.label | call to getenv | | test.cpp:43:18:43:34 | (const char *)... | semmle.label | (const char *)... | | test.cpp:56:12:56:17 | buffer | semmle.label | buffer | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected index ea59c15da13..ac52436676c 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected @@ -214,7 +214,7 @@ nodes | argvLocal.c:116:9:116:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:116:9:116:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:116:9:116:10 | i3 | semmle.label | i3 | -| argvLocal.c:117:2:117:13 | Arg(0) | semmle.label | Arg(0) | +| argvLocal.c:117:2:117:13 | Argument 0 | semmle.label | Argument 0 | | argvLocal.c:117:15:117:16 | Argument 0 indirection | semmle.label | Argument 0 indirection | | argvLocal.c:117:15:117:16 | array to pointer conversion | semmle.label | array to pointer conversion | | argvLocal.c:117:15:117:16 | array to pointer conversion | semmle.label | array to pointer conversion | @@ -223,7 +223,7 @@ nodes | argvLocal.c:121:9:121:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:121:9:121:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 | -| argvLocal.c:122:2:122:13 | Arg(0) | semmle.label | Arg(0) | +| argvLocal.c:122:2:122:13 | Argument 0 | semmle.label | Argument 0 | | argvLocal.c:122:15:122:16 | Argument 0 indirection | semmle.label | Argument 0 indirection | | argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 | | argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 | @@ -234,7 +234,7 @@ nodes | argvLocal.c:127:9:127:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:127:9:127:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:127:9:127:10 | i5 | semmle.label | i5 | -| argvLocal.c:128:2:128:13 | Arg(0) | semmle.label | Arg(0) | +| argvLocal.c:128:2:128:13 | Argument 0 | semmle.label | Argument 0 | | argvLocal.c:128:15:128:16 | Argument 0 indirection | semmle.label | Argument 0 indirection | | argvLocal.c:128:15:128:16 | array to pointer conversion | semmle.label | array to pointer conversion | | argvLocal.c:128:15:128:16 | array to pointer conversion | semmle.label | array to pointer conversion | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected index 42fe8a15f20..00f98ac48be 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected @@ -36,7 +36,7 @@ nodes | globalVars.c:12:2:12:15 | Store | semmle.label | Store | | globalVars.c:15:21:15:23 | val | semmle.label | val | | globalVars.c:16:2:16:12 | Store | semmle.label | Store | -| globalVars.c:24:2:24:9 | Arg(0) | semmle.label | Arg(0) | +| globalVars.c:24:2:24:9 | Argument 0 | semmle.label | Argument 0 | | globalVars.c:24:11:24:14 | argv | semmle.label | argv | | globalVars.c:24:11:24:14 | argv | semmle.label | argv | | globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... | @@ -47,7 +47,7 @@ nodes | globalVars.c:30:15:30:18 | copy | semmle.label | copy | | globalVars.c:30:15:30:18 | copy | semmle.label | copy | | globalVars.c:30:15:30:18 | copy | semmle.label | copy | -| globalVars.c:35:2:35:9 | Arg(0) | semmle.label | Arg(0) | +| globalVars.c:35:2:35:9 | Argument 0 | semmle.label | Argument 0 | | globalVars.c:35:11:35:14 | copy | semmle.label | copy | | globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... | | globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected index 8160b481dee..a60e361fc1e 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected @@ -141,8 +141,8 @@ nodes | test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size | | test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size | | test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size | -| test.cpp:235:2:235:9 | Arg(0) | semmle.label | Arg(0) | -| test.cpp:237:2:237:8 | Arg(0) | semmle.label | Arg(0) | +| test.cpp:235:2:235:9 | Argument 0 | semmle.label | Argument 0 | +| test.cpp:237:2:237:8 | Argument 0 | semmle.label | Argument 0 | | test.cpp:241:2:241:32 | Chi [array content] | semmle.label | Chi [array content] | | test.cpp:241:2:241:32 | Store | semmle.label | Store | | test.cpp:241:18:241:23 | call to getenv | semmle.label | call to getenv | From a6d7b1f9d937d8164574f540c99618cead5d1614 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 5 Oct 2020 15:21:15 +0200 Subject: [PATCH 213/411] Update cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll Co-authored-by: Jonas Jensen --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 359550995c3..e780c5c7eb3 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -37,7 +37,7 @@ private class PrimaryArgumentNode extends ArgumentNode { override string toString() { result = "Argument " + op.(PositionalArgumentOperand).getIndex() or - op instanceof ThisArgumentOperand and result = "this" + op instanceof ThisArgumentOperand and result = "This argument" } } From d93b37d5c5ba60b9ddb707b143e2bba69265b4cd Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 5 Oct 2020 15:11:23 +0100 Subject: [PATCH 214/411] C++: Autoformat some more files. --- cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql | 8 ++------ .../code/cpp/models/implementations/IdentityFunction.qll | 4 +--- cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll | 3 ++- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql b/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql index 367c6ac7700..cd4ec6be780 100644 --- a/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql +++ b/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql @@ -65,16 +65,12 @@ class IFStream extends Type { * The variable `std::cin` or `std::wcin`. */ class CinVariable extends NamespaceVariable { - CinVariable() { - this.hasQualifiedName("std", ["cin", "wcin"]) - } + CinVariable() { this.hasQualifiedName("std", ["cin", "wcin"]) } } /** A call to `std::operator>>`. */ class OperatorRShiftCall extends FunctionCall { - OperatorRShiftCall() { - getTarget().hasQualifiedName("std", "operator>>") - } + OperatorRShiftCall() { getTarget().hasQualifiedName("std", "operator>>") } /* * This is complicated by the fact this overload can be made diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/IdentityFunction.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/IdentityFunction.qll index decce4dce70..b717bfdfbd0 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/IdentityFunction.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/IdentityFunction.qll @@ -7,9 +7,7 @@ import semmle.code.cpp.models.interfaces.SideEffect * The standard function templates `std::move` and `std::forward`. */ class IdentityFunction extends DataFlowFunction, SideEffectFunction, AliasFunction { - IdentityFunction() { - this.hasQualifiedName("std", ["move", "forward"]) - } + IdentityFunction() { this.hasQualifiedName("std", ["move", "forward"]) } override predicate hasOnlySpecificReadSideEffects() { any() } diff --git a/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll b/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll index 8c4783611b5..4b206d984dc 100644 --- a/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll @@ -276,7 +276,8 @@ private predicate insideFunctionValueMoveTo(Element src, Element dest) { dest = formattingSend and formattingSend.getArgument(arg) = src and format = formattingSend.getFormat() and - format.getConversionChar(arg - formattingSend.getTarget().getNumberOfParameters()) = ["s", "S", "@"] + format.getConversionChar(arg - formattingSend.getTarget().getNumberOfParameters()) = + ["s", "S", "@"] ) or // Expressions computed from tainted data are also tainted From c1b5357e74ba2f908c865e29dc703b8ea39ee581 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 5 Oct 2020 16:53:05 +0200 Subject: [PATCH 215/411] remove stray todo --- javascript/ql/src/semmle/javascript/ES2015Modules.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/ES2015Modules.qll b/javascript/ql/src/semmle/javascript/ES2015Modules.qll index c25b070d829..a672ac71f91 100644 --- a/javascript/ql/src/semmle/javascript/ES2015Modules.qll +++ b/javascript/ql/src/semmle/javascript/ES2015Modules.qll @@ -235,7 +235,7 @@ abstract class ExportDeclaration extends Stmt, @export_declaration { ES2015Module getEnclosingModule() { this = result.getAnExport() } /** Holds if this export declaration exports variable `v` under the name `name`. */ - abstract predicate exportsAs(LexicalName v, string name); // TODO: Can I deprecate this? + abstract predicate exportsAs(LexicalName v, string name); /** * Gets the data flow node corresponding to the value this declaration exports From c39bca52405531281774ea287a1d2950652dd8a3 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 5 Oct 2020 17:14:37 +0200 Subject: [PATCH 216/411] C#: Model data-flow for `System.Threading.Tasks.Task.GetAwaiter()` --- .../csharp/dataflow/LibraryTypeDataFlow.qll | 41 +++++++++++++++++-- .../system/runtime/CompilerServices.qll | 30 ++++++++++++++ .../frameworks/system/threading/Tasks.qll | 3 ++ .../dataflow/library/LibraryTypeDataFlow.cs | 2 +- .../library/LibraryTypeDataFlow.expected | 2 + 5 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 csharp/ql/src/semmle/code/csharp/frameworks/system/runtime/CompilerServices.qll diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll index 5b63c2c9726..86dcd68e01c 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll @@ -11,6 +11,7 @@ private import semmle.code.csharp.frameworks.system.io.Compression private import semmle.code.csharp.frameworks.system.linq.Expressions private import semmle.code.csharp.frameworks.system.Net private import semmle.code.csharp.frameworks.system.Text +private import semmle.code.csharp.frameworks.system.runtime.CompilerServices private import semmle.code.csharp.frameworks.system.threading.Tasks private import semmle.code.csharp.frameworks.system.Web private import semmle.code.csharp.frameworks.system.web.ui.WebControls @@ -95,6 +96,11 @@ module AccessPath { result = singleton(any(PropertyContent c | c.getProperty() = p.getSourceDeclaration())) } + /** Gets a singleton field access path. */ + AccessPath field(Field f) { + result = singleton(any(FieldContent c | c.getField() = f.getSourceDeclaration())) + } + /** Gets an access path representing a property inside a collection. */ AccessPath properties(Property p) { result = TConsAccessPath(any(ElementContent c), property(p)) } } @@ -1714,9 +1720,7 @@ class SystemThreadingTasksTaskFlow extends LibraryTypeDataFlow, SystemThreadingT } /** Data flow for `System.Threading.Tasks.Task<>`. */ -class SystemThreadingTasksTaskTFlow extends LibraryTypeDataFlow { - SystemThreadingTasksTaskTFlow() { this instanceof SystemThreadingTasksTaskTClass } - +class SystemThreadingTasksTaskTFlow extends LibraryTypeDataFlow, SystemThreadingTasksTaskTClass { override predicate callableFlow( CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp, SourceDeclarationCallable c, boolean preservesValue @@ -1807,6 +1811,14 @@ class SystemThreadingTasksTaskTFlow extends LibraryTypeDataFlow { sinkAp = AccessPath::property(this.(SystemThreadingTasksTaskTClass).getResultProperty()) ) ) + or + m = this.getGetAwaiterMethod() and + source = TCallableFlowSourceQualifier() and + sourceAp = AccessPath::empty() and + sink = TCallableFlowSinkReturn() and + sinkAp = + AccessPath::field(any(SystemRuntimeCompilerServicesTaskAwaiterStruct s) + .getUnderlyingTaskField()) } } @@ -1891,6 +1903,29 @@ class SystemThreadingTasksFactoryFlow extends LibraryTypeDataFlow { } } +/** Data flow for `System.Runtime.CompilerServices.TaskAwaiter<>`. */ +class SystemRuntimeCompilerServicesTaskAwaiterFlow extends LibraryTypeDataFlow, + SystemRuntimeCompilerServicesTaskAwaiterStruct { + override predicate callableFlow( + CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp, + SourceDeclarationCallable c, boolean preservesValue + ) { + preservesValue = true and + c = this.getGetResultMethod() and + source = TCallableFlowSourceQualifier() and + sourceAp = + AccessPath::cons(any(FieldContent fc | fc.getField() = this.getUnderlyingTaskField()), + AccessPath::property(any(SystemThreadingTasksTaskTClass t).getResultProperty())) and + sink = TCallableFlowSinkReturn() and + sinkAp = AccessPath::empty() + } + + override predicate requiresAccessPath(Content head, AccessPath tail) { + head.(FieldContent).getField() = this.getUnderlyingTaskField() and + tail = AccessPath::property(any(SystemThreadingTasksTaskTClass t).getResultProperty()) + } +} + /** Data flow for `System.Text.Encoding`. */ library class SystemTextEncodingFlow extends LibraryTypeDataFlow, SystemTextEncodingClass { override predicate callableFlow( diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/runtime/CompilerServices.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/runtime/CompilerServices.qll new file mode 100644 index 00000000000..a5dd6e4c20f --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/runtime/CompilerServices.qll @@ -0,0 +1,30 @@ +/** Provides definitions related to the namespace `System.Runtime.CompilerServices`. */ + +import csharp +private import semmle.code.csharp.frameworks.system.Runtime + +/** The `System.Runtime.CompilerServices` namespace. */ +class SystemRuntimeCompilerServicesNamespace extends Namespace { + SystemRuntimeCompilerServicesNamespace() { + this.getParentNamespace() instanceof SystemRuntimeNamespace and + this.hasName("CompilerServices") + } +} + +/** An unbound generic struct in the `System.Runtime.CompilerServices` namespace. */ +class SystemRuntimeCompilerServicesNamespaceUnboundGenericStruct extends UnboundGenericStruct { + SystemRuntimeCompilerServicesNamespaceUnboundGenericStruct() { + this = any(SystemRuntimeCompilerServicesNamespace n).getATypeDeclaration() + } +} + +/** The `System.Runtime.CompilerServices.TaskAwaiter<>` struct. */ +class SystemRuntimeCompilerServicesTaskAwaiterStruct extends SystemRuntimeCompilerServicesNamespaceUnboundGenericStruct { + SystemRuntimeCompilerServicesTaskAwaiterStruct() { this.hasName("TaskAwaiter<>") } + + /** Gets the `GetResult` method. */ + Method getGetResultMethod() { result = this.getAMethod("GetResult") } + + /** Gets the field that stores the underlying task. */ + Field getUnderlyingTaskField() { result = this.getAField() and result.hasName("m_task") } +} diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/threading/Tasks.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/threading/Tasks.qll index 808ce188aac..bf1898baf00 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/threading/Tasks.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/threading/Tasks.qll @@ -38,4 +38,7 @@ class SystemThreadingTasksTaskTClass extends SystemThreadingTasksUnboundGenericC result.hasName("Result") and result.getType() = this.getTypeParameter(0) } + + /** Gets the `GetAwaiter` method. */ + Method getGetAwaiterMethod() { result = this.getAMethod("GetAwaiter") } } diff --git a/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.cs b/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.cs index e6aea19d9c0..431cb6843e9 100644 --- a/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.cs +++ b/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.cs @@ -85,7 +85,7 @@ public class LibraryTypeDataFlow HttpContextBase context = null; string name = context.Request.QueryString["name"]; - var dict = new Dictionary() { {"abc", 0 } }; + var dict = new Dictionary() { { "abc", 0 } }; } [DataContract] diff --git a/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected b/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected index 72dc7c72060..650f8cb7dff 100644 --- a/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected @@ -1780,6 +1780,7 @@ callableFlowAccessPath | System.Runtime.CompilerServices.ReadOnlyCollectionBuilder<>.Reverse(int, int) | argument 0 [[]] -> return [[]] | true | | System.Runtime.CompilerServices.ReadOnlyCollectionBuilder<>.get_Item(int) | qualifier [[]] -> return [] | true | | System.Runtime.CompilerServices.ReadOnlyCollectionBuilder<>.set_Item(int, T) | argument 1 [] -> qualifier [[]] | true | +| System.Runtime.CompilerServices.TaskAwaiter<>.GetResult() | qualifier [m_task, Result] -> return [] | true | | System.Security.PermissionSet.CopyTo(Array, int) | qualifier [[]] -> argument 0 [[]] | true | | System.Security.PermissionSet.GetEnumerator() | qualifier [[]] -> return [Current] | true | | System.String.Concat(IEnumerable) | argument 0 [[]] -> return [] | false | @@ -1929,6 +1930,7 @@ callableFlowAccessPath | System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 0 [] -> return [Result] | true | | System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, TaskContinuationOptions) | output from argument 0 [] -> return [Result] | true | | System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, TaskScheduler) | output from argument 0 [] -> return [Result] | true | +| System.Threading.Tasks.Task<>.GetAwaiter() | qualifier [] -> return [m_task] | true | | System.Threading.Tasks.Task<>.Task(Func, object) | output from argument 0 [] -> return [Result] | true | | System.Threading.Tasks.Task<>.Task(Func, object, CancellationToken) | output from argument 0 [] -> return [Result] | true | | System.Threading.Tasks.Task<>.Task(Func, object, CancellationToken, TaskCreationOptions) | output from argument 0 [] -> return [Result] | true | From 7d8bb339b6fb9a4bed2fcc3ed20b59719e6c8b23 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 5 Oct 2020 21:24:02 +0200 Subject: [PATCH 217/411] add support for destructuring object exports in `getAnExportedValue` --- javascript/ql/src/semmle/javascript/ES2015Modules.qll | 7 +++++++ javascript/ql/test/library-tests/Modules/tests.expected | 2 ++ 2 files changed, 9 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/ES2015Modules.qll b/javascript/ql/src/semmle/javascript/ES2015Modules.qll index a672ac71f91..47a8ff426ae 100644 --- a/javascript/ql/src/semmle/javascript/ES2015Modules.qll +++ b/javascript/ql/src/semmle/javascript/ES2015Modules.qll @@ -395,6 +395,13 @@ class ExportNamedDeclaration extends ExportDeclaration, @export_named_declaratio result = DataFlow::valueNode(d.getSource()) ) or + exists(ObjectPattern obj | obj = getOperand().(DeclStmt).getADecl().getBindingPattern() | + exists(DataFlow::PropRead read | read = result | + read.getBase() = obj.flow() and + name = read.getPropertyName() + ) + ) + or exists(ExportSpecifier spec | spec = getASpecifier() and name = spec.getExportedName() | not exists(getImportedPath()) and result = DataFlow::valueNode(spec.getLocal()) or diff --git a/javascript/ql/test/library-tests/Modules/tests.expected b/javascript/ql/test/library-tests/Modules/tests.expected index 55aa808b14f..810ae718add 100644 --- a/javascript/ql/test/library-tests/Modules/tests.expected +++ b/javascript/ql/test/library-tests/Modules/tests.expected @@ -71,6 +71,7 @@ test_Imports test_Module_exports | a.js:1:1:5:32 | | default | a.js:1:16:3:1 | functio ... n 23;\\n} | | a.js:1:1:5:32 | | x | a.js:5:18:5:20 | f() | +| a.js:1:1:5:32 | | y | a.js:5:25:5:25 | y | | b.js:1:1:8:0 | | f2 | a.js:1:16:3:1 | functio ... n 23;\\n} | | b.js:1:1:8:0 | | g | b.js:5:10:5:10 | f | | e.js:1:1:4:0 | | g | a.js:1:16:3:1 | functio ... n 23;\\n} | @@ -135,6 +136,7 @@ test_getLocalName test_getSourceNode | a.js:1:1:3:1 | export ... n 23;\\n} | default | a.js:1:16:3:1 | functio ... n 23;\\n} | | a.js:5:1:5:32 | export ... } = o; | x | a.js:5:18:5:20 | f() | +| a.js:5:1:5:32 | export ... } = o; | y | a.js:5:25:5:25 | y | | b.js:5:1:5:18 | export { f as g }; | g | b.js:5:10:5:10 | f | | b.js:7:1:7:21 | export ... './a'; | f2 | a.js:1:16:3:1 | functio ... n 23;\\n} | | e.js:2:1:2:16 | export { x, y }; | x | e.js:2:10:2:10 | x | From d6dc4bb6553e6c04fe33d0c88fcee5803cbde305 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sat, 3 Oct 2020 14:35:54 +0200 Subject: [PATCH 218/411] allow flask url_for urls in TargetBlank.ql --- javascript/ql/src/DOM/TargetBlank.ql | 4 +++- javascript/ql/test/query-tests/DOM/TargetBlank/tst.js | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/DOM/TargetBlank.ql b/javascript/ql/src/DOM/TargetBlank.ql index ae2978dbdcd..c925000159f 100644 --- a/javascript/ql/src/DOM/TargetBlank.ql +++ b/javascript/ql/src/DOM/TargetBlank.ql @@ -31,7 +31,9 @@ predicate hasDynamicHrefHostAttributeValue(DOM::ElementDefinition elem) { // fixed string with templating url.regexpMatch(Templating::getDelimiterMatchingRegexpWithPrefix("[^?#]*")) and // ... that does not start with a fixed host or a relative path (common formats) - not url.regexpMatch("(?i)((https?:)?//)?[-a-z0-9.]*/.*") + not url.regexpMatch("(?i)((https?:)?//)?[-a-z0-9.]*/.*") and + // .. that is not a call to `url_for` in a Flask application + not url.regexpMatch("\\{\\{\\s*url_for.*") ) ) } diff --git a/javascript/ql/test/query-tests/DOM/TargetBlank/tst.js b/javascript/ql/test/query-tests/DOM/TargetBlank/tst.js index a9afbac4646..95412acac39 100644 --- a/javascript/ql/test/query-tests/DOM/TargetBlank/tst.js +++ b/javascript/ql/test/query-tests/DOM/TargetBlank/tst.js @@ -58,3 +58,8 @@ function f() { Example; Example; Example; + +// OK, Flask application with internal links +Example; +Example; +Example; \ No newline at end of file From d7526c40ba804fa9b082591ca0c3e5e79437df6f Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 30 Sep 2020 14:33:14 +0200 Subject: [PATCH 219/411] Python: Copy old flask tests to new dataflow setup --- .../frameworks/flask/TestTaint.expected | 196 +++++++++--------- .../frameworks/flask/old_test.py | 67 ++++++ .../flask/{test.py => taint_test.py} | 0 3 files changed, 165 insertions(+), 98 deletions(-) create mode 100644 python/ql/test/experimental/library-tests/frameworks/flask/old_test.py rename python/ql/test/experimental/library-tests/frameworks/flask/{test.py => taint_test.py} (100%) diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/TestTaint.expected b/python/ql/test/experimental/library-tests/frameworks/flask/TestTaint.expected index 9a5e8e26009..d9ec3129b78 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/TestTaint.expected +++ b/python/ql/test/experimental/library-tests/frameworks/flask/TestTaint.expected @@ -1,98 +1,98 @@ -| test.py:6 | fail | test_taint | name | -| test.py:6 | fail | test_taint | number | -| test.py:7 | ok | test_taint | foo | -| test.py:14 | ok | test_taint | request.environ | -| test.py:15 | ok | test_taint | request.environ.get(..) | -| test.py:17 | ok | test_taint | request.path | -| test.py:18 | ok | test_taint | request.full_path | -| test.py:19 | ok | test_taint | request.base_url | -| test.py:20 | ok | test_taint | request.url | -| test.py:23 | fail | test_taint | request.accept_charsets.best | -| test.py:24 | fail | test_taint | request.accept_charsets.best_match(..) | -| test.py:25 | ok | test_taint | request.accept_charsets[0] | -| test.py:26 | ok | test_taint | request.accept_encodings | -| test.py:27 | ok | test_taint | request.accept_languages | -| test.py:28 | ok | test_taint | request.accept_mimetypes | -| test.py:31 | ok | test_taint | request.access_control_request_headers | -| test.py:33 | ok | test_taint | request.access_control_request_method | -| test.py:35 | ok | test_taint | request.access_route | -| test.py:36 | ok | test_taint | request.access_route[0] | -| test.py:39 | ok | test_taint | request.args | -| test.py:40 | ok | test_taint | request.args['key'] | -| test.py:41 | ok | test_taint | request.args.getlist(..) | -| test.py:44 | ok | test_taint | request.authorization | -| test.py:45 | ok | test_taint | request.authorization['username'] | -| test.py:46 | fail | test_taint | request.authorization.username | -| test.py:49 | ok | test_taint | request.cache_control | -| test.py:51 | fail | test_taint | request.cache_control.max_age | -| test.py:52 | fail | test_taint | request.cache_control.max_stale | -| test.py:53 | fail | test_taint | request.cache_control.min_fresh | -| test.py:55 | ok | test_taint | request.content_encoding | -| test.py:57 | ok | test_taint | request.content_md5 | -| test.py:59 | ok | test_taint | request.content_type | -| test.py:62 | ok | test_taint | request.cookies | -| test.py:63 | ok | test_taint | request.cookies['key'] | -| test.py:65 | ok | test_taint | request.data | -| test.py:68 | ok | test_taint | request.files | -| test.py:69 | ok | test_taint | request.files['key'] | -| test.py:70 | fail | test_taint | request.files['key'].filename | -| test.py:71 | fail | test_taint | request.files['key'].stream | -| test.py:72 | ok | test_taint | request.files.getlist(..) | -| test.py:73 | fail | test_taint | request.files.getlist(..)[0].filename | -| test.py:74 | fail | test_taint | request.files.getlist(..)[0].stream | -| test.py:77 | ok | test_taint | request.form | -| test.py:78 | ok | test_taint | request.form['key'] | -| test.py:79 | ok | test_taint | request.form.getlist(..) | -| test.py:81 | ok | test_taint | request.get_data() | -| test.py:83 | ok | test_taint | request.get_json() | -| test.py:84 | ok | test_taint | request.get_json()['foo'] | -| test.py:85 | ok | test_taint | request.get_json()['foo']['bar'] | -| test.py:89 | ok | test_taint | request.headers | -| test.py:90 | ok | test_taint | request.headers['key'] | -| test.py:91 | fail | test_taint | request.headers.get_all(..) | -| test.py:92 | fail | test_taint | request.headers.getlist(..) | -| test.py:93 | ok | test_taint | list(..) | -| test.py:94 | fail | test_taint | request.headers.to_wsgi_list() | -| test.py:96 | ok | test_taint | request.json | -| test.py:97 | ok | test_taint | request.json['foo'] | -| test.py:98 | ok | test_taint | request.json['foo']['bar'] | -| test.py:100 | ok | test_taint | request.method | -| test.py:102 | ok | test_taint | request.mimetype | -| test.py:104 | ok | test_taint | request.mimetype_params | -| test.py:106 | ok | test_taint | request.origin | -| test.py:109 | ok | test_taint | request.pragma | -| test.py:111 | ok | test_taint | request.query_string | -| test.py:113 | ok | test_taint | request.referrer | -| test.py:115 | ok | test_taint | request.remote_addr | -| test.py:117 | ok | test_taint | request.remote_user | -| test.py:120 | ok | test_taint | request.stream | -| test.py:121 | ok | test_taint | request.input_stream | -| test.py:123 | ok | test_taint | request.url | -| test.py:125 | ok | test_taint | request.user_agent | -| test.py:128 | ok | test_taint | request.values | -| test.py:129 | ok | test_taint | request.values['key'] | -| test.py:130 | ok | test_taint | request.values.getlist(..) | -| test.py:133 | ok | test_taint | request.view_args | -| test.py:134 | ok | test_taint | request.view_args['key'] | -| test.py:138 | ok | test_taint | request.script_root | -| test.py:139 | ok | test_taint | request.url_root | -| test.py:143 | ok | test_taint | request.charset | -| test.py:144 | ok | test_taint | request.url_charset | -| test.py:148 | ok | test_taint | request.date | -| test.py:151 | ok | test_taint | request.endpoint | -| test.py:156 | ok | test_taint | request.host | -| test.py:157 | ok | test_taint | request.host_url | -| test.py:159 | ok | test_taint | request.scheme | -| test.py:161 | ok | test_taint | request.script_root | -| test.py:169 | ok | test_taint | request.args | -| test.py:170 | ok | test_taint | a | -| test.py:171 | ok | test_taint | b | -| test.py:173 | ok | test_taint | request.args['key'] | -| test.py:174 | ok | test_taint | a['key'] | -| test.py:175 | ok | test_taint | b['key'] | -| test.py:177 | ok | test_taint | request.args.getlist(..) | -| test.py:178 | ok | test_taint | a.getlist(..) | -| test.py:179 | ok | test_taint | b.getlist(..) | -| test.py:180 | ok | test_taint | gl(..) | -| test.py:187 | ok | test_taint | req.path | -| test.py:188 | ok | test_taint | gd() | +| taint_test.py:6 | fail | test_taint | name | +| taint_test.py:6 | fail | test_taint | number | +| taint_test.py:7 | ok | test_taint | foo | +| taint_test.py:14 | ok | test_taint | request.environ | +| taint_test.py:15 | ok | test_taint | request.environ.get(..) | +| taint_test.py:17 | ok | test_taint | request.path | +| taint_test.py:18 | ok | test_taint | request.full_path | +| taint_test.py:19 | ok | test_taint | request.base_url | +| taint_test.py:20 | ok | test_taint | request.url | +| taint_test.py:23 | fail | test_taint | request.accept_charsets.best | +| taint_test.py:24 | fail | test_taint | request.accept_charsets.best_match(..) | +| taint_test.py:25 | ok | test_taint | request.accept_charsets[0] | +| taint_test.py:26 | ok | test_taint | request.accept_encodings | +| taint_test.py:27 | ok | test_taint | request.accept_languages | +| taint_test.py:28 | ok | test_taint | request.accept_mimetypes | +| taint_test.py:31 | ok | test_taint | request.access_control_request_headers | +| taint_test.py:33 | ok | test_taint | request.access_control_request_method | +| taint_test.py:35 | ok | test_taint | request.access_route | +| taint_test.py:36 | ok | test_taint | request.access_route[0] | +| taint_test.py:39 | ok | test_taint | request.args | +| taint_test.py:40 | ok | test_taint | request.args['key'] | +| taint_test.py:41 | ok | test_taint | request.args.getlist(..) | +| taint_test.py:44 | ok | test_taint | request.authorization | +| taint_test.py:45 | ok | test_taint | request.authorization['username'] | +| taint_test.py:46 | fail | test_taint | request.authorization.username | +| taint_test.py:49 | ok | test_taint | request.cache_control | +| taint_test.py:51 | fail | test_taint | request.cache_control.max_age | +| taint_test.py:52 | fail | test_taint | request.cache_control.max_stale | +| taint_test.py:53 | fail | test_taint | request.cache_control.min_fresh | +| taint_test.py:55 | ok | test_taint | request.content_encoding | +| taint_test.py:57 | ok | test_taint | request.content_md5 | +| taint_test.py:59 | ok | test_taint | request.content_type | +| taint_test.py:62 | ok | test_taint | request.cookies | +| taint_test.py:63 | ok | test_taint | request.cookies['key'] | +| taint_test.py:65 | ok | test_taint | request.data | +| taint_test.py:68 | ok | test_taint | request.files | +| taint_test.py:69 | ok | test_taint | request.files['key'] | +| taint_test.py:70 | fail | test_taint | request.files['key'].filename | +| taint_test.py:71 | fail | test_taint | request.files['key'].stream | +| taint_test.py:72 | ok | test_taint | request.files.getlist(..) | +| taint_test.py:73 | fail | test_taint | request.files.getlist(..)[0].filename | +| taint_test.py:74 | fail | test_taint | request.files.getlist(..)[0].stream | +| taint_test.py:77 | ok | test_taint | request.form | +| taint_test.py:78 | ok | test_taint | request.form['key'] | +| taint_test.py:79 | ok | test_taint | request.form.getlist(..) | +| taint_test.py:81 | ok | test_taint | request.get_data() | +| taint_test.py:83 | ok | test_taint | request.get_json() | +| taint_test.py:84 | ok | test_taint | request.get_json()['foo'] | +| taint_test.py:85 | ok | test_taint | request.get_json()['foo']['bar'] | +| taint_test.py:89 | ok | test_taint | request.headers | +| taint_test.py:90 | ok | test_taint | request.headers['key'] | +| taint_test.py:91 | fail | test_taint | request.headers.get_all(..) | +| taint_test.py:92 | fail | test_taint | request.headers.getlist(..) | +| taint_test.py:93 | ok | test_taint | list(..) | +| taint_test.py:94 | fail | test_taint | request.headers.to_wsgi_list() | +| taint_test.py:96 | ok | test_taint | request.json | +| taint_test.py:97 | ok | test_taint | request.json['foo'] | +| taint_test.py:98 | ok | test_taint | request.json['foo']['bar'] | +| taint_test.py:100 | ok | test_taint | request.method | +| taint_test.py:102 | ok | test_taint | request.mimetype | +| taint_test.py:104 | ok | test_taint | request.mimetype_params | +| taint_test.py:106 | ok | test_taint | request.origin | +| taint_test.py:109 | ok | test_taint | request.pragma | +| taint_test.py:111 | ok | test_taint | request.query_string | +| taint_test.py:113 | ok | test_taint | request.referrer | +| taint_test.py:115 | ok | test_taint | request.remote_addr | +| taint_test.py:117 | ok | test_taint | request.remote_user | +| taint_test.py:120 | ok | test_taint | request.stream | +| taint_test.py:121 | ok | test_taint | request.input_stream | +| taint_test.py:123 | ok | test_taint | request.url | +| taint_test.py:125 | ok | test_taint | request.user_agent | +| taint_test.py:128 | ok | test_taint | request.values | +| taint_test.py:129 | ok | test_taint | request.values['key'] | +| taint_test.py:130 | ok | test_taint | request.values.getlist(..) | +| taint_test.py:133 | ok | test_taint | request.view_args | +| taint_test.py:134 | ok | test_taint | request.view_args['key'] | +| taint_test.py:138 | ok | test_taint | request.script_root | +| taint_test.py:139 | ok | test_taint | request.url_root | +| taint_test.py:143 | ok | test_taint | request.charset | +| taint_test.py:144 | ok | test_taint | request.url_charset | +| taint_test.py:148 | ok | test_taint | request.date | +| taint_test.py:151 | ok | test_taint | request.endpoint | +| taint_test.py:156 | ok | test_taint | request.host | +| taint_test.py:157 | ok | test_taint | request.host_url | +| taint_test.py:159 | ok | test_taint | request.scheme | +| taint_test.py:161 | ok | test_taint | request.script_root | +| taint_test.py:169 | ok | test_taint | request.args | +| taint_test.py:170 | ok | test_taint | a | +| taint_test.py:171 | ok | test_taint | b | +| taint_test.py:173 | ok | test_taint | request.args['key'] | +| taint_test.py:174 | ok | test_taint | a['key'] | +| taint_test.py:175 | ok | test_taint | b['key'] | +| taint_test.py:177 | ok | test_taint | request.args.getlist(..) | +| taint_test.py:178 | ok | test_taint | a.getlist(..) | +| taint_test.py:179 | ok | test_taint | b.getlist(..) | +| taint_test.py:180 | ok | test_taint | gl(..) | +| taint_test.py:187 | ok | test_taint | req.path | +| taint_test.py:188 | ok | test_taint | gd() | diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/old_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/old_test.py new file mode 100644 index 00000000000..bedeaa56423 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/flask/old_test.py @@ -0,0 +1,67 @@ +import flask + +from flask import Flask, request, make_response +app = Flask(__name__) + +@app.route("/") +def hello_world(): + return "Hello World!" + +from flask.views import MethodView + +class MyView(MethodView): + + def get(self, user_id): + if user_id is None: + # return a list of users + pass + else: + # expose a single user + pass + +the_view = MyView.as_view('my_view') + +app.add_url_rule('/the/', defaults={'user_id': None}, + view_func=the_view, methods=['GET',]) + +@app.route("/dangerous") +def dangerous(): + return request.args.get('payload') + +@app.route("/dangerous-with-cfg-split") +def dangerous2(): + x = request.form['param0'] + if request.method == "POST": + return request.form['param1'] + return None + +@app.route('/unsafe') +def unsafe(): + first_name = request.args.get('name', '') + return make_response("Your name is " + first_name) + +@app.route('/safe') +def safe(): + first_name = request.args.get('name', '') + return make_response("Your name is " + escape(first_name)) + +@app.route('/hello/') +def hello(name): + return make_response("Your name is " + name) + +@app.route('/foo/') +def foo(subpath): + return make_response("The subpath is " + subpath) + +@app.route('/multiple/') # TODO: not recognized as route +@app.route('/multiple/foo/') # TODO: not recognized as route +@app.route('/multiple/bar/') +def multiple(foo=None, bar=None): + return make_response("foo={!r} bar={!r}".format(foo, bar)) + +@app.route('/complex/') +def complex(lang_code): + return make_response("lang_code {}".format(lang_code)) + +if __name__ == "__main__": + app.run(debug=True) diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/test.py b/python/ql/test/experimental/library-tests/frameworks/flask/taint_test.py similarity index 100% rename from python/ql/test/experimental/library-tests/frameworks/flask/test.py rename to python/ql/test/experimental/library-tests/frameworks/flask/taint_test.py From 9f1aa8ca0c98bb2a30f73f48830a6ce5fa1ef2d7 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 2 Oct 2020 18:52:14 +0200 Subject: [PATCH 220/411] Python: Expose getParameter on ParameterNode --- .../ql/src/experimental/dataflow/internal/DataFlowPublic.qll | 3 +++ python/ql/src/semmle/python/essa/Essa.qll | 1 + 2 files changed, 4 insertions(+) diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll b/python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll index fb68fe3b1f1..bec7ca747fa 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll @@ -151,6 +151,9 @@ class ParameterNode extends EssaNode { } override DataFlowCallable getEnclosingCallable() { this.isParameterOf(result, _) } + + /** Gets the `Parameter` this `ParameterNode` represents. */ + Parameter getParameter() { result = var.(ParameterDefinition).getParameter() } } /** diff --git a/python/ql/src/semmle/python/essa/Essa.qll b/python/ql/src/semmle/python/essa/Essa.qll index b44b784b48d..b8cf058c114 100644 --- a/python/ql/src/semmle/python/essa/Essa.qll +++ b/python/ql/src/semmle/python/essa/Essa.qll @@ -567,6 +567,7 @@ class ParameterDefinition extends EssaNodeDefinition { exists(Function func | func.getKwarg() = this.getDefiningNode().getNode()) } + /** Gets the `Parameter` this `ParameterDefinition` represents. */ Parameter getParameter() { result = this.getDefiningNode().getNode() } } From ebc3d32ff13f94d981b763ef8883219454ef83f1 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 6 Oct 2020 02:02:29 +0200 Subject: [PATCH 221/411] Python: Add concept for HTTP server modeling If we want to separate out into a file, we can always do this with ``` import experimental.semmle.python.HTTP as HTTP ``` --- .../experimental/semmle/python/Concepts.qll | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index e1cd0fa580e..cea4bfa2fdd 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -38,3 +38,56 @@ module SystemCommandExecution { abstract DataFlow::Node getCommand(); } } + +/** Provides classes for modeling HTTP-related APIs. */ +module HTTP { + /** Provides classes for modeling HTTP servers. */ + module Server { + /** + * An data-flow node that sets up a route on a server. + * + * Extend this class to model new APIs. If you want to model new APIs, + * extend `RouteSetup::Range` instead. + */ + class RouteSetup extends DataFlow::Node { + RouteSetup::Range range; + + RouteSetup() { this = range } + + /** Gets the URL pattern for this route, if it can be statically determined. */ + string getUrlPattern() { result = range.getUrlPattern() } + + /** Gets a function that will handle incoming requests for this route, if any. */ + Function getARouteHandler() { result = range.getARouteHandler() } + + /** + * Gets a parameter that will receive parts of the url when handling incoming + * requests for this route, if any. These automatically become a `RemoteFlowSource`. + */ + Parameter getARoutedParameter() { result = range.getARoutedParameter() } + } + + /** Provides a class for modeling new HTTP routing APIs. */ + module RouteSetup { + /** + * An data-flow node that sets up a route on a server. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `RouteSetup` instead. + */ + abstract class Range extends DataFlow::Node { + /** Gets the URL pattern for this route, if it can be statically determined. */ + abstract string getUrlPattern(); + + /** Gets a function that will handle incoming requests for this route, if any. */ + abstract Function getARouteHandler(); + + /** + * Gets a parameter that will receive parts of the url when handling incoming + * requests for this route, if any. These automatically become a `RemoteFlowSource`. + */ + abstract Parameter getARoutedParameter(); + } + } + } +} From d27e6955b4846b483a4a8dc6849b22425cdb7785 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 6 Oct 2020 02:47:19 +0200 Subject: [PATCH 222/411] Python: Add test setup for HTTP::Server::RouteSetup --- .../test/experimental/meta/ConceptsTest.qll | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/python/ql/test/experimental/meta/ConceptsTest.qll b/python/ql/test/experimental/meta/ConceptsTest.qll index eb798823d50..85857dabda2 100644 --- a/python/ql/test/experimental/meta/ConceptsTest.qll +++ b/python/ql/test/experimental/meta/ConceptsTest.qll @@ -22,8 +22,8 @@ class SystemCommandExecutionTest extends InlineExpectationsTest { override string getARelevantTag() { result = "getCommand" } override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(location.getFile().getRelativePath()) and exists(SystemCommandExecution sce, DataFlow::Node command | - exists(location.getFile().getRelativePath()) and command = sce.getCommand() and location = command.getLocation() and element = command.toString() and @@ -32,3 +32,39 @@ class SystemCommandExecutionTest extends InlineExpectationsTest { ) } } + +class HttpServerRouteSetupTest extends InlineExpectationsTest { + HttpServerRouteSetupTest() { this = "HttpServerRouteSetupTest" } + + override string getARelevantTag() { result in ["routeSetup", "routeHandler", "routedParameter"] } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(HTTP::Server::RouteSetup setup | + location = setup.getLocation() and + element = setup.toString() and + ( + value = "\"" + setup.getUrlPattern() + "\"" + or + not exists(setup.getUrlPattern()) and + value = "" + ) and + tag = "routeSetup" + ) + or + exists(HTTP::Server::RouteSetup setup, Function func | + func = setup.getARouteHandler() and + location = func.getLocation() and + element = func.toString() and + value = "" and + tag = "routeHandler" + ) + or + exists(HTTP::Server::RouteSetup setup, Parameter param | + param = setup.getARoutedParameter() and + location = param.getLocation() and + element = param.toString() and + value = param.asName().getId() and + tag = "routedParameter" + ) + } +} From b78c665f34b1b756e377870dfe65bbd3d402d7c7 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 6 Oct 2020 02:48:02 +0200 Subject: [PATCH 223/411] Python: Model RouteSetup for flask --- .../semmle/python/frameworks/Flask.qll | 170 +++++++++++++++++- .../frameworks/flask/ConceptsTest.expected | 0 .../frameworks/flask/ConceptsTest.ql | 2 + .../frameworks/flask/old_test.py | 44 ++--- .../frameworks/flask/routing_test.py | 27 +++ .../frameworks/flask/taint_test.py | 32 ++-- 6 files changed, 234 insertions(+), 41 deletions(-) create mode 100644 python/ql/test/experimental/library-tests/frameworks/flask/ConceptsTest.expected create mode 100644 python/ql/test/experimental/library-tests/frameworks/flask/ConceptsTest.ql create mode 100644 python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py diff --git a/python/ql/src/experimental/semmle/python/frameworks/Flask.qll b/python/ql/src/experimental/semmle/python/frameworks/Flask.qll index 5b4079331d7..549d4305419 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Flask.qll @@ -1,5 +1,6 @@ /** - * Provides classes modeling security-relevant aspects of the `flask` package. + * Provides classes modeling security-relevant aspects of the `flask` PyPI package. + * See https://flask.palletsprojects.com/en/1.1.x/. */ private import python @@ -11,6 +12,10 @@ private import experimental.semmle.python.frameworks.Werkzeug // for old improved impl see // https://github.com/github/codeql/blob/9f95212e103c68d0c1dfa4b6f30fb5d53954ccef/python/ql/src/semmle/python/web/flask/Request.qll +/** + * Provides models for the `flask` PyPI package. + * See https://flask.palletsprojects.com/en/1.1.x/. + */ private module Flask { /** Gets a reference to the `flask` module. */ DataFlow::Node flask(DataFlow::TypeTracker t) { @@ -23,6 +28,7 @@ private module Flask { /** Gets a reference to the `flask` module. */ DataFlow::Node flask() { result = flask(DataFlow::TypeTracker::end()) } + /** Provides models for the `flask` module. */ module flask { /** Gets a reference to the `flask.request` object. */ DataFlow::Node request(DataFlow::TypeTracker t) { @@ -32,13 +38,171 @@ private module Flask { t.startInAttr("request") and result = flask() or - exists(DataFlow::TypeTracker t2 | result = flask::request(t2).track(t2, t)) + exists(DataFlow::TypeTracker t2 | result = request(t2).track(t2, t)) } /** Gets a reference to the `flask.request` object. */ - DataFlow::Node request() { result = flask::request(DataFlow::TypeTracker::end()) } + DataFlow::Node request() { result = request(DataFlow::TypeTracker::end()) } + + /** Gets a reference to the `flask.Flask` class. */ + private DataFlow::Node classFlask(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importMember("flask", "Flask") + or + t.startInAttr("Flask") and + result = flask() + or + exists(DataFlow::TypeTracker t2 | result = classFlask(t2).track(t2, t)) + } + + /** Gets a reference to the `flask.Flask` class. */ + DataFlow::Node classFlask() { result = classFlask(DataFlow::TypeTracker::end()) } + + /** Gets a reference to an instance of `flask.Flask` (a Flask application). */ + private DataFlow::Node app(DataFlow::TypeTracker t) { + t.start() and + result.asCfgNode().(CallNode).getFunction() = flask::classFlask().asCfgNode() + or + exists(DataFlow::TypeTracker t2 | result = app(t2).track(t2, t)) + } + + /** Gets a reference to an instance of `flask.Flask` (a flask application). */ + DataFlow::Node app() { result = app(DataFlow::TypeTracker::end()) } } + // --------------------------------------------------------------------------- + // routing modeling + // --------------------------------------------------------------------------- + /** + * Gets a reference to the attribute `attr_name` of a flask application. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node app_attr(DataFlow::TypeTracker t, string attr_name) { + attr_name in ["route", "add_url_rule"] and + t.startInAttr(attr_name) and + result = flask::app() + or + // Due to bad performance when using normal setup with `app_attr(t2, attr_name).track(t2, t)` + // we have inlined that code and forced a join + exists(DataFlow::TypeTracker t2 | + exists(DataFlow::StepSummary summary | + app_attr_first_join(t2, attr_name, result, summary) and + t = t2.append(summary) + ) + ) + } + + pragma[nomagic] + private predicate app_attr_first_join( + DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, DataFlow::StepSummary summary + ) { + DataFlow::StepSummary::step(app_attr(t2, attr_name), res, summary) + } + + /** + * Gets a reference to the attribute `attr_name` of a flask application. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node app_attr(string attr_name) { + result = app_attr(DataFlow::TypeTracker::end(), attr_name) + } + + private string werkzeug_rule_re() { + // since flask uses werkzeug internally, we are using its routing rules from + // https://github.com/pallets/werkzeug/blob/4dc8d6ab840d4b78cbd5789cef91b01e3bde01d5/src/werkzeug/routing.py#L138-L151 + result = + "(?[^<]*)<(?:(?[a-zA-Z_][a-zA-Z0-9_]*)(?:\\((?.*?)\\))?\\:)?(?[a-zA-Z_][a-zA-Z0-9_]*)>" + } + + /** A route setup made by flask (sharing handling of URL patterns). */ + abstract private class FlaskRouteSetup extends HTTP::Server::RouteSetup::Range { + override Parameter getARoutedParameter() { + exists(string name | + result = this.getARouteHandler().getArgByName(name) and + exists(string match | + match = this.getUrlPattern().regexpFind(werkzeug_rule_re(), _, _) and + name = match.regexpCapture(werkzeug_rule_re(), 4) + ) + ) + } + + /** Gets the argument used to pass in the URL pattern. */ + abstract DataFlow::Node getUrlPatternArg(); + + override string getUrlPattern() { + exists(StrConst str | + DataFlow::localFlow(DataFlow::exprNode(str), this.getUrlPatternArg()) and + result = str.getText() + ) + } + } + + /** + * A call to `flask.Flask.route`. + * + * See https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.route + */ + private class FlaskAppRouteCall extends FlaskRouteSetup { + CallNode call; + + FlaskAppRouteCall() { + call.getFunction() = app_attr("route").asCfgNode() and + this.asCfgNode() = call + } + + override DataFlow::Node getUrlPatternArg() { + exists(ControlFlowNode pattern_arg | + ( + pattern_arg = call.getArg(0) + or + pattern_arg = call.getArgByName("rule") + ) and + result.asCfgNode() = pattern_arg + ) + } + + override Function getARouteHandler() { result.getADecorator() = call.getNode() } + } + + /** + * A call to `flask.Flask.add_url_rule`. + * + * See https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.add_url_rule + */ + private class FlaskAppAddUrlRule extends FlaskRouteSetup { + CallNode call; + + FlaskAppAddUrlRule() { + call.getFunction() = app_attr("add_url_rule").asCfgNode() and + this.asCfgNode() = call + } + + override DataFlow::Node getUrlPatternArg() { + exists(ControlFlowNode pattern_arg | + ( + pattern_arg = call.getArg(0) + or + pattern_arg = call.getArgByName("rule") + ) and + result.asCfgNode() = pattern_arg + ) + } + + override Function getARouteHandler() { + exists(ControlFlowNode view_func_arg, DataFlow::Node func_src | + view_func_arg = call.getArg(2) + or + view_func_arg = call.getArgByName("view_func") + | + DataFlow::localFlow(func_src, any(DataFlow::Node dest | dest.asCfgNode() = view_func_arg)) and + func_src.asExpr().(CallableExpr) = result.getDefinition() + ) + } + } + + // --------------------------------------------------------------------------- + // flask.Request taint modeling + // --------------------------------------------------------------------------- // TODO: Do we even need this class? :| /** * A source of remote flow from a flask request. diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/ConceptsTest.expected b/python/ql/test/experimental/library-tests/frameworks/flask/ConceptsTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/ConceptsTest.ql b/python/ql/test/experimental/library-tests/frameworks/flask/ConceptsTest.ql new file mode 100644 index 00000000000..b557a0bccb6 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/flask/ConceptsTest.ql @@ -0,0 +1,2 @@ +import python +import experimental.meta.ConceptsTest diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/old_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/old_test.py index bedeaa56423..1d199d31004 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/old_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/old_test.py @@ -3,15 +3,15 @@ import flask from flask import Flask, request, make_response app = Flask(__name__) -@app.route("/") -def hello_world(): +@app.route("/") # $routeSetup="/" +def hello_world(): # $routeHandler return "Hello World!" from flask.views import MethodView class MyView(MethodView): - def get(self, user_id): + def get(self, user_id): # $f-:routeHandler if user_id is None: # return a list of users pass @@ -21,46 +21,46 @@ class MyView(MethodView): the_view = MyView.as_view('my_view') -app.add_url_rule('/the/', defaults={'user_id': None}, +app.add_url_rule('/the/', defaults={'user_id': None}, # $routeSetup="/the/" view_func=the_view, methods=['GET',]) -@app.route("/dangerous") -def dangerous(): +@app.route("/dangerous") # $routeSetup="/dangerous" +def dangerous(): # $routeHandler return request.args.get('payload') -@app.route("/dangerous-with-cfg-split") -def dangerous2(): +@app.route("/dangerous-with-cfg-split") # $routeSetup="/dangerous-with-cfg-split" +def dangerous2(): # $routeHandler x = request.form['param0'] if request.method == "POST": return request.form['param1'] return None -@app.route('/unsafe') -def unsafe(): +@app.route("/unsafe") # $routeSetup="/unsafe" +def unsafe(): # $routeHandler first_name = request.args.get('name', '') return make_response("Your name is " + first_name) -@app.route('/safe') -def safe(): +@app.route("/safe") # $routeSetup="/safe" +def safe(): # $routeHandler first_name = request.args.get('name', '') return make_response("Your name is " + escape(first_name)) -@app.route('/hello/') -def hello(name): +@app.route("/hello/") # $routeSetup="/hello/" +def hello(name): # $routeHandler $routedParameter=name return make_response("Your name is " + name) -@app.route('/foo/') -def foo(subpath): +@app.route("/foo/") # $routeSetup="/foo/" +def foo(subpath): # $routeHandler $routedParameter=subpath return make_response("The subpath is " + subpath) -@app.route('/multiple/') # TODO: not recognized as route -@app.route('/multiple/foo/') # TODO: not recognized as route -@app.route('/multiple/bar/') -def multiple(foo=None, bar=None): +@app.route("/multiple/") # $routeSetup="/multiple/" +@app.route("/multiple/foo/") # $routeSetup="/multiple/foo/" +@app.route("/multiple/bar/") # $routeSetup="/multiple/bar/" +def multiple(foo=None, bar=None): # $routeHandler $routedParameter=foo $routedParameter=bar return make_response("foo={!r} bar={!r}".format(foo, bar)) -@app.route('/complex/') -def complex(lang_code): +@app.route("/complex/") # $routeSetup="/complex/" +def complex(lang_code): # $routeHandler $routedParameter=lang_code return make_response("lang_code {}".format(lang_code)) if __name__ == "__main__": diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py new file mode 100644 index 00000000000..7cd45e4f8e9 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py @@ -0,0 +1,27 @@ +import flask + +from flask import Flask, make_response +app = Flask(__name__) + + +SOME_ROUTE = "/some/route" +@app.route(SOME_ROUTE) # $routeSetup="/some/route" +def some_route(): # $routeHandler + return make_response("some_route") + + +# TODO: We should be able to handle this one +def index(): # $routeHandler + return make_response("index") +app.add_url_rule('/index', 'index', index) # $routeSetup="/index" + + +# We don't support this yet, and I think that's OK +def later_set(): # $f-:routeHandler + return make_response("later_set") +app.add_url_rule('/later-set', 'later_set', view_func=None) # $routeSetup="/later-set" +app.view_functions['later_set'] = later_set + + +if __name__ == "__main__": + app.run(debug=True) diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/taint_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/taint_test.py index 9cf9e7a2027..267d0e50760 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/taint_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/taint_test.py @@ -1,8 +1,8 @@ from flask import Flask, request app = Flask(__name__) -@app.route('/test_taint//') -def test_taint(name = "World!", number="0", foo="foo"): +@app.route("/test_taint//") # $routeSetup="/test_taint//" +def test_taint(name = "World!", number="0", foo="foo"): # $routeHandler $routedParameter=name $routedParameter=number ensure_tainted(name, number) ensure_not_tainted(foo) @@ -191,8 +191,8 @@ def test_taint(name = "World!", number="0", foo="foo"): -@app.route('/debug//', methods=['GET']) -def debug(foo, bar): +@app.route("/debug//", methods=['GET']) # $routeSetup="/debug//" +def debug(foo, bar): # $routeHandler $routedParameter=foo $routedParameter=bar print("request.view_args", request.view_args) print("request.headers {!r}".format(request.headers)) @@ -202,8 +202,8 @@ def debug(foo, bar): return 'ok' -@app.route('/stream', methods=['POST']) -def stream(): +@app.route("/stream", methods=['POST']) # $routeSetup="/stream" +def stream(): # $routeHandler print(request.path) s = request.stream print(s) @@ -212,8 +212,8 @@ def stream(): return 'ok' -@app.route('/input_stream', methods=['POST']) -def input_stream(): +@app.route("/input_stream", methods=['POST']) # $routeSetup="/input_stream" +def input_stream(): # $routeHandler print(request.path) s = request.input_stream print(s) @@ -223,15 +223,15 @@ def input_stream(): return 'ok' -@app.route('/form', methods=['POST']) -def form(): +@app.route("/form", methods=['POST']) # $routeSetup="/form" +def form(): # $routeHandler print(request.path) print("request.form", request.form) return 'ok' -@app.route('/cache_control', methods=['POST']) -def cache_control(): +@app.route("/cache_control", methods=['POST']) # $routeSetup="/cache_control" +def cache_control(): # $routeHandler print(request.path) print("request.cache_control.max_age", request.cache_control.max_age, type(request.cache_control.max_age)) print("request.cache_control.max_stale", request.cache_control.max_stale, type(request.cache_control.max_stale)) @@ -239,16 +239,16 @@ def cache_control(): return 'ok' -@app.route('/file_upload', methods=['POST']) -def file_upload(): +@app.route("/file_upload", methods=['POST']) # $routeSetup="/file_upload" +def file_upload(): # $routeHandler print(request.path) for k,v in request.files.items(): print(k, v, v.name, v.filename, v.stream) return 'ok' -@app.route('/args', methods=['GET']) -def args(): +@app.route("/args", methods=['GET']) # $routeSetup="/args" +def args(): # $routeHandler print(request.path) print("request.args", request.args) From f03a8a838b676b9b0767bb06ef5cb5b83b4aafba Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 6 Oct 2020 02:49:49 +0200 Subject: [PATCH 224/411] Python: Make any routed parameter a RemoteFlowSource I'm not 100% sure whether this approach makes everything too magic, but I like the fact that you can't _forget_ to make routed params remove-flow sources. --- python/ql/src/experimental/dataflow/RemoteFlowSources.qll | 1 + python/ql/src/experimental/semmle/python/Concepts.qll | 7 +++++++ .../library-tests/frameworks/flask/TestTaint.expected | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/python/ql/src/experimental/dataflow/RemoteFlowSources.qll b/python/ql/src/experimental/dataflow/RemoteFlowSources.qll index dcda1550d0c..9c6a0dc1ccb 100644 --- a/python/ql/src/experimental/dataflow/RemoteFlowSources.qll +++ b/python/ql/src/experimental/dataflow/RemoteFlowSources.qll @@ -2,6 +2,7 @@ private import python private import experimental.dataflow.DataFlow // Need to import since frameworks can extend `RemoteFlowSource::Range` private import experimental.semmle.python.Frameworks +private import experimental.semmle.python.Concepts /** * A data flow source of remote user input. diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index cea4bfa2fdd..454d5d4505d 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -7,6 +7,7 @@ import python private import experimental.dataflow.DataFlow private import experimental.semmle.python.Frameworks +private import experimental.dataflow.RemoteFlowSources /** * A data-flow node that executes an operating system command, @@ -89,5 +90,11 @@ module HTTP { abstract Parameter getARoutedParameter(); } } + + private class RoutedParameter extends RemoteFlowSource::Range, DataFlow::ParameterNode { + RoutedParameter() { this.getParameter() = any(RouteSetup setup).getARoutedParameter() } + + override string getSourceType() { result = "RoutedParameter" } + } } } diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/TestTaint.expected b/python/ql/test/experimental/library-tests/frameworks/flask/TestTaint.expected index d9ec3129b78..8c3b4ea57c9 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/TestTaint.expected +++ b/python/ql/test/experimental/library-tests/frameworks/flask/TestTaint.expected @@ -1,5 +1,5 @@ -| taint_test.py:6 | fail | test_taint | name | -| taint_test.py:6 | fail | test_taint | number | +| taint_test.py:6 | ok | test_taint | name | +| taint_test.py:6 | ok | test_taint | number | | taint_test.py:7 | ok | test_taint | foo | | taint_test.py:14 | ok | test_taint | request.environ | | taint_test.py:15 | ok | test_taint | request.environ.get(..) | From fbe115c046afe1b67618b139318fc2e0667a76a3 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 6 Oct 2020 03:08:55 +0200 Subject: [PATCH 225/411] Python: Show TypeTracking doesn't work for module members --- .../test/experimental/dataflow/typetracking/mymodule.py | 4 ++++ python/ql/test/experimental/dataflow/typetracking/test.py | 8 ++++++++ 2 files changed, 12 insertions(+) create mode 100644 python/ql/test/experimental/dataflow/typetracking/mymodule.py diff --git a/python/ql/test/experimental/dataflow/typetracking/mymodule.py b/python/ql/test/experimental/dataflow/typetracking/mymodule.py new file mode 100644 index 00000000000..ed4ca954c43 --- /dev/null +++ b/python/ql/test/experimental/dataflow/typetracking/mymodule.py @@ -0,0 +1,4 @@ +x = tracked # $tracked + +def func(): + return tracked # $tracked diff --git a/python/ql/test/experimental/dataflow/typetracking/test.py b/python/ql/test/experimental/dataflow/typetracking/test.py index 141120d7015..60ef0b64470 100644 --- a/python/ql/test/experimental/dataflow/typetracking/test.py +++ b/python/ql/test/experimental/dataflow/typetracking/test.py @@ -49,6 +49,14 @@ def global_var_write_test(): write_g(x) # $tracked use_g() +def test_import(): + import mymodule + mymodule.x # $f-:tracked + y = mymodule.func() # $tracked + y # $tracked + +# ------------------------------------------------------------------------------ + def expects_int(x): # $int do_int_stuff(x) # $int From faf663a334ada867a6e3abe9b4ba14dff7cc4a42 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 1 Oct 2020 08:11:06 +0200 Subject: [PATCH 226/411] C#: Flow summary for Nullable --- .../csharp/dataflow/LibraryTypeDataFlow.qll | 45 ++++++++++++++++++- .../semmle/code/csharp/frameworks/System.qll | 34 ++++++++++++++ .../library/LibraryTypeDataFlow.expected | 6 +++ 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll index b7d94baa435..79854e3daad 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll @@ -339,7 +339,7 @@ abstract class LibraryTypeDataFlow extends Type { * Holds if data may flow from `source` to `sink` when calling callable `c`. * * `sourceAp` describes the contents of `source` that flows to `sink` - * (if any), and `sinkContent` describes the contents of `sink` that it + * (if any), and `sinkAp` describes the contents of `sink` that it * flows to (if any). */ pragma[nomagic] @@ -728,6 +728,49 @@ class SystemLazyFlow extends LibraryTypeDataFlow, SystemLazyClass { } } +/** Data flow for `System.Nullable<>`. */ +class SystemNullableFlow extends LibraryTypeDataFlow, SystemNullableStruct { + override predicate callableFlow( + CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp, + SourceDeclarationCallable c, boolean preservesValue + ) { + preservesValue = true and + c.(Constructor).getDeclaringType() = this and + source = getFlowSourceArg(c, 0, sourceAp) and + sourceAp = AccessPath::empty() and + sink = TCallableFlowSinkReturn() and + sinkAp = AccessPath::property(this.getValueProperty()) + or + preservesValue = true and + c = this.getAGetValueOrDefaultMethod() and + source = TCallableFlowSourceQualifier() and + sourceAp = AccessPath::property(this.getValueProperty()) and + sink = TCallableFlowSinkReturn() and + sinkAp = AccessPath::empty() + or + preservesValue = false and + c = this.getHasValueProperty().getGetter() and + source = TCallableFlowSourceQualifier() and + sourceAp = AccessPath::property(this.getValueProperty()) and + sink = TCallableFlowSinkReturn() and + sinkAp = AccessPath::empty() + or + preservesValue = true and + c = this.getAGetValueOrDefaultMethod() and + source = getFlowSourceArg(c, 0, _) and + sourceAp = AccessPath::empty() and + sink = TCallableFlowSinkReturn() and + sinkAp = AccessPath::empty() + or + preservesValue = false and + c = this.getValueProperty().getGetter() and + source = TCallableFlowSourceQualifier() and + sourceAp = AccessPath::empty() and + sink = TCallableFlowSinkReturn() and + sinkAp = AccessPath::empty() + } +} + /** Data flow for `System.Collections.IEnumerable` (and sub types). */ class IEnumerableFlow extends LibraryTypeDataFlow, RefType { IEnumerableFlow() { this.getABaseType*() instanceof SystemCollectionsIEnumerableInterface } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/System.qll b/csharp/ql/src/semmle/code/csharp/frameworks/System.qll index 70f4c85138d..9812fe08c6b 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/System.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/System.qll @@ -21,6 +21,11 @@ class SystemUnboundGenericClass extends UnboundGenericClass { SystemUnboundGenericClass() { this.getNamespace() instanceof SystemNamespace } } +/** An unbound generic struct in the `System` namespace. */ +class SystemUnboundGenericStruct extends UnboundGenericStruct { + SystemUnboundGenericStruct() { this.getNamespace() instanceof SystemNamespace } +} + /** An interface in the `System` namespace. */ class SystemInterface extends Interface { SystemInterface() { this.getNamespace() instanceof SystemNamespace } @@ -215,6 +220,35 @@ class SystemLazyClass extends SystemUnboundGenericClass { } } +/** The `System.Nullable` struct. */ +class SystemNullableStruct extends SystemUnboundGenericStruct { + SystemNullableStruct() { + this.hasName("Nullable<>") and + this.getNumberOfTypeParameters() = 1 + } + + /** Gets the `Value` property. */ + Property getValueProperty() { + result.getDeclaringType() = this and + result.hasName("Value") and + result.getType() = getTypeParameter(0) + } + + /** Gets the `HasValue` property. */ + Property getHasValueProperty() { + result.getDeclaringType() = this and + result.hasName("HasValue") and + result.getType() instanceof BoolType + } + + /** Gets a `GetValueOrDefault()` method. */ + Method getAGetValueOrDefaultMethod() { + result.getDeclaringType() = this and + result.hasName("GetValueOrDefault") and + result.getReturnType() = getTypeParameter(0) + } +} + /** The `System.NullReferenceException` class. */ class SystemNullReferenceExceptionClass extends SystemClass { SystemNullReferenceExceptionClass() { this.hasName("NullReferenceException") } diff --git a/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected b/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected index a144979b77c..377c9d05acc 100644 --- a/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected @@ -494,6 +494,8 @@ callableFlow | System.Net.WebUtility.HtmlEncode(string) | argument 0 -> return | false | | System.Net.WebUtility.HtmlEncode(string, TextWriter) | argument 0 -> return | false | | System.Net.WebUtility.UrlEncode(string) | argument 0 -> return | false | +| System.Nullable<>.GetValueOrDefault(T) | argument 0 -> return | true | +| System.Nullable<>.get_Value() | qualifier -> return | false | | System.Security.Cryptography.CryptoStream.BeginRead(Byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | | System.Security.Cryptography.CryptoStream.BeginWrite(Byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | | System.Security.Cryptography.CryptoStream.Read(Byte[], int, int) | qualifier -> argument 0 | false | @@ -1848,6 +1850,10 @@ callableFlowAccessPath | System.Net.NetworkInformation.IPAddressCollection.Add(IPAddress) | argument 0 [] -> qualifier [[]] | true | | System.Net.NetworkInformation.IPAddressCollection.CopyTo(IPAddress[], int) | qualifier [[]] -> argument 0 [[]] | true | | System.Net.NetworkInformation.IPAddressCollection.GetEnumerator() | qualifier [[]] -> return [Current] | true | +| System.Nullable<>.GetValueOrDefault() | qualifier [Value] -> return [] | true | +| System.Nullable<>.GetValueOrDefault(T) | qualifier [Value] -> return [] | true | +| System.Nullable<>.Nullable(T) | argument 0 [] -> return [Value] | true | +| System.Nullable<>.get_HasValue() | qualifier [Value] -> return [] | false | | System.Resources.ResourceReader.GetEnumerator() | qualifier [[]] -> return [Current] | true | | System.Resources.ResourceSet.GetEnumerator() | qualifier [[]] -> return [Current] | true | | System.Runtime.CompilerServices.ConditionalWeakTable<,>.GetEnumerator() | qualifier [[]] -> return [Current] | true | From 576085af5016c56a7d71de752c0260a6372ac8b9 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 1 Oct 2020 11:57:02 +0200 Subject: [PATCH 227/411] Add extra information to nullable conversion test file --- .../conversion/nullable/Nullable.cs | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/csharp/ql/test/library-tests/conversion/nullable/Nullable.cs b/csharp/ql/test/library-tests/conversion/nullable/Nullable.cs index 08d714f123f..af9c518b238 100644 --- a/csharp/ql/test/library-tests/conversion/nullable/Nullable.cs +++ b/csharp/ql/test/library-tests/conversion/nullable/Nullable.cs @@ -1,20 +1,29 @@ using System; +using System.Runtime.Serialization; class C { - sbyte x1; - sbyte? x2; + int x1; + int? x2; Nullable x3; Nullable x4; // Verify conversions void M() { - x2 = x1; - x3 = x4; + x2 = x1; // T -> T? conversion: implicit, nullable -> implicit cast + x3 = x4; // T1? -> T2? conversion: implicit, nullable -> implicit cast + + x12 = x1; // T1 -> T2? conversion: implicit, nullable -> implicit cast + x12 = null; // null -> T? conversion: implicit, null literal -> no cast + + x3 = x2; // T? -> T? no conversion + + x14 = x15; // T1? -> T2? conversion: implicit, user defined -> implicit cast } // Cause the following types to exist in the database: + sbyte? x0; byte? x5; short? x6; ushort? x7; @@ -24,4 +33,19 @@ class C double? x11; long? x12; float? x13; + + A? x14; + B? x15; + + struct A + { + } + + struct B + { + public static implicit operator A(B value) + { + return new A(); + } + } } From dd5fb6ce129201a302ebd682694aa260ba4413e4 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 6 Oct 2020 08:46:43 +0100 Subject: [PATCH 228/411] Exclude JS tests from code scanning --- .github/codeql/codeql-config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index 638f30dd4ce..cbd1f33a7f6 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -7,3 +7,5 @@ paths-ignore: - '/cpp/' - '/java/' - '/python/' + - '/javascript/ql/test' + - '/javascript/extractor/tests' From 9206549a389f7ea009f4ae269405a26320464b33 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Mon, 5 Oct 2020 16:22:40 +0100 Subject: [PATCH 229/411] JavaScript: Make integration of TypeScript canonical names with modules in API graphs more consistent. Previously, canonical names were direct successors of module definitions/uses, now they are successors of exports/imports. --- .../ql/src/semmle/javascript/ApiGraphs.qll | 51 ++++++++++++------- .../src/semmle/javascript/CanonicalNames.qll | 10 +++- javascript/ql/test/ApiGraphs/typed/index.ts | 6 +-- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index da78e3a543d..2f19e65fb5b 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -346,16 +346,30 @@ module API { exists(SSA::implicitInit([nm.getModuleVariable(), nm.getExportsVariable()])) ) ) + or + m = any(CanonicalName n | isDefined(n)).getExternalModuleName() + } or + MkModuleImport(string m) { + imports(_, m) + or + m = any(CanonicalName n | isUsed(n)).getExternalModuleName() } or - MkModuleImport(string m) { imports(_, m) } or MkClassInstance(DataFlow::ClassNode cls) { cls = trackDefNode(_) and hasSemantics(cls) } or MkAsyncFuncResult(DataFlow::FunctionNode f) { f = trackDefNode(_) and f.getFunction().isAsync() and hasSemantics(f) } or MkDef(DataFlow::Node nd) { rhs(_, _, nd) } or MkUse(DataFlow::Node nd) { use(_, _, nd) } or - MkCanonicalNameDef(CanonicalName n) { isDefined(n) } or - MkCanonicalNameUse(CanonicalName n) { isUsed(n) } + MkCanonicalNameDef(CanonicalName n) { + // module roots are represented by `MkModuleExport` nodes + not n.isRoot() and + isDefined(n) + } or + MkCanonicalNameUse(CanonicalName n) { + // module roots are represented by `MkModuleImport` nodes + not n.isRoot() and + isUsed(n) + } class TDef = MkModuleDef or TNonModuleDef; @@ -399,6 +413,18 @@ module API { ) } + private TApiNode mkCanonicalNameDef(CanonicalName cn) { + if cn.isModuleRoot() + then result = MkModuleExport(cn.getExternalModuleName()) + else result = MkCanonicalNameDef(cn) + } + + private TApiNode mkCanonicalNameUse(CanonicalName cn) { + if cn.isModuleRoot() + then result = MkModuleImport(cn.getExternalModuleName()) + else result = MkCanonicalNameUse(cn) + } + /** * Holds if `rhs` is the right-hand side of a definition of a node that should have an * incoming edge from `base` labeled `lbl` in the API graph. @@ -698,20 +724,11 @@ module API { succ = MkClassInstance(trackDefNode(def)) ) or - exists(CanonicalName cn | - pred = MkRoot() and - lbl = Label::mod(cn.getExternalModuleName()) - | - succ = MkCanonicalNameUse(cn) or - succ = MkCanonicalNameDef(cn) - ) - or - exists(CanonicalName cn1, CanonicalName cn2 | - cn2 = cn1.getAChild() and - lbl = Label::member(cn2.getName()) - | - (pred = MkCanonicalNameDef(cn1) or pred = MkCanonicalNameUse(cn1)) and - (succ = MkCanonicalNameDef(cn2) or succ = MkCanonicalNameUse(cn2)) + exists(CanonicalName cn1, string n, CanonicalName cn2 | + pred in [mkCanonicalNameDef(cn1), mkCanonicalNameUse(cn1)] and + cn2 = cn1.getChild(n) and + lbl = Label::member(n) and + succ in [mkCanonicalNameDef(cn2), mkCanonicalNameUse(cn2)] ) or exists(DataFlow::Node nd, DataFlow::FunctionNode f | diff --git a/javascript/ql/src/semmle/javascript/CanonicalNames.qll b/javascript/ql/src/semmle/javascript/CanonicalNames.qll index 54c39202038..7435be7131a 100644 --- a/javascript/ql/src/semmle/javascript/CanonicalNames.qll +++ b/javascript/ql/src/semmle/javascript/CanonicalNames.qll @@ -25,10 +25,18 @@ class CanonicalName extends @symbol { CanonicalName getParent() { symbol_parent(this, result) } /** - * Gets a child of this canonical name, i.e. an extension of its qualified name. + * Gets a child of this canonical name, that is, an extension of its qualified name. */ CanonicalName getAChild() { result.getParent() = this } + /** + * Gets the child of this canonical name that has the given `name`, if any. + */ + CanonicalName getChild(string name) { + result = getAChild() and + result.getName() = name + } + /** * Gets the name without prefix. */ diff --git a/javascript/ql/test/ApiGraphs/typed/index.ts b/javascript/ql/test/ApiGraphs/typed/index.ts index b89dac43aff..8f1338d95c2 100644 --- a/javascript/ql/test/ApiGraphs/typed/index.ts +++ b/javascript/ql/test/ApiGraphs/typed/index.ts @@ -11,7 +11,7 @@ app.use(bodyParser.json()); app.post("/find", (req, res) => { let v = JSON.parse(req.body.x); - getCollection().find({ id: v }); /* use (member find (instance (member Collection (module mongodb)))) */ + getCollection().find({ id: v }); /* use (member find (instance (member Collection (member exports (module mongodb))))) */ }); import * as mongoose from "mongoose"; @@ -19,6 +19,6 @@ declare function getMongooseModel(): mongoose.Model; declare function getMongooseQuery(): mongoose.Query; app.post("/find", (req, res) => { let v = JSON.parse(req.body.x); - getMongooseModel().find({ id: v }); /* def (parameter 0 (member find (instance (member Model (module mongoose))))) */ - getMongooseQuery().find({ id: v }); /* def (parameter 0 (member find (instance (member Query (module mongoose))))) */ + getMongooseModel().find({ id: v }); /* def (parameter 0 (member find (instance (member Model (member exports (module mongoose)))))) */ + getMongooseQuery().find({ id: v }); /* def (parameter 0 (member find (instance (member Query (member exports (module mongoose)))))) */ }); From 8277d5c08f9d8f6b462ba86a90952efda1365675 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Mon, 5 Oct 2020 16:41:44 +0100 Subject: [PATCH 230/411] JavaScript: Introduce convenience predicate for working with typed API-graph nodes. --- javascript/ql/src/semmle/javascript/ApiGraphs.qll | 11 +++++++++++ .../ql/test/ApiGraphs/typed/NodeOfType.expected | 3 +++ javascript/ql/test/ApiGraphs/typed/NodeOfType.ql | 4 ++++ 3 files changed, 18 insertions(+) create mode 100644 javascript/ql/test/ApiGraphs/typed/NodeOfType.expected create mode 100644 javascript/ql/test/ApiGraphs/typed/NodeOfType.ql diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 2f19e65fb5b..8b082b74719 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -286,6 +286,17 @@ module API { /** Gets a node corresponding to an export of module `m`. */ Node moduleExport(string m) { result = Impl::MkModuleDef(m).(Node).getMember("exports") } + /** Provides helper predicates for accessing API-graph nodes. */ + module Node { + /** Gets a node whose type has the given qualified name. */ + Node ofType(string moduleName, string exportedName) { + exists(TypeName tn | + tn.hasQualifiedName(moduleName, exportedName) and + result = Impl::MkCanonicalNameUse(tn).(Node).getInstance() + ) + } + } + /** * An API entry point. * diff --git a/javascript/ql/test/ApiGraphs/typed/NodeOfType.expected b/javascript/ql/test/ApiGraphs/typed/NodeOfType.expected new file mode 100644 index 00000000000..4513f16cfc3 --- /dev/null +++ b/javascript/ql/test/ApiGraphs/typed/NodeOfType.expected @@ -0,0 +1,3 @@ +| mongodb | Collection | index.ts:14:3:14:17 | getCollection() | +| mongoose | Model | index.ts:22:3:22:20 | getMongooseModel() | +| mongoose | Query | index.ts:23:3:23:20 | getMongooseQuery() | diff --git a/javascript/ql/test/ApiGraphs/typed/NodeOfType.ql b/javascript/ql/test/ApiGraphs/typed/NodeOfType.ql new file mode 100644 index 00000000000..582385c802a --- /dev/null +++ b/javascript/ql/test/ApiGraphs/typed/NodeOfType.ql @@ -0,0 +1,4 @@ +import javascript + +from string mod, string tp +select mod, tp, API::Node::ofType(mod, tp).getAnImmediateUse() From 0109805ab0643b743334d8ee72042277dd37ac78 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 6 Oct 2020 09:45:03 +0100 Subject: [PATCH 231/411] JavaScript: Use new API in NoSQL models. --- .../ql/src/semmle/javascript/ApiGraphs.qll | 3 - .../semmle/javascript/frameworks/NoSQL.qll | 60 +++---------------- 2 files changed, 8 insertions(+), 55 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 8b082b74719..6f5333e892d 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -312,9 +312,6 @@ module API { /** Gets a data-flow node that defines this entry point. */ abstract DataFlow::Node getARhs(); - - /** Gets an API-graph node for this entry point. */ - API::Node getNode() { result = root().getASuccessor(this) } } /** diff --git a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll index 91a62e5b1f4..269c6603f6c 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll @@ -48,20 +48,6 @@ private module MongoDB { not result.getAnImmediateUse().(DataFlow::ParameterNode).getName() = "client" // mongodb v3 provides a `Mongoclient` here } - /** - * A collection based on the type `mongodb.Collection`. - * - * Note that this also covers `mongoose` models since they are subtypes - * of `mongodb.Collection`. - */ - private class TypedMongoCollection extends API::EntryPoint { - TypedMongoCollection() { this = "TypedMongoCollection" } - - override DataFlow::SourceNode getAUse() { result.hasUnderlyingType("mongodb", "Collection") } - - override DataFlow::Node getARhs() { none() } - } - /** Gets a data flow node referring to a MongoDB collection. */ private API::Node getACollection() { // A collection resulting from calling `Db.collection(...)`. @@ -71,7 +57,8 @@ private module MongoDB { result = collection.getParameter(1).getParameter(0) ) or - result = any(TypedMongoCollection c).getNode() + // note that this also covers `mongoose` models since they are subtypes of `mongodb.Collection` + result = API::Node::ofType("mongodb", "Collection") } /** A call to a MongoDB query method. */ @@ -225,17 +212,6 @@ private module Mongoose { } } - /** - * A Mongoose collection based on the type `mongoose.Model`. - */ - private class TypedMongooseModel extends API::EntryPoint { - TypedMongooseModel() { this = "TypedMongooseModel" } - - override DataFlow::SourceNode getAUse() { result.hasUnderlyingType("mongoose", "Model") } - - override DataFlow::Node getARhs() { none() } - } - /** * Gets a API-graph node referring to a Mongoose Model object. */ @@ -247,7 +223,7 @@ private module Mongoose { result = conn.getMember("models").getAMember() ) or - result = any(TypedMongooseModel c).getNode() + result = API::Node::ofType("mongoose", "Model") } /** @@ -341,24 +317,13 @@ private module Mongoose { override API::Node getQueryArgument() { result = this.getParameter(2) } } - /** - * A Mongoose query. - */ - private class TypedMongooseQuery extends API::EntryPoint { - TypedMongooseQuery() { this = "TypedMongooseQuery" } - - override DataFlow::SourceNode getAUse() { result.hasUnderlyingType("mongoose", "Query") } - - override DataFlow::Node getARhs() { none() } - } - /** * Gets a data flow node referring to a Mongoose query object. */ API::Node getAMongooseQuery() { result = any(MongooseFunction f).getQueryReturn() or - result = any(TypedMongooseQuery c).getNode() + result = API::Node::ofType("mongoose", "Query") or result = getAMongooseQuery() @@ -560,23 +525,14 @@ private module Mongoose { } } - /** - * A Mongoose document. - */ - private class TypedMongooseDocument extends API::EntryPoint { - TypedMongooseDocument() { this = "TypedMongooseDocument" } - - override DataFlow::SourceNode getAUse() { result.hasUnderlyingType("mongoose", "Document") } - - override DataFlow::Node getARhs() { none() } - } - /** * Gets a data flow node referring to a Mongoose Document object. */ private API::Node getAMongooseDocument() { - result instanceof RetrievedDocument or - result = any(TypedMongooseDocument c).getNode() or + result instanceof RetrievedDocument + or + result = API::Node::ofType("mongoose", "Document") + or result = getAMongooseDocument() .getMember(any(string name | MethodSignatures::returnsDocument(name))) From 8f13d586b7662f39f60e9613aebeec511ebb861e Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 6 Oct 2020 10:49:15 +0200 Subject: [PATCH 232/411] Python: More tests of conditonals Also use better formatter (better because comments are close to what they comment) --- .../dataflow/coverage/dataflow.expected | 554 +++++++++--------- .../dataflow/coverage/localFlow.expected | 56 +- .../experimental/dataflow/coverage/test.py | 116 ++-- 3 files changed, 362 insertions(+), 364 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 379b44a3090..b1cb5f0f077 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -29,128 +29,128 @@ edges | datamodel.py:155:14:155:25 | ControlFlowNode for Customized() [Attribute b] | datamodel.py:159:6:159:15 | ControlFlowNode for customized [Attribute b] | | datamodel.py:159:6:159:15 | ControlFlowNode for customized [Attribute b] | datamodel.py:159:6:159:17 | ControlFlowNode for Attribute | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:36:21:36:26 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:50:9:50:14 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:84:10:84:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:91:10:91:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:101:10:101:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:106:22:106:27 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:111:10:111:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:49:9:49:14 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:81:9:81:14 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:87:10:87:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:97:10:97:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:102:22:102:27 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:107:10:107:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:119:10:119:15 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:124:10:124:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:129:10:129:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:134:22:134:27 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:139:10:139:15 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:152:15:152:20 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:157:15:157:20 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:184:23:184:28 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:189:25:189:30 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:200:34:200:39 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:344:11:344:16 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:348:11:348:16 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:352:16:352:21 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:375:28:375:33 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:457:12:457:17 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:462:28:462:33 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:504:9:504:14 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:129:22:129:27 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:134:10:134:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:146:15:146:20 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:151:15:151:20 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:177:23:177:28 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:182:25:182:30 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:193:34:193:39 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:330:11:330:16 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:334:11:334:16 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:338:16:338:21 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:361:28:361:33 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:446:12:446:17 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:453:28:453:33 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:502:9:502:14 | ControlFlowNode for SOURCE | | test.py:14:1:14:6 | GSSA Variable SOURCE | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:14:1:14:6 | GSSA Variable SOURCE | | test.py:36:10:36:26 | ControlFlowNode for Tuple [Tuple element at index 1] | test.py:37:9:37:9 | ControlFlowNode for x [Tuple element at index 1] | | test.py:36:21:36:26 | ControlFlowNode for SOURCE | test.py:36:10:36:26 | ControlFlowNode for Tuple [Tuple element at index 1] | | test.py:37:9:37:9 | ControlFlowNode for x [Tuple element at index 1] | test.py:37:9:37:12 | ControlFlowNode for Subscript | | test.py:37:9:37:12 | ControlFlowNode for Subscript | test.py:38:10:38:10 | ControlFlowNode for y | -| test.py:50:9:50:14 | ControlFlowNode for SOURCE | test.py:51:10:51:10 | ControlFlowNode for x | -| test.py:57:9:57:16 | ControlFlowNode for Str | test.py:58:10:58:10 | ControlFlowNode for x | -| test.py:62:9:62:17 | ControlFlowNode for Str | test.py:63:10:63:10 | ControlFlowNode for x | -| test.py:67:9:67:10 | ControlFlowNode for IntegerLiteral | test.py:68:10:68:10 | ControlFlowNode for x | -| test.py:72:9:72:12 | ControlFlowNode for FloatLiteral | test.py:73:10:73:10 | ControlFlowNode for x | -| test.py:84:10:84:15 | ControlFlowNode for SOURCE | test.py:85:10:85:10 | ControlFlowNode for x | -| test.py:91:9:91:16 | ControlFlowNode for List [List element] | test.py:92:10:92:10 | ControlFlowNode for x [List element] | -| test.py:91:10:91:15 | ControlFlowNode for SOURCE | test.py:91:9:91:16 | ControlFlowNode for List [List element] | -| test.py:92:10:92:10 | ControlFlowNode for x [List element] | test.py:92:10:92:13 | ControlFlowNode for Subscript | -| test.py:101:9:101:37 | ControlFlowNode for ListComp [List element] | test.py:102:10:102:10 | ControlFlowNode for x [List element] | -| test.py:101:10:101:15 | ControlFlowNode for SOURCE | test.py:101:9:101:37 | ControlFlowNode for ListComp [List element] | -| test.py:102:10:102:10 | ControlFlowNode for x [List element] | test.py:102:10:102:13 | ControlFlowNode for Subscript | -| test.py:106:9:106:29 | ControlFlowNode for ListComp [List element] | test.py:107:10:107:10 | ControlFlowNode for x [List element] | -| test.py:106:10:106:10 | ControlFlowNode for y | test.py:106:9:106:29 | ControlFlowNode for ListComp [List element] | -| test.py:106:16:106:16 | SSA variable y | test.py:106:10:106:10 | ControlFlowNode for y | -| test.py:106:21:106:28 | ControlFlowNode for List [List element] | test.py:106:16:106:16 | SSA variable y | -| test.py:106:22:106:27 | ControlFlowNode for SOURCE | test.py:106:21:106:28 | ControlFlowNode for List [List element] | -| test.py:107:10:107:10 | ControlFlowNode for x [List element] | test.py:107:10:107:13 | ControlFlowNode for Subscript | -| test.py:111:9:111:16 | ControlFlowNode for List [List element] | test.py:112:21:112:21 | ControlFlowNode for l [List element] | -| test.py:111:10:111:15 | ControlFlowNode for SOURCE | test.py:111:9:111:16 | ControlFlowNode for List [List element] | -| test.py:112:9:112:22 | ControlFlowNode for ListComp [List element] | test.py:113:10:113:10 | ControlFlowNode for x [List element] | -| test.py:112:10:112:10 | ControlFlowNode for y | test.py:112:9:112:22 | ControlFlowNode for ListComp [List element] | -| test.py:112:16:112:16 | SSA variable y | test.py:112:10:112:10 | ControlFlowNode for y | -| test.py:112:21:112:21 | ControlFlowNode for l [List element] | test.py:112:16:112:16 | SSA variable y | -| test.py:113:10:113:10 | ControlFlowNode for x [List element] | test.py:113:10:113:13 | ControlFlowNode for Subscript | -| test.py:124:9:124:16 | ControlFlowNode for Set [List element] | test.py:125:10:125:10 | ControlFlowNode for x [List element] | -| test.py:124:10:124:15 | ControlFlowNode for SOURCE | test.py:124:9:124:16 | ControlFlowNode for Set [List element] | -| test.py:125:10:125:10 | ControlFlowNode for x [List element] | test.py:125:10:125:16 | ControlFlowNode for Attribute() | -| test.py:129:9:129:37 | ControlFlowNode for SetComp [Set element] | test.py:130:10:130:10 | ControlFlowNode for x [Set element] | -| test.py:129:10:129:15 | ControlFlowNode for SOURCE | test.py:129:9:129:37 | ControlFlowNode for SetComp [Set element] | +| test.py:49:9:49:14 | ControlFlowNode for SOURCE | test.py:50:10:50:10 | ControlFlowNode for x | +| test.py:55:9:55:16 | ControlFlowNode for Str | test.py:56:10:56:10 | ControlFlowNode for x | +| test.py:60:9:60:17 | ControlFlowNode for Str | test.py:61:10:61:10 | ControlFlowNode for x | +| test.py:65:9:65:10 | ControlFlowNode for IntegerLiteral | test.py:66:10:66:10 | ControlFlowNode for x | +| test.py:70:9:70:12 | ControlFlowNode for FloatLiteral | test.py:71:10:71:10 | ControlFlowNode for x | +| test.py:81:9:81:14 | ControlFlowNode for SOURCE | test.py:82:10:82:10 | ControlFlowNode for x | +| test.py:87:9:87:16 | ControlFlowNode for List [List element] | test.py:88:10:88:10 | ControlFlowNode for x [List element] | +| test.py:87:10:87:15 | ControlFlowNode for SOURCE | test.py:87:9:87:16 | ControlFlowNode for List [List element] | +| test.py:88:10:88:10 | ControlFlowNode for x [List element] | test.py:88:10:88:13 | ControlFlowNode for Subscript | +| test.py:97:9:97:37 | ControlFlowNode for ListComp [List element] | test.py:98:10:98:10 | ControlFlowNode for x [List element] | +| test.py:97:10:97:15 | ControlFlowNode for SOURCE | test.py:97:9:97:37 | ControlFlowNode for ListComp [List element] | +| test.py:98:10:98:10 | ControlFlowNode for x [List element] | test.py:98:10:98:13 | ControlFlowNode for Subscript | +| test.py:102:9:102:29 | ControlFlowNode for ListComp [List element] | test.py:103:10:103:10 | ControlFlowNode for x [List element] | +| test.py:102:10:102:10 | ControlFlowNode for y | test.py:102:9:102:29 | ControlFlowNode for ListComp [List element] | +| test.py:102:16:102:16 | SSA variable y | test.py:102:10:102:10 | ControlFlowNode for y | +| test.py:102:21:102:28 | ControlFlowNode for List [List element] | test.py:102:16:102:16 | SSA variable y | +| test.py:102:22:102:27 | ControlFlowNode for SOURCE | test.py:102:21:102:28 | ControlFlowNode for List [List element] | +| test.py:103:10:103:10 | ControlFlowNode for x [List element] | test.py:103:10:103:13 | ControlFlowNode for Subscript | +| test.py:107:9:107:16 | ControlFlowNode for List [List element] | test.py:108:21:108:21 | ControlFlowNode for l [List element] | +| test.py:107:10:107:15 | ControlFlowNode for SOURCE | test.py:107:9:107:16 | ControlFlowNode for List [List element] | +| test.py:108:9:108:22 | ControlFlowNode for ListComp [List element] | test.py:109:10:109:10 | ControlFlowNode for x [List element] | +| test.py:108:10:108:10 | ControlFlowNode for y | test.py:108:9:108:22 | ControlFlowNode for ListComp [List element] | +| test.py:108:16:108:16 | SSA variable y | test.py:108:10:108:10 | ControlFlowNode for y | +| test.py:108:21:108:21 | ControlFlowNode for l [List element] | test.py:108:16:108:16 | SSA variable y | +| test.py:109:10:109:10 | ControlFlowNode for x [List element] | test.py:109:10:109:13 | ControlFlowNode for Subscript | +| test.py:119:9:119:16 | ControlFlowNode for Set [List element] | test.py:120:10:120:10 | ControlFlowNode for x [List element] | +| test.py:119:10:119:15 | ControlFlowNode for SOURCE | test.py:119:9:119:16 | ControlFlowNode for Set [List element] | +| test.py:120:10:120:10 | ControlFlowNode for x [List element] | test.py:120:10:120:16 | ControlFlowNode for Attribute() | +| test.py:124:9:124:37 | ControlFlowNode for SetComp [Set element] | test.py:125:10:125:10 | ControlFlowNode for x [Set element] | +| test.py:124:10:124:15 | ControlFlowNode for SOURCE | test.py:124:9:124:37 | ControlFlowNode for SetComp [Set element] | +| test.py:125:10:125:10 | ControlFlowNode for x [Set element] | test.py:125:10:125:16 | ControlFlowNode for Attribute() | +| test.py:129:9:129:29 | ControlFlowNode for SetComp [Set element] | test.py:130:10:130:10 | ControlFlowNode for x [Set element] | +| test.py:129:10:129:10 | ControlFlowNode for y | test.py:129:9:129:29 | ControlFlowNode for SetComp [Set element] | +| test.py:129:16:129:16 | SSA variable y | test.py:129:10:129:10 | ControlFlowNode for y | +| test.py:129:21:129:28 | ControlFlowNode for List [List element] | test.py:129:16:129:16 | SSA variable y | +| test.py:129:22:129:27 | ControlFlowNode for SOURCE | test.py:129:21:129:28 | ControlFlowNode for List [List element] | | test.py:130:10:130:10 | ControlFlowNode for x [Set element] | test.py:130:10:130:16 | ControlFlowNode for Attribute() | -| test.py:134:9:134:29 | ControlFlowNode for SetComp [Set element] | test.py:135:10:135:10 | ControlFlowNode for x [Set element] | -| test.py:134:10:134:10 | ControlFlowNode for y | test.py:134:9:134:29 | ControlFlowNode for SetComp [Set element] | -| test.py:134:16:134:16 | SSA variable y | test.py:134:10:134:10 | ControlFlowNode for y | -| test.py:134:21:134:28 | ControlFlowNode for List [List element] | test.py:134:16:134:16 | SSA variable y | -| test.py:134:22:134:27 | ControlFlowNode for SOURCE | test.py:134:21:134:28 | ControlFlowNode for List [List element] | -| test.py:135:10:135:10 | ControlFlowNode for x [Set element] | test.py:135:10:135:16 | ControlFlowNode for Attribute() | -| test.py:139:9:139:16 | ControlFlowNode for Set [List element] | test.py:140:21:140:21 | ControlFlowNode for l [List element] | -| test.py:139:10:139:15 | ControlFlowNode for SOURCE | test.py:139:9:139:16 | ControlFlowNode for Set [List element] | -| test.py:140:9:140:22 | ControlFlowNode for SetComp [Set element] | test.py:141:10:141:10 | ControlFlowNode for x [Set element] | -| test.py:140:10:140:10 | ControlFlowNode for y | test.py:140:9:140:22 | ControlFlowNode for SetComp [Set element] | -| test.py:140:16:140:16 | SSA variable y | test.py:140:10:140:10 | ControlFlowNode for y | -| test.py:140:21:140:21 | ControlFlowNode for l [List element] | test.py:140:16:140:16 | SSA variable y | -| test.py:141:10:141:10 | ControlFlowNode for x [Set element] | test.py:141:10:141:16 | ControlFlowNode for Attribute() | -| test.py:152:9:152:21 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:153:10:153:10 | ControlFlowNode for x [Dictionary element at key s] | -| test.py:152:15:152:20 | ControlFlowNode for SOURCE | test.py:152:9:152:21 | ControlFlowNode for Dict [Dictionary element at key s] | -| test.py:153:10:153:10 | ControlFlowNode for x [Dictionary element at key s] | test.py:153:10:153:15 | ControlFlowNode for Subscript | -| test.py:157:9:157:21 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:158:10:158:10 | ControlFlowNode for x [Dictionary element at key s] | -| test.py:157:15:157:20 | ControlFlowNode for SOURCE | test.py:157:9:157:21 | ControlFlowNode for Dict [Dictionary element at key s] | -| test.py:158:10:158:10 | ControlFlowNode for x [Dictionary element at key s] | test.py:158:10:158:19 | ControlFlowNode for Attribute() | -| test.py:184:9:184:42 | ControlFlowNode for ListComp [List element] | test.py:185:10:185:10 | ControlFlowNode for x [List element] | -| test.py:184:10:184:10 | ControlFlowNode for y | test.py:184:9:184:42 | ControlFlowNode for ListComp [List element] | -| test.py:184:16:184:16 | SSA variable z [List element] | test.py:184:41:184:41 | ControlFlowNode for z [List element] | -| test.py:184:21:184:30 | ControlFlowNode for List [List element, List element] | test.py:184:16:184:16 | SSA variable z [List element] | -| test.py:184:22:184:29 | ControlFlowNode for List [List element] | test.py:184:21:184:30 | ControlFlowNode for List [List element, List element] | -| test.py:184:23:184:28 | ControlFlowNode for SOURCE | test.py:184:22:184:29 | ControlFlowNode for List [List element] | -| test.py:184:36:184:36 | SSA variable y | test.py:184:10:184:10 | ControlFlowNode for y | -| test.py:184:41:184:41 | ControlFlowNode for z [List element] | test.py:184:36:184:36 | SSA variable y | -| test.py:185:10:185:10 | ControlFlowNode for x [List element] | test.py:185:10:185:13 | ControlFlowNode for Subscript | -| test.py:189:9:189:68 | ControlFlowNode for ListComp [List element] | test.py:190:10:190:10 | ControlFlowNode for x [List element] | -| test.py:189:10:189:10 | ControlFlowNode for y | test.py:189:9:189:68 | ControlFlowNode for ListComp [List element] | -| test.py:189:16:189:16 | SSA variable v [List element, List element, ... (3)] | test.py:189:45:189:45 | ControlFlowNode for v [List element, List element, ... (3)] | -| test.py:189:21:189:34 | ControlFlowNode for List [List element, List element, ... (4)] | test.py:189:16:189:16 | SSA variable v [List element, List element, ... (3)] | -| test.py:189:22:189:33 | ControlFlowNode for List [List element, List element, ... (3)] | test.py:189:21:189:34 | ControlFlowNode for List [List element, List element, ... (4)] | -| test.py:189:23:189:32 | ControlFlowNode for List [List element, List element] | test.py:189:22:189:33 | ControlFlowNode for List [List element, List element, ... (3)] | -| test.py:189:24:189:31 | ControlFlowNode for List [List element] | test.py:189:23:189:32 | ControlFlowNode for List [List element, List element] | -| test.py:189:25:189:30 | ControlFlowNode for SOURCE | test.py:189:24:189:31 | ControlFlowNode for List [List element] | -| test.py:189:40:189:40 | SSA variable u [List element, List element] | test.py:189:56:189:56 | ControlFlowNode for u [List element, List element] | -| test.py:189:45:189:45 | ControlFlowNode for v [List element, List element, ... (3)] | test.py:189:40:189:40 | SSA variable u [List element, List element] | -| test.py:189:51:189:51 | SSA variable z [List element] | test.py:189:67:189:67 | ControlFlowNode for z [List element] | -| test.py:189:56:189:56 | ControlFlowNode for u [List element, List element] | test.py:189:51:189:51 | SSA variable z [List element] | -| test.py:189:62:189:62 | SSA variable y | test.py:189:10:189:10 | ControlFlowNode for y | -| test.py:189:67:189:67 | ControlFlowNode for z [List element] | test.py:189:62:189:62 | SSA variable y | -| test.py:190:10:190:10 | ControlFlowNode for x [List element] | test.py:190:10:190:13 | ControlFlowNode for Subscript | -| test.py:200:9:200:42 | ControlFlowNode for ListComp [List element] | test.py:201:10:201:10 | ControlFlowNode for x [List element] | -| test.py:200:10:200:10 | ControlFlowNode for y | test.py:200:9:200:42 | ControlFlowNode for ListComp [List element] | -| test.py:200:16:200:16 | SSA variable y | test.py:200:10:200:10 | ControlFlowNode for y | -| test.py:200:22:200:22 | ControlFlowNode for z | test.py:200:22:200:40 | ControlFlowNode for GeneratorExp [List element] | -| test.py:200:22:200:40 | ControlFlowNode for GeneratorExp [List element] | test.py:200:16:200:16 | SSA variable y | -| test.py:200:28:200:28 | SSA variable z | test.py:200:22:200:22 | ControlFlowNode for z | -| test.py:200:33:200:40 | ControlFlowNode for List [List element] | test.py:200:28:200:28 | SSA variable z | -| test.py:200:34:200:39 | ControlFlowNode for SOURCE | test.py:200:33:200:40 | ControlFlowNode for List [List element] | -| test.py:201:10:201:10 | ControlFlowNode for x [List element] | test.py:201:10:201:13 | ControlFlowNode for Subscript | -| test.py:344:11:344:16 | ControlFlowNode for SOURCE | test.py:344:11:344:17 | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:344:11:344:17 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:344:10:344:21 | ControlFlowNode for Subscript | -| test.py:348:10:348:17 | ControlFlowNode for List [List element] | test.py:348:10:348:20 | ControlFlowNode for Subscript | -| test.py:348:11:348:16 | ControlFlowNode for SOURCE | test.py:348:10:348:17 | ControlFlowNode for List [List element] | -| test.py:352:10:352:22 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:352:10:352:27 | ControlFlowNode for Subscript | -| test.py:352:16:352:21 | ControlFlowNode for SOURCE | test.py:352:10:352:22 | ControlFlowNode for Dict [Dictionary element at key s] | -| test.py:375:28:375:33 | ControlFlowNode for SOURCE | test.py:375:10:375:34 | ControlFlowNode for second() | -| test.py:457:12:457:17 | ControlFlowNode for SOURCE | test.py:457:10:457:18 | ControlFlowNode for f() | -| test.py:462:28:462:33 | ControlFlowNode for SOURCE | test.py:462:10:462:34 | ControlFlowNode for second() | -| test.py:504:9:504:14 | ControlFlowNode for SOURCE | test.py:506:10:506:10 | ControlFlowNode for a | -| test.py:504:9:504:14 | ControlFlowNode for SOURCE | test.py:511:10:511:10 | ControlFlowNode for b | +| test.py:134:9:134:16 | ControlFlowNode for Set [List element] | test.py:135:21:135:21 | ControlFlowNode for l [List element] | +| test.py:134:10:134:15 | ControlFlowNode for SOURCE | test.py:134:9:134:16 | ControlFlowNode for Set [List element] | +| test.py:135:9:135:22 | ControlFlowNode for SetComp [Set element] | test.py:136:10:136:10 | ControlFlowNode for x [Set element] | +| test.py:135:10:135:10 | ControlFlowNode for y | test.py:135:9:135:22 | ControlFlowNode for SetComp [Set element] | +| test.py:135:16:135:16 | SSA variable y | test.py:135:10:135:10 | ControlFlowNode for y | +| test.py:135:21:135:21 | ControlFlowNode for l [List element] | test.py:135:16:135:16 | SSA variable y | +| test.py:136:10:136:10 | ControlFlowNode for x [Set element] | test.py:136:10:136:16 | ControlFlowNode for Attribute() | +| test.py:146:9:146:21 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:147:10:147:10 | ControlFlowNode for x [Dictionary element at key s] | +| test.py:146:15:146:20 | ControlFlowNode for SOURCE | test.py:146:9:146:21 | ControlFlowNode for Dict [Dictionary element at key s] | +| test.py:147:10:147:10 | ControlFlowNode for x [Dictionary element at key s] | test.py:147:10:147:15 | ControlFlowNode for Subscript | +| test.py:151:9:151:21 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:152:10:152:10 | ControlFlowNode for x [Dictionary element at key s] | +| test.py:151:15:151:20 | ControlFlowNode for SOURCE | test.py:151:9:151:21 | ControlFlowNode for Dict [Dictionary element at key s] | +| test.py:152:10:152:10 | ControlFlowNode for x [Dictionary element at key s] | test.py:152:10:152:19 | ControlFlowNode for Attribute() | +| test.py:177:9:177:42 | ControlFlowNode for ListComp [List element] | test.py:178:10:178:10 | ControlFlowNode for x [List element] | +| test.py:177:10:177:10 | ControlFlowNode for y | test.py:177:9:177:42 | ControlFlowNode for ListComp [List element] | +| test.py:177:16:177:16 | SSA variable z [List element] | test.py:177:41:177:41 | ControlFlowNode for z [List element] | +| test.py:177:21:177:30 | ControlFlowNode for List [List element, List element] | test.py:177:16:177:16 | SSA variable z [List element] | +| test.py:177:22:177:29 | ControlFlowNode for List [List element] | test.py:177:21:177:30 | ControlFlowNode for List [List element, List element] | +| test.py:177:23:177:28 | ControlFlowNode for SOURCE | test.py:177:22:177:29 | ControlFlowNode for List [List element] | +| test.py:177:36:177:36 | SSA variable y | test.py:177:10:177:10 | ControlFlowNode for y | +| test.py:177:41:177:41 | ControlFlowNode for z [List element] | test.py:177:36:177:36 | SSA variable y | +| test.py:178:10:178:10 | ControlFlowNode for x [List element] | test.py:178:10:178:13 | ControlFlowNode for Subscript | +| test.py:182:9:182:68 | ControlFlowNode for ListComp [List element] | test.py:183:10:183:10 | ControlFlowNode for x [List element] | +| test.py:182:10:182:10 | ControlFlowNode for y | test.py:182:9:182:68 | ControlFlowNode for ListComp [List element] | +| test.py:182:16:182:16 | SSA variable v [List element, List element, ... (3)] | test.py:182:45:182:45 | ControlFlowNode for v [List element, List element, ... (3)] | +| test.py:182:21:182:34 | ControlFlowNode for List [List element, List element, ... (4)] | test.py:182:16:182:16 | SSA variable v [List element, List element, ... (3)] | +| test.py:182:22:182:33 | ControlFlowNode for List [List element, List element, ... (3)] | test.py:182:21:182:34 | ControlFlowNode for List [List element, List element, ... (4)] | +| test.py:182:23:182:32 | ControlFlowNode for List [List element, List element] | test.py:182:22:182:33 | ControlFlowNode for List [List element, List element, ... (3)] | +| test.py:182:24:182:31 | ControlFlowNode for List [List element] | test.py:182:23:182:32 | ControlFlowNode for List [List element, List element] | +| test.py:182:25:182:30 | ControlFlowNode for SOURCE | test.py:182:24:182:31 | ControlFlowNode for List [List element] | +| test.py:182:40:182:40 | SSA variable u [List element, List element] | test.py:182:56:182:56 | ControlFlowNode for u [List element, List element] | +| test.py:182:45:182:45 | ControlFlowNode for v [List element, List element, ... (3)] | test.py:182:40:182:40 | SSA variable u [List element, List element] | +| test.py:182:51:182:51 | SSA variable z [List element] | test.py:182:67:182:67 | ControlFlowNode for z [List element] | +| test.py:182:56:182:56 | ControlFlowNode for u [List element, List element] | test.py:182:51:182:51 | SSA variable z [List element] | +| test.py:182:62:182:62 | SSA variable y | test.py:182:10:182:10 | ControlFlowNode for y | +| test.py:182:67:182:67 | ControlFlowNode for z [List element] | test.py:182:62:182:62 | SSA variable y | +| test.py:183:10:183:10 | ControlFlowNode for x [List element] | test.py:183:10:183:13 | ControlFlowNode for Subscript | +| test.py:193:9:193:42 | ControlFlowNode for ListComp [List element] | test.py:194:10:194:10 | ControlFlowNode for x [List element] | +| test.py:193:10:193:10 | ControlFlowNode for y | test.py:193:9:193:42 | ControlFlowNode for ListComp [List element] | +| test.py:193:16:193:16 | SSA variable y | test.py:193:10:193:10 | ControlFlowNode for y | +| test.py:193:22:193:22 | ControlFlowNode for z | test.py:193:22:193:40 | ControlFlowNode for GeneratorExp [List element] | +| test.py:193:22:193:40 | ControlFlowNode for GeneratorExp [List element] | test.py:193:16:193:16 | SSA variable y | +| test.py:193:28:193:28 | SSA variable z | test.py:193:22:193:22 | ControlFlowNode for z | +| test.py:193:33:193:40 | ControlFlowNode for List [List element] | test.py:193:28:193:28 | SSA variable z | +| test.py:193:34:193:39 | ControlFlowNode for SOURCE | test.py:193:33:193:40 | ControlFlowNode for List [List element] | +| test.py:194:10:194:10 | ControlFlowNode for x [List element] | test.py:194:10:194:13 | ControlFlowNode for Subscript | +| test.py:330:11:330:16 | ControlFlowNode for SOURCE | test.py:330:11:330:17 | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:330:11:330:17 | ControlFlowNode for Tuple [Tuple element at index 0] | test.py:330:10:330:21 | ControlFlowNode for Subscript | +| test.py:334:10:334:17 | ControlFlowNode for List [List element] | test.py:334:10:334:20 | ControlFlowNode for Subscript | +| test.py:334:11:334:16 | ControlFlowNode for SOURCE | test.py:334:10:334:17 | ControlFlowNode for List [List element] | +| test.py:338:10:338:22 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:338:10:338:27 | ControlFlowNode for Subscript | +| test.py:338:16:338:21 | ControlFlowNode for SOURCE | test.py:338:10:338:22 | ControlFlowNode for Dict [Dictionary element at key s] | +| test.py:361:28:361:33 | ControlFlowNode for SOURCE | test.py:361:10:361:34 | ControlFlowNode for second() | +| test.py:446:12:446:17 | ControlFlowNode for SOURCE | test.py:446:10:446:18 | ControlFlowNode for f() | +| test.py:453:28:453:33 | ControlFlowNode for SOURCE | test.py:453:10:453:34 | ControlFlowNode for second() | +| test.py:502:9:502:14 | ControlFlowNode for SOURCE | test.py:504:10:504:10 | ControlFlowNode for a | +| test.py:502:9:502:14 | ControlFlowNode for SOURCE | test.py:509:10:509:10 | ControlFlowNode for b | nodes | datamodel.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module datamodel | semmle.label | ModuleVariableNode for Global Variable SOURCE in Module datamodel | | datamodel.py:13:1:13:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | @@ -179,126 +179,126 @@ nodes | test.py:37:9:37:9 | ControlFlowNode for x [Tuple element at index 1] | semmle.label | ControlFlowNode for x [Tuple element at index 1] | | test.py:37:9:37:12 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | test.py:38:10:38:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | -| test.py:50:9:50:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:51:10:51:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:57:9:57:16 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | -| test.py:58:10:58:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:62:9:62:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | -| test.py:63:10:63:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:67:9:67:10 | ControlFlowNode for IntegerLiteral | semmle.label | ControlFlowNode for IntegerLiteral | -| test.py:68:10:68:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:72:9:72:12 | ControlFlowNode for FloatLiteral | semmle.label | ControlFlowNode for FloatLiteral | -| test.py:73:10:73:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:84:10:84:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:85:10:85:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:91:9:91:16 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:91:10:91:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:92:10:92:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | -| test.py:92:10:92:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:101:9:101:37 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] | -| test.py:101:10:101:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:102:10:102:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | -| test.py:102:10:102:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:106:9:106:29 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] | -| test.py:106:10:106:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | -| test.py:106:16:106:16 | SSA variable y | semmle.label | SSA variable y | -| test.py:106:21:106:28 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:106:22:106:27 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:107:10:107:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | -| test.py:107:10:107:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:111:9:111:16 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:111:10:111:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:112:9:112:22 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] | -| test.py:112:10:112:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | -| test.py:112:16:112:16 | SSA variable y | semmle.label | SSA variable y | -| test.py:112:21:112:21 | ControlFlowNode for l [List element] | semmle.label | ControlFlowNode for l [List element] | -| test.py:113:10:113:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | -| test.py:113:10:113:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:124:9:124:16 | ControlFlowNode for Set [List element] | semmle.label | ControlFlowNode for Set [List element] | +| test.py:49:9:49:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:50:10:50:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:55:9:55:16 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | +| test.py:56:10:56:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:60:9:60:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | +| test.py:61:10:61:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:65:9:65:10 | ControlFlowNode for IntegerLiteral | semmle.label | ControlFlowNode for IntegerLiteral | +| test.py:66:10:66:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:70:9:70:12 | ControlFlowNode for FloatLiteral | semmle.label | ControlFlowNode for FloatLiteral | +| test.py:71:10:71:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:81:9:81:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:82:10:82:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:87:9:87:16 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:87:10:87:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:88:10:88:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | +| test.py:88:10:88:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:97:9:97:37 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] | +| test.py:97:10:97:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:98:10:98:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | +| test.py:98:10:98:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:102:9:102:29 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] | +| test.py:102:10:102:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | +| test.py:102:16:102:16 | SSA variable y | semmle.label | SSA variable y | +| test.py:102:21:102:28 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:102:22:102:27 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:103:10:103:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | +| test.py:103:10:103:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:107:9:107:16 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:107:10:107:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:108:9:108:22 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] | +| test.py:108:10:108:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | +| test.py:108:16:108:16 | SSA variable y | semmle.label | SSA variable y | +| test.py:108:21:108:21 | ControlFlowNode for l [List element] | semmle.label | ControlFlowNode for l [List element] | +| test.py:109:10:109:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | +| test.py:109:10:109:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:119:9:119:16 | ControlFlowNode for Set [List element] | semmle.label | ControlFlowNode for Set [List element] | +| test.py:119:10:119:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:120:10:120:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | +| test.py:120:10:120:16 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| test.py:124:9:124:37 | ControlFlowNode for SetComp [Set element] | semmle.label | ControlFlowNode for SetComp [Set element] | | test.py:124:10:124:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:125:10:125:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | +| test.py:125:10:125:10 | ControlFlowNode for x [Set element] | semmle.label | ControlFlowNode for x [Set element] | | test.py:125:10:125:16 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| test.py:129:9:129:37 | ControlFlowNode for SetComp [Set element] | semmle.label | ControlFlowNode for SetComp [Set element] | -| test.py:129:10:129:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:129:9:129:29 | ControlFlowNode for SetComp [Set element] | semmle.label | ControlFlowNode for SetComp [Set element] | +| test.py:129:10:129:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | +| test.py:129:16:129:16 | SSA variable y | semmle.label | SSA variable y | +| test.py:129:21:129:28 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:129:22:129:27 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:130:10:130:10 | ControlFlowNode for x [Set element] | semmle.label | ControlFlowNode for x [Set element] | | test.py:130:10:130:16 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| test.py:134:9:134:29 | ControlFlowNode for SetComp [Set element] | semmle.label | ControlFlowNode for SetComp [Set element] | -| test.py:134:10:134:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | -| test.py:134:16:134:16 | SSA variable y | semmle.label | SSA variable y | -| test.py:134:21:134:28 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:134:22:134:27 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:135:10:135:10 | ControlFlowNode for x [Set element] | semmle.label | ControlFlowNode for x [Set element] | -| test.py:135:10:135:16 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| test.py:139:9:139:16 | ControlFlowNode for Set [List element] | semmle.label | ControlFlowNode for Set [List element] | -| test.py:139:10:139:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:140:9:140:22 | ControlFlowNode for SetComp [Set element] | semmle.label | ControlFlowNode for SetComp [Set element] | -| test.py:140:10:140:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | -| test.py:140:16:140:16 | SSA variable y | semmle.label | SSA variable y | -| test.py:140:21:140:21 | ControlFlowNode for l [List element] | semmle.label | ControlFlowNode for l [List element] | -| test.py:141:10:141:10 | ControlFlowNode for x [Set element] | semmle.label | ControlFlowNode for x [Set element] | -| test.py:141:10:141:16 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| test.py:152:9:152:21 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] | -| test.py:152:15:152:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:153:10:153:10 | ControlFlowNode for x [Dictionary element at key s] | semmle.label | ControlFlowNode for x [Dictionary element at key s] | -| test.py:153:10:153:15 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:157:9:157:21 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] | -| test.py:157:15:157:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:158:10:158:10 | ControlFlowNode for x [Dictionary element at key s] | semmle.label | ControlFlowNode for x [Dictionary element at key s] | -| test.py:158:10:158:19 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| test.py:184:9:184:42 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] | -| test.py:184:10:184:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | -| test.py:184:16:184:16 | SSA variable z [List element] | semmle.label | SSA variable z [List element] | -| test.py:184:21:184:30 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:184:22:184:29 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:184:23:184:28 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:184:36:184:36 | SSA variable y | semmle.label | SSA variable y | -| test.py:184:41:184:41 | ControlFlowNode for z [List element] | semmle.label | ControlFlowNode for z [List element] | -| test.py:185:10:185:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | -| test.py:185:10:185:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:189:9:189:68 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] | -| test.py:189:10:189:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | -| test.py:189:16:189:16 | SSA variable v [List element, List element, ... (3)] | semmle.label | SSA variable v [List element, List element, ... (3)] | -| test.py:189:21:189:34 | ControlFlowNode for List [List element, List element, ... (4)] | semmle.label | ControlFlowNode for List [List element, List element, ... (4)] | -| test.py:189:22:189:33 | ControlFlowNode for List [List element, List element, ... (3)] | semmle.label | ControlFlowNode for List [List element, List element, ... (3)] | -| test.py:189:23:189:32 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | -| test.py:189:24:189:31 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:189:25:189:30 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:189:40:189:40 | SSA variable u [List element, List element] | semmle.label | SSA variable u [List element, List element] | -| test.py:189:45:189:45 | ControlFlowNode for v [List element, List element, ... (3)] | semmle.label | ControlFlowNode for v [List element, List element, ... (3)] | -| test.py:189:51:189:51 | SSA variable z [List element] | semmle.label | SSA variable z [List element] | -| test.py:189:56:189:56 | ControlFlowNode for u [List element, List element] | semmle.label | ControlFlowNode for u [List element, List element] | -| test.py:189:62:189:62 | SSA variable y | semmle.label | SSA variable y | -| test.py:189:67:189:67 | ControlFlowNode for z [List element] | semmle.label | ControlFlowNode for z [List element] | -| test.py:190:10:190:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | -| test.py:190:10:190:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:200:9:200:42 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] | -| test.py:200:10:200:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | -| test.py:200:16:200:16 | SSA variable y | semmle.label | SSA variable y | -| test.py:200:22:200:22 | ControlFlowNode for z | semmle.label | ControlFlowNode for z | -| test.py:200:22:200:40 | ControlFlowNode for GeneratorExp [List element] | semmle.label | ControlFlowNode for GeneratorExp [List element] | -| test.py:200:28:200:28 | SSA variable z | semmle.label | SSA variable z | -| test.py:200:33:200:40 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:200:34:200:39 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:201:10:201:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | -| test.py:201:10:201:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:344:10:344:21 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:344:11:344:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:344:11:344:17 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | -| test.py:348:10:348:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | -| test.py:348:10:348:20 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:348:11:348:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:352:10:352:22 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] | -| test.py:352:10:352:27 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| test.py:352:16:352:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:375:10:375:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:375:28:375:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:457:10:457:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | -| test.py:457:12:457:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:462:10:462:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:462:28:462:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:504:9:504:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:506:10:506:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | -| test.py:511:10:511:10 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | +| test.py:134:9:134:16 | ControlFlowNode for Set [List element] | semmle.label | ControlFlowNode for Set [List element] | +| test.py:134:10:134:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:135:9:135:22 | ControlFlowNode for SetComp [Set element] | semmle.label | ControlFlowNode for SetComp [Set element] | +| test.py:135:10:135:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | +| test.py:135:16:135:16 | SSA variable y | semmle.label | SSA variable y | +| test.py:135:21:135:21 | ControlFlowNode for l [List element] | semmle.label | ControlFlowNode for l [List element] | +| test.py:136:10:136:10 | ControlFlowNode for x [Set element] | semmle.label | ControlFlowNode for x [Set element] | +| test.py:136:10:136:16 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| test.py:146:9:146:21 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] | +| test.py:146:15:146:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:147:10:147:10 | ControlFlowNode for x [Dictionary element at key s] | semmle.label | ControlFlowNode for x [Dictionary element at key s] | +| test.py:147:10:147:15 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:151:9:151:21 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] | +| test.py:151:15:151:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:152:10:152:10 | ControlFlowNode for x [Dictionary element at key s] | semmle.label | ControlFlowNode for x [Dictionary element at key s] | +| test.py:152:10:152:19 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| test.py:177:9:177:42 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] | +| test.py:177:10:177:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | +| test.py:177:16:177:16 | SSA variable z [List element] | semmle.label | SSA variable z [List element] | +| test.py:177:21:177:30 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:177:22:177:29 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:177:23:177:28 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:177:36:177:36 | SSA variable y | semmle.label | SSA variable y | +| test.py:177:41:177:41 | ControlFlowNode for z [List element] | semmle.label | ControlFlowNode for z [List element] | +| test.py:178:10:178:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | +| test.py:178:10:178:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:182:9:182:68 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] | +| test.py:182:10:182:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | +| test.py:182:16:182:16 | SSA variable v [List element, List element, ... (3)] | semmle.label | SSA variable v [List element, List element, ... (3)] | +| test.py:182:21:182:34 | ControlFlowNode for List [List element, List element, ... (4)] | semmle.label | ControlFlowNode for List [List element, List element, ... (4)] | +| test.py:182:22:182:33 | ControlFlowNode for List [List element, List element, ... (3)] | semmle.label | ControlFlowNode for List [List element, List element, ... (3)] | +| test.py:182:23:182:32 | ControlFlowNode for List [List element, List element] | semmle.label | ControlFlowNode for List [List element, List element] | +| test.py:182:24:182:31 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:182:25:182:30 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:182:40:182:40 | SSA variable u [List element, List element] | semmle.label | SSA variable u [List element, List element] | +| test.py:182:45:182:45 | ControlFlowNode for v [List element, List element, ... (3)] | semmle.label | ControlFlowNode for v [List element, List element, ... (3)] | +| test.py:182:51:182:51 | SSA variable z [List element] | semmle.label | SSA variable z [List element] | +| test.py:182:56:182:56 | ControlFlowNode for u [List element, List element] | semmle.label | ControlFlowNode for u [List element, List element] | +| test.py:182:62:182:62 | SSA variable y | semmle.label | SSA variable y | +| test.py:182:67:182:67 | ControlFlowNode for z [List element] | semmle.label | ControlFlowNode for z [List element] | +| test.py:183:10:183:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | +| test.py:183:10:183:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:193:9:193:42 | ControlFlowNode for ListComp [List element] | semmle.label | ControlFlowNode for ListComp [List element] | +| test.py:193:10:193:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y | +| test.py:193:16:193:16 | SSA variable y | semmle.label | SSA variable y | +| test.py:193:22:193:22 | ControlFlowNode for z | semmle.label | ControlFlowNode for z | +| test.py:193:22:193:40 | ControlFlowNode for GeneratorExp [List element] | semmle.label | ControlFlowNode for GeneratorExp [List element] | +| test.py:193:28:193:28 | SSA variable z | semmle.label | SSA variable z | +| test.py:193:33:193:40 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:193:34:193:39 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:194:10:194:10 | ControlFlowNode for x [List element] | semmle.label | ControlFlowNode for x [List element] | +| test.py:194:10:194:13 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:330:10:330:21 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:330:11:330:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:330:11:330:17 | ControlFlowNode for Tuple [Tuple element at index 0] | semmle.label | ControlFlowNode for Tuple [Tuple element at index 0] | +| test.py:334:10:334:17 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | +| test.py:334:10:334:20 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:334:11:334:16 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:338:10:338:22 | ControlFlowNode for Dict [Dictionary element at key s] | semmle.label | ControlFlowNode for Dict [Dictionary element at key s] | +| test.py:338:10:338:27 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| test.py:338:16:338:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:361:10:361:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:361:28:361:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:446:10:446:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | +| test.py:446:12:446:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:453:10:453:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:453:28:453:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:502:9:502:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:504:10:504:10 | ControlFlowNode for a | semmle.label | ControlFlowNode for a | +| test.py:509:10:509:10 | ControlFlowNode for b | semmle.label | ControlFlowNode for b | #select | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | | datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | Flow found | @@ -326,53 +326,53 @@ nodes | datamodel.py:159:6:159:17 | ControlFlowNode for Attribute | datamodel.py:152:14:152:19 | ControlFlowNode for SOURCE | datamodel.py:159:6:159:17 | ControlFlowNode for Attribute | Flow found | | test.py:38:10:38:10 | ControlFlowNode for y | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:38:10:38:10 | ControlFlowNode for y | Flow found | | test.py:38:10:38:10 | ControlFlowNode for y | test.py:36:21:36:26 | ControlFlowNode for SOURCE | test.py:38:10:38:10 | ControlFlowNode for y | Flow found | -| test.py:51:10:51:10 | ControlFlowNode for x | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:51:10:51:10 | ControlFlowNode for x | Flow found | -| test.py:51:10:51:10 | ControlFlowNode for x | test.py:50:9:50:14 | ControlFlowNode for SOURCE | test.py:51:10:51:10 | ControlFlowNode for x | Flow found | -| test.py:58:10:58:10 | ControlFlowNode for x | test.py:57:9:57:16 | ControlFlowNode for Str | test.py:58:10:58:10 | ControlFlowNode for x | Flow found | -| test.py:63:10:63:10 | ControlFlowNode for x | test.py:62:9:62:17 | ControlFlowNode for Str | test.py:63:10:63:10 | ControlFlowNode for x | Flow found | -| test.py:68:10:68:10 | ControlFlowNode for x | test.py:67:9:67:10 | ControlFlowNode for IntegerLiteral | test.py:68:10:68:10 | ControlFlowNode for x | Flow found | -| test.py:73:10:73:10 | ControlFlowNode for x | test.py:72:9:72:12 | ControlFlowNode for FloatLiteral | test.py:73:10:73:10 | ControlFlowNode for x | Flow found | -| test.py:85:10:85:10 | ControlFlowNode for x | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:85:10:85:10 | ControlFlowNode for x | Flow found | -| test.py:85:10:85:10 | ControlFlowNode for x | test.py:84:10:84:15 | ControlFlowNode for SOURCE | test.py:85:10:85:10 | ControlFlowNode for x | Flow found | -| test.py:92:10:92:13 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:92:10:92:13 | ControlFlowNode for Subscript | Flow found | -| test.py:92:10:92:13 | ControlFlowNode for Subscript | test.py:91:10:91:15 | ControlFlowNode for SOURCE | test.py:92:10:92:13 | ControlFlowNode for Subscript | Flow found | -| test.py:102:10:102:13 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:102:10:102:13 | ControlFlowNode for Subscript | Flow found | -| test.py:102:10:102:13 | ControlFlowNode for Subscript | test.py:101:10:101:15 | ControlFlowNode for SOURCE | test.py:102:10:102:13 | ControlFlowNode for Subscript | Flow found | -| test.py:107:10:107:13 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:107:10:107:13 | ControlFlowNode for Subscript | Flow found | -| test.py:107:10:107:13 | ControlFlowNode for Subscript | test.py:106:22:106:27 | ControlFlowNode for SOURCE | test.py:107:10:107:13 | ControlFlowNode for Subscript | Flow found | -| test.py:113:10:113:13 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:113:10:113:13 | ControlFlowNode for Subscript | Flow found | -| test.py:113:10:113:13 | ControlFlowNode for Subscript | test.py:111:10:111:15 | ControlFlowNode for SOURCE | test.py:113:10:113:13 | ControlFlowNode for Subscript | Flow found | +| test.py:50:10:50:10 | ControlFlowNode for x | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:50:10:50:10 | ControlFlowNode for x | Flow found | +| test.py:50:10:50:10 | ControlFlowNode for x | test.py:49:9:49:14 | ControlFlowNode for SOURCE | test.py:50:10:50:10 | ControlFlowNode for x | Flow found | +| test.py:56:10:56:10 | ControlFlowNode for x | test.py:55:9:55:16 | ControlFlowNode for Str | test.py:56:10:56:10 | ControlFlowNode for x | Flow found | +| test.py:61:10:61:10 | ControlFlowNode for x | test.py:60:9:60:17 | ControlFlowNode for Str | test.py:61:10:61:10 | ControlFlowNode for x | Flow found | +| test.py:66:10:66:10 | ControlFlowNode for x | test.py:65:9:65:10 | ControlFlowNode for IntegerLiteral | test.py:66:10:66:10 | ControlFlowNode for x | Flow found | +| test.py:71:10:71:10 | ControlFlowNode for x | test.py:70:9:70:12 | ControlFlowNode for FloatLiteral | test.py:71:10:71:10 | ControlFlowNode for x | Flow found | +| test.py:82:10:82:10 | ControlFlowNode for x | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:82:10:82:10 | ControlFlowNode for x | Flow found | +| test.py:82:10:82:10 | ControlFlowNode for x | test.py:81:9:81:14 | ControlFlowNode for SOURCE | test.py:82:10:82:10 | ControlFlowNode for x | Flow found | +| test.py:88:10:88:13 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:88:10:88:13 | ControlFlowNode for Subscript | Flow found | +| test.py:88:10:88:13 | ControlFlowNode for Subscript | test.py:87:10:87:15 | ControlFlowNode for SOURCE | test.py:88:10:88:13 | ControlFlowNode for Subscript | Flow found | +| test.py:98:10:98:13 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:98:10:98:13 | ControlFlowNode for Subscript | Flow found | +| test.py:98:10:98:13 | ControlFlowNode for Subscript | test.py:97:10:97:15 | ControlFlowNode for SOURCE | test.py:98:10:98:13 | ControlFlowNode for Subscript | Flow found | +| test.py:103:10:103:13 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:103:10:103:13 | ControlFlowNode for Subscript | Flow found | +| test.py:103:10:103:13 | ControlFlowNode for Subscript | test.py:102:22:102:27 | ControlFlowNode for SOURCE | test.py:103:10:103:13 | ControlFlowNode for Subscript | Flow found | +| test.py:109:10:109:13 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:109:10:109:13 | ControlFlowNode for Subscript | Flow found | +| test.py:109:10:109:13 | ControlFlowNode for Subscript | test.py:107:10:107:15 | ControlFlowNode for SOURCE | test.py:109:10:109:13 | ControlFlowNode for Subscript | Flow found | +| test.py:120:10:120:16 | ControlFlowNode for Attribute() | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:120:10:120:16 | ControlFlowNode for Attribute() | Flow found | +| test.py:120:10:120:16 | ControlFlowNode for Attribute() | test.py:119:10:119:15 | ControlFlowNode for SOURCE | test.py:120:10:120:16 | ControlFlowNode for Attribute() | Flow found | | test.py:125:10:125:16 | ControlFlowNode for Attribute() | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:125:10:125:16 | ControlFlowNode for Attribute() | Flow found | | test.py:125:10:125:16 | ControlFlowNode for Attribute() | test.py:124:10:124:15 | ControlFlowNode for SOURCE | test.py:125:10:125:16 | ControlFlowNode for Attribute() | Flow found | | test.py:130:10:130:16 | ControlFlowNode for Attribute() | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:130:10:130:16 | ControlFlowNode for Attribute() | Flow found | -| test.py:130:10:130:16 | ControlFlowNode for Attribute() | test.py:129:10:129:15 | ControlFlowNode for SOURCE | test.py:130:10:130:16 | ControlFlowNode for Attribute() | Flow found | -| test.py:135:10:135:16 | ControlFlowNode for Attribute() | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:135:10:135:16 | ControlFlowNode for Attribute() | Flow found | -| test.py:135:10:135:16 | ControlFlowNode for Attribute() | test.py:134:22:134:27 | ControlFlowNode for SOURCE | test.py:135:10:135:16 | ControlFlowNode for Attribute() | Flow found | -| test.py:141:10:141:16 | ControlFlowNode for Attribute() | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:141:10:141:16 | ControlFlowNode for Attribute() | Flow found | -| test.py:141:10:141:16 | ControlFlowNode for Attribute() | test.py:139:10:139:15 | ControlFlowNode for SOURCE | test.py:141:10:141:16 | ControlFlowNode for Attribute() | Flow found | -| test.py:153:10:153:15 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:153:10:153:15 | ControlFlowNode for Subscript | Flow found | -| test.py:153:10:153:15 | ControlFlowNode for Subscript | test.py:152:15:152:20 | ControlFlowNode for SOURCE | test.py:153:10:153:15 | ControlFlowNode for Subscript | Flow found | -| test.py:158:10:158:19 | ControlFlowNode for Attribute() | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:158:10:158:19 | ControlFlowNode for Attribute() | Flow found | -| test.py:158:10:158:19 | ControlFlowNode for Attribute() | test.py:157:15:157:20 | ControlFlowNode for SOURCE | test.py:158:10:158:19 | ControlFlowNode for Attribute() | Flow found | -| test.py:185:10:185:13 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:185:10:185:13 | ControlFlowNode for Subscript | Flow found | -| test.py:185:10:185:13 | ControlFlowNode for Subscript | test.py:184:23:184:28 | ControlFlowNode for SOURCE | test.py:185:10:185:13 | ControlFlowNode for Subscript | Flow found | -| test.py:190:10:190:13 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:190:10:190:13 | ControlFlowNode for Subscript | Flow found | -| test.py:190:10:190:13 | ControlFlowNode for Subscript | test.py:189:25:189:30 | ControlFlowNode for SOURCE | test.py:190:10:190:13 | ControlFlowNode for Subscript | Flow found | -| test.py:201:10:201:13 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:201:10:201:13 | ControlFlowNode for Subscript | Flow found | -| test.py:201:10:201:13 | ControlFlowNode for Subscript | test.py:200:34:200:39 | ControlFlowNode for SOURCE | test.py:201:10:201:13 | ControlFlowNode for Subscript | Flow found | -| test.py:344:10:344:21 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:344:10:344:21 | ControlFlowNode for Subscript | Flow found | -| test.py:344:10:344:21 | ControlFlowNode for Subscript | test.py:344:11:344:16 | ControlFlowNode for SOURCE | test.py:344:10:344:21 | ControlFlowNode for Subscript | Flow found | -| test.py:348:10:348:20 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:348:10:348:20 | ControlFlowNode for Subscript | Flow found | -| test.py:348:10:348:20 | ControlFlowNode for Subscript | test.py:348:11:348:16 | ControlFlowNode for SOURCE | test.py:348:10:348:20 | ControlFlowNode for Subscript | Flow found | -| test.py:352:10:352:27 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:352:10:352:27 | ControlFlowNode for Subscript | Flow found | -| test.py:352:10:352:27 | ControlFlowNode for Subscript | test.py:352:16:352:21 | ControlFlowNode for SOURCE | test.py:352:10:352:27 | ControlFlowNode for Subscript | Flow found | -| test.py:375:10:375:34 | ControlFlowNode for second() | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:375:10:375:34 | ControlFlowNode for second() | Flow found | -| test.py:375:10:375:34 | ControlFlowNode for second() | test.py:375:28:375:33 | ControlFlowNode for SOURCE | test.py:375:10:375:34 | ControlFlowNode for second() | Flow found | -| test.py:457:10:457:18 | ControlFlowNode for f() | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:457:10:457:18 | ControlFlowNode for f() | Flow found | -| test.py:457:10:457:18 | ControlFlowNode for f() | test.py:457:12:457:17 | ControlFlowNode for SOURCE | test.py:457:10:457:18 | ControlFlowNode for f() | Flow found | -| test.py:462:10:462:34 | ControlFlowNode for second() | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:462:10:462:34 | ControlFlowNode for second() | Flow found | -| test.py:462:10:462:34 | ControlFlowNode for second() | test.py:462:28:462:33 | ControlFlowNode for SOURCE | test.py:462:10:462:34 | ControlFlowNode for second() | Flow found | -| test.py:506:10:506:10 | ControlFlowNode for a | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:506:10:506:10 | ControlFlowNode for a | Flow found | -| test.py:506:10:506:10 | ControlFlowNode for a | test.py:504:9:504:14 | ControlFlowNode for SOURCE | test.py:506:10:506:10 | ControlFlowNode for a | Flow found | -| test.py:511:10:511:10 | ControlFlowNode for b | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:511:10:511:10 | ControlFlowNode for b | Flow found | -| test.py:511:10:511:10 | ControlFlowNode for b | test.py:504:9:504:14 | ControlFlowNode for SOURCE | test.py:511:10:511:10 | ControlFlowNode for b | Flow found | +| test.py:130:10:130:16 | ControlFlowNode for Attribute() | test.py:129:22:129:27 | ControlFlowNode for SOURCE | test.py:130:10:130:16 | ControlFlowNode for Attribute() | Flow found | +| test.py:136:10:136:16 | ControlFlowNode for Attribute() | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:136:10:136:16 | ControlFlowNode for Attribute() | Flow found | +| test.py:136:10:136:16 | ControlFlowNode for Attribute() | test.py:134:10:134:15 | ControlFlowNode for SOURCE | test.py:136:10:136:16 | ControlFlowNode for Attribute() | Flow found | +| test.py:147:10:147:15 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:147:10:147:15 | ControlFlowNode for Subscript | Flow found | +| test.py:147:10:147:15 | ControlFlowNode for Subscript | test.py:146:15:146:20 | ControlFlowNode for SOURCE | test.py:147:10:147:15 | ControlFlowNode for Subscript | Flow found | +| test.py:152:10:152:19 | ControlFlowNode for Attribute() | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:152:10:152:19 | ControlFlowNode for Attribute() | Flow found | +| test.py:152:10:152:19 | ControlFlowNode for Attribute() | test.py:151:15:151:20 | ControlFlowNode for SOURCE | test.py:152:10:152:19 | ControlFlowNode for Attribute() | Flow found | +| test.py:178:10:178:13 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:178:10:178:13 | ControlFlowNode for Subscript | Flow found | +| test.py:178:10:178:13 | ControlFlowNode for Subscript | test.py:177:23:177:28 | ControlFlowNode for SOURCE | test.py:178:10:178:13 | ControlFlowNode for Subscript | Flow found | +| test.py:183:10:183:13 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:183:10:183:13 | ControlFlowNode for Subscript | Flow found | +| test.py:183:10:183:13 | ControlFlowNode for Subscript | test.py:182:25:182:30 | ControlFlowNode for SOURCE | test.py:183:10:183:13 | ControlFlowNode for Subscript | Flow found | +| test.py:194:10:194:13 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:194:10:194:13 | ControlFlowNode for Subscript | Flow found | +| test.py:194:10:194:13 | ControlFlowNode for Subscript | test.py:193:34:193:39 | ControlFlowNode for SOURCE | test.py:194:10:194:13 | ControlFlowNode for Subscript | Flow found | +| test.py:330:10:330:21 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:330:10:330:21 | ControlFlowNode for Subscript | Flow found | +| test.py:330:10:330:21 | ControlFlowNode for Subscript | test.py:330:11:330:16 | ControlFlowNode for SOURCE | test.py:330:10:330:21 | ControlFlowNode for Subscript | Flow found | +| test.py:334:10:334:20 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:334:10:334:20 | ControlFlowNode for Subscript | Flow found | +| test.py:334:10:334:20 | ControlFlowNode for Subscript | test.py:334:11:334:16 | ControlFlowNode for SOURCE | test.py:334:10:334:20 | ControlFlowNode for Subscript | Flow found | +| test.py:338:10:338:27 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:338:10:338:27 | ControlFlowNode for Subscript | Flow found | +| test.py:338:10:338:27 | ControlFlowNode for Subscript | test.py:338:16:338:21 | ControlFlowNode for SOURCE | test.py:338:10:338:27 | ControlFlowNode for Subscript | Flow found | +| test.py:361:10:361:34 | ControlFlowNode for second() | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:361:10:361:34 | ControlFlowNode for second() | Flow found | +| test.py:361:10:361:34 | ControlFlowNode for second() | test.py:361:28:361:33 | ControlFlowNode for SOURCE | test.py:361:10:361:34 | ControlFlowNode for second() | Flow found | +| test.py:446:10:446:18 | ControlFlowNode for f() | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:446:10:446:18 | ControlFlowNode for f() | Flow found | +| test.py:446:10:446:18 | ControlFlowNode for f() | test.py:446:12:446:17 | ControlFlowNode for SOURCE | test.py:446:10:446:18 | ControlFlowNode for f() | Flow found | +| test.py:453:10:453:34 | ControlFlowNode for second() | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:453:10:453:34 | ControlFlowNode for second() | Flow found | +| test.py:453:10:453:34 | ControlFlowNode for second() | test.py:453:28:453:33 | ControlFlowNode for SOURCE | test.py:453:10:453:34 | ControlFlowNode for second() | Flow found | +| test.py:504:10:504:10 | ControlFlowNode for a | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:504:10:504:10 | ControlFlowNode for a | Flow found | +| test.py:504:10:504:10 | ControlFlowNode for a | test.py:502:9:502:14 | ControlFlowNode for SOURCE | test.py:504:10:504:10 | ControlFlowNode for a | Flow found | +| test.py:509:10:509:10 | ControlFlowNode for b | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:509:10:509:10 | ControlFlowNode for b | Flow found | +| test.py:509:10:509:10 | ControlFlowNode for b | test.py:502:9:502:14 | ControlFlowNode for SOURCE | test.py:509:10:509:10 | ControlFlowNode for b | Flow found | diff --git a/python/ql/test/experimental/dataflow/coverage/localFlow.expected b/python/ql/test/experimental/dataflow/coverage/localFlow.expected index 9610f505123..128dbc1dae0 100644 --- a/python/ql/test/experimental/dataflow/coverage/localFlow.expected +++ b/python/ql/test/experimental/dataflow/coverage/localFlow.expected @@ -6,31 +6,31 @@ | test.py:37:5:37:5 | SSA variable y | test.py:38:5:38:11 | SSA variable y | | test.py:37:5:37:5 | SSA variable y | test.py:38:10:38:10 | ControlFlowNode for y | | test.py:37:9:37:12 | ControlFlowNode for Subscript | test.py:37:5:37:5 | SSA variable y | -| test.py:188:1:188:53 | GSSA Variable SINK | test.py:190:5:190:8 | ControlFlowNode for SINK | -| test.py:188:1:188:53 | GSSA Variable SOURCE | test.py:189:25:189:30 | ControlFlowNode for SOURCE | -| test.py:189:5:189:5 | SSA variable x | test.py:190:10:190:10 | ControlFlowNode for x | -| test.py:189:9:189:68 | ControlFlowNode for ListComp | test.py:189:5:189:5 | SSA variable x | -| test.py:189:9:189:68 | SSA variable u | test.py:189:9:189:68 | SSA variable u | -| test.py:189:9:189:68 | SSA variable u | test.py:189:9:189:68 | SSA variable u | -| test.py:189:9:189:68 | SSA variable u | test.py:189:9:189:68 | SSA variable u | -| test.py:189:9:189:68 | SSA variable v | test.py:189:9:189:68 | SSA variable v | -| test.py:189:9:189:68 | SSA variable y | test.py:189:9:189:68 | SSA variable y | -| test.py:189:9:189:68 | SSA variable y | test.py:189:9:189:68 | SSA variable y | -| test.py:189:9:189:68 | SSA variable y | test.py:189:9:189:68 | SSA variable y | -| test.py:189:9:189:68 | SSA variable y | test.py:189:9:189:68 | SSA variable y | -| test.py:189:9:189:68 | SSA variable y | test.py:189:9:189:68 | SSA variable y | -| test.py:189:9:189:68 | SSA variable y | test.py:189:9:189:68 | SSA variable y | -| test.py:189:9:189:68 | SSA variable y | test.py:189:9:189:68 | SSA variable y | -| test.py:189:9:189:68 | SSA variable z | test.py:189:9:189:68 | SSA variable z | -| test.py:189:9:189:68 | SSA variable z | test.py:189:9:189:68 | SSA variable z | -| test.py:189:9:189:68 | SSA variable z | test.py:189:9:189:68 | SSA variable z | -| test.py:189:9:189:68 | SSA variable z | test.py:189:9:189:68 | SSA variable z | -| test.py:189:9:189:68 | SSA variable z | test.py:189:9:189:68 | SSA variable z | -| test.py:189:16:189:16 | SSA variable v | test.py:189:9:189:68 | SSA variable v | -| test.py:189:16:189:16 | SSA variable v | test.py:189:45:189:45 | ControlFlowNode for v | -| test.py:189:40:189:40 | SSA variable u | test.py:189:9:189:68 | SSA variable u | -| test.py:189:40:189:40 | SSA variable u | test.py:189:56:189:56 | ControlFlowNode for u | -| test.py:189:51:189:51 | SSA variable z | test.py:189:9:189:68 | SSA variable z | -| test.py:189:51:189:51 | SSA variable z | test.py:189:67:189:67 | ControlFlowNode for z | -| test.py:189:62:189:62 | SSA variable y | test.py:189:9:189:68 | SSA variable y | -| test.py:189:62:189:62 | SSA variable y | test.py:189:10:189:10 | ControlFlowNode for y | +| test.py:181:1:181:53 | GSSA Variable SINK | test.py:183:5:183:8 | ControlFlowNode for SINK | +| test.py:181:1:181:53 | GSSA Variable SOURCE | test.py:182:25:182:30 | ControlFlowNode for SOURCE | +| test.py:182:5:182:5 | SSA variable x | test.py:183:10:183:10 | ControlFlowNode for x | +| test.py:182:9:182:68 | ControlFlowNode for ListComp | test.py:182:5:182:5 | SSA variable x | +| test.py:182:9:182:68 | SSA variable u | test.py:182:9:182:68 | SSA variable u | +| test.py:182:9:182:68 | SSA variable u | test.py:182:9:182:68 | SSA variable u | +| test.py:182:9:182:68 | SSA variable u | test.py:182:9:182:68 | SSA variable u | +| test.py:182:9:182:68 | SSA variable v | test.py:182:9:182:68 | SSA variable v | +| test.py:182:9:182:68 | SSA variable y | test.py:182:9:182:68 | SSA variable y | +| test.py:182:9:182:68 | SSA variable y | test.py:182:9:182:68 | SSA variable y | +| test.py:182:9:182:68 | SSA variable y | test.py:182:9:182:68 | SSA variable y | +| test.py:182:9:182:68 | SSA variable y | test.py:182:9:182:68 | SSA variable y | +| test.py:182:9:182:68 | SSA variable y | test.py:182:9:182:68 | SSA variable y | +| test.py:182:9:182:68 | SSA variable y | test.py:182:9:182:68 | SSA variable y | +| test.py:182:9:182:68 | SSA variable y | test.py:182:9:182:68 | SSA variable y | +| test.py:182:9:182:68 | SSA variable z | test.py:182:9:182:68 | SSA variable z | +| test.py:182:9:182:68 | SSA variable z | test.py:182:9:182:68 | SSA variable z | +| test.py:182:9:182:68 | SSA variable z | test.py:182:9:182:68 | SSA variable z | +| test.py:182:9:182:68 | SSA variable z | test.py:182:9:182:68 | SSA variable z | +| test.py:182:9:182:68 | SSA variable z | test.py:182:9:182:68 | SSA variable z | +| test.py:182:16:182:16 | SSA variable v | test.py:182:9:182:68 | SSA variable v | +| test.py:182:16:182:16 | SSA variable v | test.py:182:45:182:45 | ControlFlowNode for v | +| test.py:182:40:182:40 | SSA variable u | test.py:182:9:182:68 | SSA variable u | +| test.py:182:40:182:40 | SSA variable u | test.py:182:56:182:56 | ControlFlowNode for u | +| test.py:182:51:182:51 | SSA variable z | test.py:182:9:182:68 | SSA variable z | +| test.py:182:51:182:51 | SSA variable z | test.py:182:67:182:67 | ControlFlowNode for z | +| test.py:182:62:182:62 | SSA variable y | test.py:182:9:182:68 | SSA variable y | +| test.py:182:62:182:62 | SSA variable y | test.py:182:10:182:10 | ControlFlowNode for y | diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 32e303e3652..383b31e3c3b 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -43,16 +43,14 @@ def test_tuple_negative(): y = x[0] SINK_F(y) + # 6.2.1. Identifiers (Names) - - def test_names(): x = SOURCE SINK(x) + # 6.2.2. Literals - - def test_string_literal(): x = "source" SINK(x) @@ -77,16 +75,14 @@ def test_imagnumber_literal(): x = 42j SINK(x) # Flow missing + # 6.2.3. Parenthesized forms - - def test_parenthesized_form(): - x = (SOURCE) + x = SOURCE SINK(x) + # 6.2.5. List displays - - def test_list_display(): x = [SOURCE] SINK(x[0]) @@ -114,12 +110,11 @@ def test_list_comprehension_inflow(): def test_nested_list_display(): - x = [* [SOURCE]] + x = [*[SOURCE]] SINK(x[0]) # Flow missing + # 6.2.6. Set displays - - def test_set_display(): x = {SOURCE} SINK(x.pop()) @@ -142,12 +137,11 @@ def test_set_comprehension_inflow(): def test_nested_set_display(): - x = {* {SOURCE}} + x = {*{SOURCE}} SINK(x.pop()) # Flow missing + # 6.2.7. Dictionary displays - - def test_dict_display(): x = {"s": SOURCE} SINK(x["s"]) @@ -169,17 +163,16 @@ def test_dict_comprehension_pop(): def test_nested_dict_display(): - x = {** {"s": SOURCE}} + x = {**{"s": SOURCE}} SINK(x["s"]) # Flow missing def test_nested_dict_display_pop(): - x = {** {"s": SOURCE}} + x = {**{"s": SOURCE}} SINK(x.pop("s")) # Flow missing + # Nested comprehensions - - def test_nested_comprehension(): x = [y for z in [[SOURCE]] for y in z] SINK(x[0]) @@ -200,16 +193,14 @@ def test_nested_comprehension_paren(): x = [y for y in (z for z in [SOURCE])] SINK(x[0]) + # 6.2.8. Generator expressions - - def test_generator(): x = (SOURCE for y in [NONSOURCE]) SINK([*x][0]) # Flow missing + # 6.2.9. Yield expressions - - def gen(x): yield x @@ -227,16 +218,14 @@ def test_yield_from(): g = gen_from(SOURCE) SINK(next(g)) # Flow missing + # a statement rather than an expression, but related to generators - - def test_for(): for x in gen(SOURCE): SINK(x) # Flow missing + # 6.2.9.1. Generator-iterator methods - - def test___next__(): g = gen(SOURCE) SINK(g.__next__()) # Flow missing @@ -266,21 +255,20 @@ def test_throw(): n = next(g) SINK(g.throw(TypeError)) # Flow missing + # no `test_close` as `close` involves no data flow # 6.2.9.3. Asynchronous generator functions - - async def agen(x): yield x + # 6.2.9.4. Asynchronous generator-iterator methods # helper to run async test functions - - def runa(a): import asyncio + asyncio.run(a) @@ -325,9 +313,8 @@ async def atest_athrow(): def test_athrow(): runa(atest_athrow()) + # 6.3.1. Attribute references - - class C: a = SOURCE @@ -335,11 +322,10 @@ class C: def test_attribute_reference(): SINK(C.a) # Flow missing + # overriding __getattr__ should be tested by the class coverage tests # 6.3.2. Subscriptions - - def test_subscription_tuple(): SINK((SOURCE,)[0]) @@ -351,6 +337,7 @@ def test_subscription_list(): def test_subscription_mapping(): SINK({"s": SOURCE}["s"]) + # overriding __getitem__ should be tested by the class coverage tests @@ -362,11 +349,10 @@ def test_slicing(): s = l[0:1:1] SINK(s[0]) # Flow missing + # The grammar seems to allow `l[0:1:1, 0:1]`, but the interpreter does not like it # 6.3.4. Calls - - def second(a, b): return b @@ -406,79 +392,92 @@ def f_extra_keyword(a, **b): def test_call_extra_keyword(): SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) # Flow missing + # return the name of the first extra keyword argument - - def f_extra_keyword_flow(**a): return [*a][0] + # call the function with our source as the name of the keyword arguemnt - - def test_call_extra_keyword_flow(): SINK(f_extra_keyword_flow(**{SOURCE: None})) # Flow missing + # 6.12. Assignment expressions - - def test_assignment_expression(): x = NONSOURCE SINK(x := SOURCE) # Flow missing + # 6.13. Conditional expressions - - def test_conditional_true(): SINK(SOURCE if True else NONSOURCE) # Flow missing +def test_conditional_true_guards(): + SINK_F(NONSOURCE if True else SOURCE) + + def test_conditional_false(): SINK(NONSOURCE if False else SOURCE) # Flow missing + +def test_conditional_false_guards(): + SINK_F(SOURCE if False else NONSOURCE) + + # Condition is evaluated first, so x is SOURCE once chosen - - def test_conditional_evaluation_true(): x = NONSOURCE SINK(x if (SOURCE == (x := SOURCE)) else NONSOURCE) # Flow missing + # Condition is evaluated first, so x is SOURCE once chosen - - def test_conditional_evaluation_false(): x = NONSOURCE SINK(NONSOURCE if (NONSOURCE == (x := SOURCE)) else x) # Flow missing + # 6.14. Lambdas - - def test_lambda(): - def f(x): return x + def f(x): + return x + SINK(f(SOURCE)) def test_lambda_positional(): - def second(a, b): return b + def second(a, b): + return b + SINK(second(NONSOURCE, SOURCE)) def test_lambda_positional_negative(): - def second(a, b): return b + def second(a, b): + return b + SINK_F(second(SOURCE, NONSOURCE)) def test_lambda_keyword(): - def second(a, b): return b + def second(a, b): + return b + SINK(second(NONSOURCE, b=SOURCE)) # Flow missing def test_lambda_unpack_iterable(): - def second(a, b): return b + def second(a, b): + return b + SINK(second(NONSOURCE, *[SOURCE])) # Flow missing def test_lambda_unpack_mapping(): - def second(a, b): return b + def second(a, b): + return b + SINK(second(NONSOURCE, **{"b": SOURCE})) # Flow missing @@ -491,9 +490,8 @@ def test_lambda_extra_keyword(): f_extra_keyword = lambda a, **b: b["b"] SINK(f_extra_keyword(NONSOURCE, b=SOURCE)) # Flow missing + # call the function with our source as the name of the keyword arguemnt - - def test_lambda_extra_keyword_flow(): # return the name of the first extra keyword argument f_extra_keyword_flow = lambda **a: [*a][0] From 0f077f5d7d483a04e5be899b28ffe521a2941f7f Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 6 Oct 2020 10:54:23 +0200 Subject: [PATCH 233/411] Python: Add flow inside `IfExprNode`s --- .../dataflow/internal/DataFlowPrivate.qll | 3 +++ .../experimental/dataflow/coverage/dataflow.expected | 12 ++++++++++++ .../ql/test/experimental/dataflow/coverage/test.py | 4 ++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll b/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll index fcc98e9d8ce..79bdfdced52 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll @@ -170,6 +170,9 @@ module EssaFlow { nodeTo.(EssaNode).getVar() = p.getVariable() and nodeFrom.(EssaNode).getVar() = p.getAnInput() ) + or + // If expressions + nodeFrom.asCfgNode() = nodeTo.asCfgNode().(IfExprNode).getAnOperand() } predicate useToNextUse(NameNode nodeFrom, NameNode nodeTo) { diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index b1cb5f0f077..4e558bd1247 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -48,6 +48,8 @@ edges | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:334:11:334:16 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:338:16:338:21 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:361:28:361:33 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:414:10:414:15 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:422:34:422:39 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:446:12:446:17 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:453:28:453:33 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:502:9:502:14 | ControlFlowNode for SOURCE | @@ -147,6 +149,8 @@ edges | test.py:338:10:338:22 | ControlFlowNode for Dict [Dictionary element at key s] | test.py:338:10:338:27 | ControlFlowNode for Subscript | | test.py:338:16:338:21 | ControlFlowNode for SOURCE | test.py:338:10:338:22 | ControlFlowNode for Dict [Dictionary element at key s] | | test.py:361:28:361:33 | ControlFlowNode for SOURCE | test.py:361:10:361:34 | ControlFlowNode for second() | +| test.py:414:10:414:15 | ControlFlowNode for SOURCE | test.py:414:10:414:38 | ControlFlowNode for IfExp | +| test.py:422:34:422:39 | ControlFlowNode for SOURCE | test.py:422:10:422:39 | ControlFlowNode for IfExp | | test.py:446:12:446:17 | ControlFlowNode for SOURCE | test.py:446:10:446:18 | ControlFlowNode for f() | | test.py:453:28:453:33 | ControlFlowNode for SOURCE | test.py:453:10:453:34 | ControlFlowNode for second() | | test.py:502:9:502:14 | ControlFlowNode for SOURCE | test.py:504:10:504:10 | ControlFlowNode for a | @@ -292,6 +296,10 @@ nodes | test.py:338:16:338:21 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:361:10:361:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | | test.py:361:28:361:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:414:10:414:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:414:10:414:38 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | +| test.py:422:10:422:39 | ControlFlowNode for IfExp | semmle.label | ControlFlowNode for IfExp | +| test.py:422:34:422:39 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:446:10:446:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | | test.py:446:12:446:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:453:10:453:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | @@ -368,6 +376,10 @@ nodes | test.py:338:10:338:27 | ControlFlowNode for Subscript | test.py:338:16:338:21 | ControlFlowNode for SOURCE | test.py:338:10:338:27 | ControlFlowNode for Subscript | Flow found | | test.py:361:10:361:34 | ControlFlowNode for second() | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:361:10:361:34 | ControlFlowNode for second() | Flow found | | test.py:361:10:361:34 | ControlFlowNode for second() | test.py:361:28:361:33 | ControlFlowNode for SOURCE | test.py:361:10:361:34 | ControlFlowNode for second() | Flow found | +| test.py:414:10:414:38 | ControlFlowNode for IfExp | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:414:10:414:38 | ControlFlowNode for IfExp | Flow found | +| test.py:414:10:414:38 | ControlFlowNode for IfExp | test.py:414:10:414:15 | ControlFlowNode for SOURCE | test.py:414:10:414:38 | ControlFlowNode for IfExp | Flow found | +| test.py:422:10:422:39 | ControlFlowNode for IfExp | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:422:10:422:39 | ControlFlowNode for IfExp | Flow found | +| test.py:422:10:422:39 | ControlFlowNode for IfExp | test.py:422:34:422:39 | ControlFlowNode for SOURCE | test.py:422:10:422:39 | ControlFlowNode for IfExp | Flow found | | test.py:446:10:446:18 | ControlFlowNode for f() | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:446:10:446:18 | ControlFlowNode for f() | Flow found | | test.py:446:10:446:18 | ControlFlowNode for f() | test.py:446:12:446:17 | ControlFlowNode for SOURCE | test.py:446:10:446:18 | ControlFlowNode for f() | Flow found | | test.py:453:10:453:34 | ControlFlowNode for second() | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:453:10:453:34 | ControlFlowNode for second() | Flow found | diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 383b31e3c3b..744082b84e2 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -411,7 +411,7 @@ def test_assignment_expression(): # 6.13. Conditional expressions def test_conditional_true(): - SINK(SOURCE if True else NONSOURCE) # Flow missing + SINK(SOURCE if True else NONSOURCE) def test_conditional_true_guards(): @@ -419,7 +419,7 @@ def test_conditional_true_guards(): def test_conditional_false(): - SINK(NONSOURCE if False else SOURCE) # Flow missing + SINK(NONSOURCE if False else SOURCE) def test_conditional_false_guards(): From 16bad003a013e19b521ad0ef74be59d72657d5c4 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 6 Oct 2020 10:58:46 +0200 Subject: [PATCH 234/411] Python: Add test for routed params with unknown url pattern --- .../library-tests/frameworks/flask/routing_test.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py index 7cd45e4f8e9..b546cc263eb 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py @@ -23,5 +23,10 @@ app.add_url_rule('/later-set', 'later_set', view_func=None) # $routeSetup="/lat app.view_functions['later_set'] = later_set +@app.route(UNKNOWN_ROUTE) # $routeSetup +def unkown_route(foo, bar): # $routeHandler + return make_response("unkown_route") + + if __name__ == "__main__": app.run(debug=True) From c31cdaacb22ebd00a63728ee183743416c552844 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 6 Oct 2020 10:01:04 +0100 Subject: [PATCH 235/411] JS: Add test for getFieldTypeAnnotation --- .../library-tests/ClassNode/InstanceMember.expected | 2 +- .../library-tests/ClassNode/InstanceMethod.expected | 2 +- .../test/library-tests/ClassNode/SuperClass.expected | 1 + javascript/ql/test/library-tests/ClassNode/fields.ts | 12 +++++++++++- .../ClassNode/getAReceiverNode.expected | 3 ++- .../ClassNode/getFieldTypeAnnotation.expected | 4 ++++ .../ClassNode/getFieldTypeAnnotation.ql | 4 ++++ 7 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 javascript/ql/test/library-tests/ClassNode/getFieldTypeAnnotation.expected create mode 100644 javascript/ql/test/library-tests/ClassNode/getFieldTypeAnnotation.ql diff --git a/javascript/ql/test/library-tests/ClassNode/InstanceMember.expected b/javascript/ql/test/library-tests/ClassNode/InstanceMember.expected index a6faded04a4..b3dce399092 100644 --- a/javascript/ql/test/library-tests/ClassNode/InstanceMember.expected +++ b/javascript/ql/test/library-tests/ClassNode/InstanceMember.expected @@ -1,4 +1,4 @@ -| fields.ts:2:16:2:32 | (x: string) => {} | Foo.m | method | +| fields.ts:12:16:12:32 | (x: string) => {} | Foo.m | method | | namespace.js:5:32:5:44 | function() {} | Baz.method | method | | tst2.js:6:9:9:3 | () {\\n ... .x;\\n } | C.method | method | | tst2.js:11:13:13:3 | () {\\n ... .x;\\n } | C.getter | getter | diff --git a/javascript/ql/test/library-tests/ClassNode/InstanceMethod.expected b/javascript/ql/test/library-tests/ClassNode/InstanceMethod.expected index c5b94a35a3c..380aae4d275 100644 --- a/javascript/ql/test/library-tests/ClassNode/InstanceMethod.expected +++ b/javascript/ql/test/library-tests/ClassNode/InstanceMethod.expected @@ -1,4 +1,4 @@ -| fields.ts:2:16:2:32 | (x: string) => {} | Foo.m | +| fields.ts:12:16:12:32 | (x: string) => {} | Foo.m | | namespace.js:5:32:5:44 | function() {} | Baz.method | | tst2.js:6:9:9:3 | () {\\n ... .x;\\n } | C.method | | tst2.js:18:14:18:22 | (x) => {} | D.f | diff --git a/javascript/ql/test/library-tests/ClassNode/SuperClass.expected b/javascript/ql/test/library-tests/ClassNode/SuperClass.expected index bb35f1ee711..553cd258c79 100644 --- a/javascript/ql/test/library-tests/ClassNode/SuperClass.expected +++ b/javascript/ql/test/library-tests/ClassNode/SuperClass.expected @@ -1,3 +1,4 @@ +| fields.ts:5:1:13:1 | class F ... > {};\\n} | Foo | fields.ts:1:1:3:1 | class B ... mber;\\n} | Base | | tst.js:13:1:13:21 | class A ... ds A {} | A2 | tst.js:3:1:10:1 | class A ... () {}\\n} | A | | tst.js:15:1:15:15 | function B() {} | B | tst.js:3:1:10:1 | class A ... () {}\\n} | A | | tst.js:19:1:19:15 | function C() {} | C | tst.js:15:1:15:15 | function B() {} | B | diff --git a/javascript/ql/test/library-tests/ClassNode/fields.ts b/javascript/ql/test/library-tests/ClassNode/fields.ts index f288a47bb4d..8a9a8bc98d2 100644 --- a/javascript/ql/test/library-tests/ClassNode/fields.ts +++ b/javascript/ql/test/library-tests/ClassNode/fields.ts @@ -1,3 +1,13 @@ -class Foo { +class Base { + baseField: number; +} + +class Foo extends Base { + constructor(public x: number, private y: string) { + super(); + } + + z: string[]; + public m = (x: string) => {}; } diff --git a/javascript/ql/test/library-tests/ClassNode/getAReceiverNode.expected b/javascript/ql/test/library-tests/ClassNode/getAReceiverNode.expected index f8f057d646f..08a9be0aadf 100644 --- a/javascript/ql/test/library-tests/ClassNode/getAReceiverNode.expected +++ b/javascript/ql/test/library-tests/ClassNode/getAReceiverNode.expected @@ -1,4 +1,5 @@ -| fields.ts:1:1:3:1 | class F ... > {};\\n} | fields.ts:1:11:1:10 | this | +| fields.ts:1:1:3:1 | class B ... mber;\\n} | fields.ts:1:12:1:11 | this | +| fields.ts:5:1:13:1 | class F ... > {};\\n} | fields.ts:6:5:6:4 | this | | namespace.js:3:15:3:31 | function Baz() {} | namespace.js:3:15:3:14 | this | | namespace.js:3:15:3:31 | function Baz() {} | namespace.js:5:32:5:31 | this | | tst2.js:1:1:14:1 | class C ... ;\\n }\\n} | tst2.js:2:14:2:13 | this | diff --git a/javascript/ql/test/library-tests/ClassNode/getFieldTypeAnnotation.expected b/javascript/ql/test/library-tests/ClassNode/getFieldTypeAnnotation.expected new file mode 100644 index 00000000000..8ce69dfe3b4 --- /dev/null +++ b/javascript/ql/test/library-tests/ClassNode/getFieldTypeAnnotation.expected @@ -0,0 +1,4 @@ +| fields.ts:1:1:3:1 | class B ... mber;\\n} | baseField | fields.ts:2:16:2:21 | number | +| fields.ts:5:1:13:1 | class F ... > {};\\n} | x | fields.ts:6:27:6:32 | number | +| fields.ts:5:1:13:1 | class F ... > {};\\n} | y | fields.ts:6:46:6:51 | string | +| fields.ts:5:1:13:1 | class F ... > {};\\n} | z | fields.ts:10:8:10:15 | string[] | diff --git a/javascript/ql/test/library-tests/ClassNode/getFieldTypeAnnotation.ql b/javascript/ql/test/library-tests/ClassNode/getFieldTypeAnnotation.ql new file mode 100644 index 00000000000..a8f37f9549d --- /dev/null +++ b/javascript/ql/test/library-tests/ClassNode/getFieldTypeAnnotation.ql @@ -0,0 +1,4 @@ +import javascript + +from DataFlow::ClassNode cls, string name +select cls, name, cls.getFieldTypeAnnotation(name) From a962a8a3bdb2a50db21345e06db634ff531d2c16 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 6 Oct 2020 10:01:36 +0100 Subject: [PATCH 236/411] JS: Autoformat --- .../ql/src/semmle/javascript/dataflow/Configuration.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll index 337054a918a..ebed20e5214 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll @@ -426,7 +426,9 @@ private predicate barrierGuardBlocksSsaRefinement( * `outcome` is bound to the outcome of `cond` for join-ordering purposes. */ pragma[noinline] -private predicate barrierGuardUsedInCondition(BarrierGuardNode guard, ConditionGuardNode cond, boolean outcome) { +private predicate barrierGuardUsedInCondition( + BarrierGuardNode guard, ConditionGuardNode cond, boolean outcome +) { barrierGuardIsRelevant(guard) and outcome = cond.getOutcome() and ( From b82727d0b8b2a3ddaa58380d0d1c396adea16b07 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 6 Oct 2020 11:03:25 +0200 Subject: [PATCH 237/411] Python: Consider routed parameter if URL pattern unknown --- .../ql/src/experimental/semmle/python/frameworks/Flask.qll | 6 ++++++ .../library-tests/frameworks/flask/routing_test.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Flask.qll b/python/ql/src/experimental/semmle/python/frameworks/Flask.qll index 549d4305419..48fd345572e 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Flask.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Flask.qll @@ -117,6 +117,12 @@ private module Flask { /** A route setup made by flask (sharing handling of URL patterns). */ abstract private class FlaskRouteSetup extends HTTP::Server::RouteSetup::Range { override Parameter getARoutedParameter() { + // If we don't know the URL pattern, we simply mark all parameters as a routed + // parameter. This should give us more RemoteFlowSources but could also lead to + // more FPs. If this turns out to be the wrong tradeoff, we can always change our mind. + not exists(this.getUrlPattern()) and + result = this.getARouteHandler().getArgByName(_) + or exists(string name | result = this.getARouteHandler().getArgByName(name) and exists(string match | diff --git a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py index b546cc263eb..7af50f613f2 100644 --- a/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py +++ b/python/ql/test/experimental/library-tests/frameworks/flask/routing_test.py @@ -24,7 +24,7 @@ app.view_functions['later_set'] = later_set @app.route(UNKNOWN_ROUTE) # $routeSetup -def unkown_route(foo, bar): # $routeHandler +def unkown_route(foo, bar): # $routeHandler $routedParameter=foo $routedParameter=bar return make_response("unkown_route") From d26a89b95e105939ed20c1ef78da90e280398bd3 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 6 Oct 2020 11:35:18 +0200 Subject: [PATCH 238/411] Python: Fix QLDoc for RouteSetup --- python/ql/src/experimental/semmle/python/Concepts.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index 454d5d4505d..49e8593fc8d 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -47,7 +47,7 @@ module HTTP { /** * An data-flow node that sets up a route on a server. * - * Extend this class to model new APIs. If you want to model new APIs, + * Extend this class to refine existing API models. If you want to model new APIs, * extend `RouteSetup::Range` instead. */ class RouteSetup extends DataFlow::Node { From 36ddbcdd7171f54ec5a6182bdc47b582df22b2b4 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 6 Oct 2020 11:41:48 +0200 Subject: [PATCH 239/411] C#: Reenable disabled test on OSX --- csharp/extractor/Semmle.Extraction.Tests/Layout.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.Tests/Layout.cs b/csharp/extractor/Semmle.Extraction.Tests/Layout.cs index a5f36f0c19d..4d0aec60bec 100644 --- a/csharp/extractor/Semmle.Extraction.Tests/Layout.cs +++ b/csharp/extractor/Semmle.Extraction.Tests/Layout.cs @@ -45,10 +45,14 @@ namespace Semmle.Extraction.Tests Directory.SetCurrentDirectory(tmpDir); if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { - // `Directory.SetCurrentDirectory()` doesn't seem to work on macOS, - // so disable this test on macOS, for now + // `Directory.SetCurrentDirectory()` seems to slightly change the path on macOS, + // so adjusting it: Assert.NotEqual(Directory.GetCurrentDirectory(), tmpDir); - return; + tmpDir = "/private" + tmpDir; + // Remove trailing slash: + Assert.Equal('/', tmpDir[tmpDir.Length - 1]); + tmpDir = tmpDir.Substring(0, tmpDir.Length - 1); + Assert.Equal(Directory.GetCurrentDirectory(), tmpDir); } var f1 = project!.GetTrapPath(Logger, new TransformedPathStub("foo.cs"), TrapWriter.CompressionMode.Gzip); var g1 = TrapWriter.NestPaths(Logger, tmpDir, "foo.cs.trap.gz"); From e15758ba7f645c4ec841bab32c130478198aaa8a Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 6 Oct 2020 11:42:11 +0200 Subject: [PATCH 240/411] C#: Add test for named tuple types --- .../ql/test/library-tests/csharp7/CSharp7.cs | 11 +- .../csharp7/CaseCondition.expected | 6 +- .../ConstructedLocalFunctions.expected | 8 +- .../library-tests/csharp7/DefUse.expected | 88 +-- .../library-tests/csharp7/Discards.expected | 16 +- .../csharp7/ExpressionBodies.expected | 14 +- .../library-tests/csharp7/ForEach.expected | 12 +- .../library-tests/csharp7/GlobalFlow.expected | 6 +- .../csharp7/GlobalTaintTracking.expected | 8 +- .../library-tests/csharp7/IsFlow.expected | 146 ++-- .../library-tests/csharp7/IsPatterns.expected | 10 +- .../LocalFunctionCallArguments.expected | 20 +- .../csharp7/LocalFunctionCalls.expected | 20 +- .../csharp7/LocalFunctionParameters.expected | 28 +- .../csharp7/LocalFunctionStmts.expected | 18 +- .../csharp7/LocalFunctions.expected | 38 +- .../csharp7/LocalTaintFlow.expected | 234 +++--- .../csharp7/LocalVariables.expected | 64 +- .../library-tests/csharp7/PrintAst.expected | 722 +++++++++--------- .../csharp7/RefDelegates.expected | 2 +- .../library-tests/csharp7/RefExprs.expected | 12 +- .../csharp7/RefFunctions.expected | 4 +- .../csharp7/RefVariables.expected | 8 +- .../csharp7/TaintReaches.expected | 22 +- .../csharp7/TupleAccess.expected | 16 +- .../library-tests/csharp7/TupleExpr.expected | 36 +- .../library-tests/csharp7/TupleTypes.expected | 24 +- .../library-tests/csharp7/TypeCase1.expected | 18 +- .../library-tests/csharp7/TypeCase2.expected | 8 +- .../library-tests/csharp7/TypeCase3.expected | 2 +- .../csharp7/UnboundLocalFunctions.expected | 10 +- 31 files changed, 816 insertions(+), 815 deletions(-) diff --git a/csharp/ql/test/library-tests/csharp7/CSharp7.cs b/csharp/ql/test/library-tests/csharp7/CSharp7.cs index 0b42403f6c0..0339ccc8728 100644 --- a/csharp/ql/test/library-tests/csharp7/CSharp7.cs +++ b/csharp/ql/test/library-tests/csharp7/CSharp7.cs @@ -61,9 +61,9 @@ class OutVariables class Tuples { - (int, int) F() + (int A, int B) F() { - return (1, 2); + return (A: 1, B: 2); } void Expressions() @@ -71,7 +71,7 @@ class Tuples (var x, var y) = F(); var z = F(); (x, y) = F(); - x = F().Item1; + x = F().A; (x, y, z.Item1) = (1, 2, 3); (x, y) = (x, y) = (1, 2); (var a, (var b, var c)) = (1, z); @@ -148,7 +148,8 @@ class LocalFunctions return f9(1); } - Action a = () => { + Action a = () => + { int f9() => 0; }; @@ -295,7 +296,7 @@ class ForLoops { void Test() { - for(int x=0; x<10 && x is int y; ++x) + for (int x = 0; x < 10 && x is int y; ++x) { Console.WriteLine(y); } diff --git a/csharp/ql/test/library-tests/csharp7/CaseCondition.expected b/csharp/ql/test/library-tests/csharp7/CaseCondition.expected index 67bff16713d..f538575183e 100644 --- a/csharp/ql/test/library-tests/csharp7/CaseCondition.expected +++ b/csharp/ql/test/library-tests/csharp7/CaseCondition.expected @@ -1,3 +1,3 @@ -| CSharp7.cs:253:13:253:31 | case ...: | CSharp7.cs:253:26:253:30 | ... < ... | -| CSharp7.cs:255:13:255:41 | case ...: | CSharp7.cs:255:27:255:40 | ... is ... | -| CSharp7.cs:258:13:258:36 | case ...: | CSharp7.cs:258:30:258:35 | ... > ... | +| CSharp7.cs:254:13:254:31 | case ...: | CSharp7.cs:254:26:254:30 | ... < ... | +| CSharp7.cs:256:13:256:41 | case ...: | CSharp7.cs:256:27:256:40 | ... is ... | +| CSharp7.cs:259:13:259:36 | case ...: | CSharp7.cs:259:30:259:35 | ... > ... | diff --git a/csharp/ql/test/library-tests/csharp7/ConstructedLocalFunctions.expected b/csharp/ql/test/library-tests/csharp7/ConstructedLocalFunctions.expected index 0b67eaba5df..a945d262198 100644 --- a/csharp/ql/test/library-tests/csharp7/ConstructedLocalFunctions.expected +++ b/csharp/ql/test/library-tests/csharp7/ConstructedLocalFunctions.expected @@ -1,4 +1,4 @@ -| CSharp7.cs:160:9:160:24 | f | f() | f() | -| CSharp7.cs:161:9:161:25 | g | g(U) | g(T) | -| CSharp7.cs:163:9:168:9 | h | h(int, int) | h(T, U) | -| CSharp7.cs:163:9:168:9 | h | h(string, bool) | h(T, U) | +| CSharp7.cs:161:9:161:24 | f | f() | f() | +| CSharp7.cs:162:9:162:25 | g | g(U) | g(T) | +| CSharp7.cs:164:9:169:9 | h | h(int, int) | h(T, U) | +| CSharp7.cs:164:9:169:9 | h | h(string, bool) | h(T, U) | diff --git a/csharp/ql/test/library-tests/csharp7/DefUse.expected b/csharp/ql/test/library-tests/csharp7/DefUse.expected index 93bdff568c2..62cc5ea4b1b 100644 --- a/csharp/ql/test/library-tests/csharp7/DefUse.expected +++ b/csharp/ql/test/library-tests/csharp7/DefUse.expected @@ -29,47 +29,47 @@ | CSharp7.cs:141:20:141:20 | x | CSharp7.cs:141:41:141:41 | access to parameter x | | CSharp7.cs:143:20:143:20 | x | CSharp7.cs:143:29:143:29 | access to parameter x | | CSharp7.cs:147:24:147:24 | x | CSharp7.cs:147:33:147:33 | access to parameter x | -| CSharp7.cs:161:18:161:18 | t | CSharp7.cs:161:24:161:24 | access to parameter t | -| CSharp7.cs:163:26:163:26 | u | CSharp7.cs:167:22:167:22 | access to parameter u | -| CSharp7.cs:176:16:176:30 | String src = ... | CSharp7.cs:181:23:181:25 | access to local variable src | -| CSharp7.cs:176:16:176:30 | String src = ... | CSharp7.cs:182:23:182:25 | access to local variable src | -| CSharp7.cs:176:16:176:30 | String src = ... | CSharp7.cs:183:23:183:25 | access to local variable src | -| CSharp7.cs:177:25:177:25 | s | CSharp7.cs:177:33:177:33 | access to parameter s | -| CSharp7.cs:178:25:178:25 | s | CSharp7.cs:178:31:178:31 | access to parameter s | -| CSharp7.cs:179:25:179:25 | s | CSharp7.cs:179:37:179:37 | access to parameter s | -| CSharp7.cs:191:13:191:18 | Int32 v1 = ... | CSharp7.cs:192:26:192:27 | access to local variable v1 | -| CSharp7.cs:191:13:191:18 | Int32 v1 = ... | CSharp7.cs:198:21:198:22 | access to local variable v1 | -| CSharp7.cs:193:13:193:31 | Int32[] array = ... | CSharp7.cs:195:14:195:18 | access to local variable array | -| CSharp7.cs:193:13:193:31 | Int32[] array = ... | CSharp7.cs:196:26:196:30 | access to local variable array | -| CSharp7.cs:195:9:195:21 | ... = ... | CSharp7.cs:197:26:197:27 | access to local variable r1 | -| CSharp7.cs:195:9:195:21 | ... = ... | CSharp7.cs:199:33:199:34 | access to local variable r1 | -| CSharp7.cs:195:9:195:21 | ... = ... | CSharp7.cs:200:16:200:17 | access to local variable r1 | -| CSharp7.cs:203:24:203:24 | p | CSharp7.cs:206:20:206:20 | access to parameter p | -| CSharp7.cs:205:28:205:28 | q | CSharp7.cs:205:44:205:44 | access to parameter q | -| CSharp7.cs:233:16:233:23 | Object o = ... | CSharp7.cs:234:13:234:13 | access to local variable o | -| CSharp7.cs:233:16:233:23 | Object o = ... | CSharp7.cs:238:18:238:18 | access to local variable o | -| CSharp7.cs:233:16:233:23 | Object o = ... | CSharp7.cs:242:18:242:18 | access to local variable o | -| CSharp7.cs:233:16:233:23 | Object o = ... | CSharp7.cs:245:18:245:18 | access to local variable o | -| CSharp7.cs:233:16:233:23 | Object o = ... | CSharp7.cs:249:17:249:17 | access to local variable o | -| CSharp7.cs:233:16:233:23 | Object o = ... | CSharp7.cs:255:27:255:27 | access to local variable o | -| CSharp7.cs:234:18:234:23 | Int32 i1 | CSharp7.cs:234:28:234:29 | access to local variable i1 | -| CSharp7.cs:234:18:234:23 | Int32 i1 | CSharp7.cs:236:38:236:39 | access to local variable i1 | -| CSharp7.cs:238:23:238:31 | String s1 | CSharp7.cs:240:41:240:42 | access to local variable s1 | -| CSharp7.cs:255:32:255:40 | String s4 | CSharp7.cs:256:40:256:41 | access to local variable s4 | -| CSharp7.cs:258:18:258:23 | Int32 i2 | CSharp7.cs:258:30:258:31 | access to local variable i2 | -| CSharp7.cs:258:18:258:23 | Int32 i2 | CSharp7.cs:259:47:259:48 | access to local variable i2 | -| CSharp7.cs:261:18:261:23 | Int32 i3 | CSharp7.cs:262:42:262:43 | access to local variable i3 | -| CSharp7.cs:264:18:264:26 | String s2 | CSharp7.cs:265:45:265:46 | access to local variable s2 | -| CSharp7.cs:283:13:283:48 | Dictionary dict = ... | CSharp7.cs:284:20:284:23 | access to local variable dict | -| CSharp7.cs:284:13:284:62 | IEnumerable<(Int32,String)> list = ... | CSharp7.cs:286:39:286:42 | access to local variable list | -| CSharp7.cs:284:13:284:62 | IEnumerable<(Int32,String)> list = ... | CSharp7.cs:288:36:288:39 | access to local variable list | -| CSharp7.cs:284:13:284:62 | IEnumerable<(Int32,String)> list = ... | CSharp7.cs:290:32:290:35 | access to local variable list | -| CSharp7.cs:284:32:284:35 | item | CSharp7.cs:284:41:284:44 | access to parameter item | -| CSharp7.cs:284:32:284:35 | item | CSharp7.cs:284:51:284:54 | access to parameter item | -| CSharp7.cs:298:17:298:19 | Int32 x = ... | CSharp7.cs:298:22:298:22 | access to local variable x | -| CSharp7.cs:298:17:298:19 | Int32 x = ... | CSharp7.cs:298:30:298:30 | access to local variable x | -| CSharp7.cs:298:17:298:19 | Int32 x = ... | CSharp7.cs:298:44:298:44 | access to local variable x | -| CSharp7.cs:298:35:298:39 | Int32 y | CSharp7.cs:300:31:300:31 | access to local variable y | -| CSharp7.cs:298:42:298:44 | ++... | CSharp7.cs:298:22:298:22 | access to local variable x | -| CSharp7.cs:298:42:298:44 | ++... | CSharp7.cs:298:30:298:30 | access to local variable x | -| CSharp7.cs:298:42:298:44 | ++... | CSharp7.cs:298:44:298:44 | access to local variable x | +| CSharp7.cs:162:18:162:18 | t | CSharp7.cs:162:24:162:24 | access to parameter t | +| CSharp7.cs:164:26:164:26 | u | CSharp7.cs:168:22:168:22 | access to parameter u | +| CSharp7.cs:177:16:177:30 | String src = ... | CSharp7.cs:182:23:182:25 | access to local variable src | +| CSharp7.cs:177:16:177:30 | String src = ... | CSharp7.cs:183:23:183:25 | access to local variable src | +| CSharp7.cs:177:16:177:30 | String src = ... | CSharp7.cs:184:23:184:25 | access to local variable src | +| CSharp7.cs:178:25:178:25 | s | CSharp7.cs:178:33:178:33 | access to parameter s | +| CSharp7.cs:179:25:179:25 | s | CSharp7.cs:179:31:179:31 | access to parameter s | +| CSharp7.cs:180:25:180:25 | s | CSharp7.cs:180:37:180:37 | access to parameter s | +| CSharp7.cs:192:13:192:18 | Int32 v1 = ... | CSharp7.cs:193:26:193:27 | access to local variable v1 | +| CSharp7.cs:192:13:192:18 | Int32 v1 = ... | CSharp7.cs:199:21:199:22 | access to local variable v1 | +| CSharp7.cs:194:13:194:31 | Int32[] array = ... | CSharp7.cs:196:14:196:18 | access to local variable array | +| CSharp7.cs:194:13:194:31 | Int32[] array = ... | CSharp7.cs:197:26:197:30 | access to local variable array | +| CSharp7.cs:196:9:196:21 | ... = ... | CSharp7.cs:198:26:198:27 | access to local variable r1 | +| CSharp7.cs:196:9:196:21 | ... = ... | CSharp7.cs:200:33:200:34 | access to local variable r1 | +| CSharp7.cs:196:9:196:21 | ... = ... | CSharp7.cs:201:16:201:17 | access to local variable r1 | +| CSharp7.cs:204:24:204:24 | p | CSharp7.cs:207:20:207:20 | access to parameter p | +| CSharp7.cs:206:28:206:28 | q | CSharp7.cs:206:44:206:44 | access to parameter q | +| CSharp7.cs:234:16:234:23 | Object o = ... | CSharp7.cs:235:13:235:13 | access to local variable o | +| CSharp7.cs:234:16:234:23 | Object o = ... | CSharp7.cs:239:18:239:18 | access to local variable o | +| CSharp7.cs:234:16:234:23 | Object o = ... | CSharp7.cs:243:18:243:18 | access to local variable o | +| CSharp7.cs:234:16:234:23 | Object o = ... | CSharp7.cs:246:18:246:18 | access to local variable o | +| CSharp7.cs:234:16:234:23 | Object o = ... | CSharp7.cs:250:17:250:17 | access to local variable o | +| CSharp7.cs:234:16:234:23 | Object o = ... | CSharp7.cs:256:27:256:27 | access to local variable o | +| CSharp7.cs:235:18:235:23 | Int32 i1 | CSharp7.cs:235:28:235:29 | access to local variable i1 | +| CSharp7.cs:235:18:235:23 | Int32 i1 | CSharp7.cs:237:38:237:39 | access to local variable i1 | +| CSharp7.cs:239:23:239:31 | String s1 | CSharp7.cs:241:41:241:42 | access to local variable s1 | +| CSharp7.cs:256:32:256:40 | String s4 | CSharp7.cs:257:40:257:41 | access to local variable s4 | +| CSharp7.cs:259:18:259:23 | Int32 i2 | CSharp7.cs:259:30:259:31 | access to local variable i2 | +| CSharp7.cs:259:18:259:23 | Int32 i2 | CSharp7.cs:260:47:260:48 | access to local variable i2 | +| CSharp7.cs:262:18:262:23 | Int32 i3 | CSharp7.cs:263:42:263:43 | access to local variable i3 | +| CSharp7.cs:265:18:265:26 | String s2 | CSharp7.cs:266:45:266:46 | access to local variable s2 | +| CSharp7.cs:284:13:284:48 | Dictionary dict = ... | CSharp7.cs:285:20:285:23 | access to local variable dict | +| CSharp7.cs:285:13:285:62 | IEnumerable<(Int32,String)> list = ... | CSharp7.cs:287:39:287:42 | access to local variable list | +| CSharp7.cs:285:13:285:62 | IEnumerable<(Int32,String)> list = ... | CSharp7.cs:289:36:289:39 | access to local variable list | +| CSharp7.cs:285:13:285:62 | IEnumerable<(Int32,String)> list = ... | CSharp7.cs:291:32:291:35 | access to local variable list | +| CSharp7.cs:285:32:285:35 | item | CSharp7.cs:285:41:285:44 | access to parameter item | +| CSharp7.cs:285:32:285:35 | item | CSharp7.cs:285:51:285:54 | access to parameter item | +| CSharp7.cs:299:18:299:22 | Int32 x = ... | CSharp7.cs:299:25:299:25 | access to local variable x | +| CSharp7.cs:299:18:299:22 | Int32 x = ... | CSharp7.cs:299:35:299:35 | access to local variable x | +| CSharp7.cs:299:18:299:22 | Int32 x = ... | CSharp7.cs:299:49:299:49 | access to local variable x | +| CSharp7.cs:299:40:299:44 | Int32 y | CSharp7.cs:301:31:301:31 | access to local variable y | +| CSharp7.cs:299:47:299:49 | ++... | CSharp7.cs:299:25:299:25 | access to local variable x | +| CSharp7.cs:299:47:299:49 | ++... | CSharp7.cs:299:35:299:35 | access to local variable x | +| CSharp7.cs:299:47:299:49 | ++... | CSharp7.cs:299:49:299:49 | access to local variable x | diff --git a/csharp/ql/test/library-tests/csharp7/Discards.expected b/csharp/ql/test/library-tests/csharp7/Discards.expected index 41f6e47ac17..0fffde7c1c0 100644 --- a/csharp/ql/test/library-tests/csharp7/Discards.expected +++ b/csharp/ql/test/library-tests/csharp7/Discards.expected @@ -1,8 +1,8 @@ -| CSharp7.cs:222:9:222:9 | _ | (Int32,Double) | -| CSharp7.cs:222:19:222:19 | _ | Boolean | -| CSharp7.cs:223:10:223:10 | _ | Int32 | -| CSharp7.cs:223:13:223:13 | _ | Double | -| CSharp7.cs:223:24:223:24 | _ | Boolean | -| CSharp7.cs:224:17:224:17 | _ | Double | -| CSharp7.cs:224:28:224:28 | _ | Boolean | -| CSharp7.cs:225:10:225:10 | _ | Int32 | +| CSharp7.cs:223:9:223:9 | _ | (Int32,Double) | +| CSharp7.cs:223:19:223:19 | _ | Boolean | +| CSharp7.cs:224:10:224:10 | _ | Int32 | +| CSharp7.cs:224:13:224:13 | _ | Double | +| CSharp7.cs:224:24:224:24 | _ | Boolean | +| CSharp7.cs:225:17:225:17 | _ | Double | +| CSharp7.cs:225:28:225:28 | _ | Boolean | +| CSharp7.cs:226:10:226:10 | _ | Int32 | diff --git a/csharp/ql/test/library-tests/csharp7/ExpressionBodies.expected b/csharp/ql/test/library-tests/csharp7/ExpressionBodies.expected index b7dd392b22a..5a09ce22d43 100644 --- a/csharp/ql/test/library-tests/csharp7/ExpressionBodies.expected +++ b/csharp/ql/test/library-tests/csharp7/ExpressionBodies.expected @@ -9,10 +9,10 @@ | CSharp7.cs:141:9:141:51 | f6 | CSharp7.cs:141:26:141:50 | ... ? ... : ... | | CSharp7.cs:143:9:143:31 | f7 | CSharp7.cs:143:26:143:30 | call to local function f6 | | CSharp7.cs:147:13:147:35 | f9 | CSharp7.cs:147:30:147:34 | call to local function f7 | -| CSharp7.cs:152:13:152:26 | f9 | CSharp7.cs:152:25:152:25 | 0 | -| CSharp7.cs:160:9:160:24 | f | CSharp7.cs:160:23:160:23 | 1 | -| CSharp7.cs:161:9:161:25 | g | CSharp7.cs:161:24:161:24 | access to parameter t | -| CSharp7.cs:165:13:165:43 | f2 | CSharp7.cs:165:37:165:42 | call to local function f | -| CSharp7.cs:177:9:177:40 | f | CSharp7.cs:177:31:177:39 | ... + ... | -| CSharp7.cs:178:9:178:32 | g | CSharp7.cs:178:31:178:31 | access to parameter s | -| CSharp7.cs:284:32:284:61 | (...) => ... | CSharp7.cs:284:40:284:61 | (..., ...) | +| CSharp7.cs:153:13:153:26 | f9 | CSharp7.cs:153:25:153:25 | 0 | +| CSharp7.cs:161:9:161:24 | f | CSharp7.cs:161:23:161:23 | 1 | +| CSharp7.cs:162:9:162:25 | g | CSharp7.cs:162:24:162:24 | access to parameter t | +| CSharp7.cs:166:13:166:43 | f2 | CSharp7.cs:166:37:166:42 | call to local function f | +| CSharp7.cs:178:9:178:40 | f | CSharp7.cs:178:31:178:39 | ... + ... | +| CSharp7.cs:179:9:179:32 | g | CSharp7.cs:179:31:179:31 | access to parameter s | +| CSharp7.cs:285:32:285:61 | (...) => ... | CSharp7.cs:285:40:285:61 | (..., ...) | diff --git a/csharp/ql/test/library-tests/csharp7/ForEach.expected b/csharp/ql/test/library-tests/csharp7/ForEach.expected index 71f3d7cb0ae..d0699faabf0 100644 --- a/csharp/ql/test/library-tests/csharp7/ForEach.expected +++ b/csharp/ql/test/library-tests/csharp7/ForEach.expected @@ -1,6 +1,6 @@ -| CSharp7.cs:286:9:286:47 | foreach (... ... in ...) ... | 0 | CSharp7.cs:286:23:286:23 | Int32 a | CSharp7.cs:286:23:286:23 | a | CSharp7.cs:286:39:286:42 | access to local variable list | CSharp7.cs:286:45:286:47 | {...} | -| CSharp7.cs:286:9:286:47 | foreach (... ... in ...) ... | 1 | CSharp7.cs:286:33:286:33 | String b | CSharp7.cs:286:33:286:33 | b | CSharp7.cs:286:39:286:42 | access to local variable list | CSharp7.cs:286:45:286:47 | {...} | -| CSharp7.cs:288:9:288:44 | foreach (... ... in ...) ... | 0 | CSharp7.cs:288:23:288:23 | Int32 a | CSharp7.cs:288:23:288:23 | a | CSharp7.cs:288:36:288:39 | access to local variable list | CSharp7.cs:288:42:288:44 | {...} | -| CSharp7.cs:288:9:288:44 | foreach (... ... in ...) ... | 1 | CSharp7.cs:288:30:288:30 | String b | CSharp7.cs:288:30:288:30 | b | CSharp7.cs:288:36:288:39 | access to local variable list | CSharp7.cs:288:42:288:44 | {...} | -| CSharp7.cs:290:9:290:40 | foreach (... ... in ...) ... | 0 | CSharp7.cs:290:23:290:23 | Int32 a | CSharp7.cs:290:23:290:23 | a | CSharp7.cs:290:32:290:35 | access to local variable list | CSharp7.cs:290:38:290:40 | {...} | -| CSharp7.cs:290:9:290:40 | foreach (... ... in ...) ... | 1 | CSharp7.cs:290:26:290:26 | String b | CSharp7.cs:290:26:290:26 | b | CSharp7.cs:290:32:290:35 | access to local variable list | CSharp7.cs:290:38:290:40 | {...} | +| CSharp7.cs:287:9:287:47 | foreach (... ... in ...) ... | 0 | CSharp7.cs:287:23:287:23 | Int32 a | CSharp7.cs:287:23:287:23 | a | CSharp7.cs:287:39:287:42 | access to local variable list | CSharp7.cs:287:45:287:47 | {...} | +| CSharp7.cs:287:9:287:47 | foreach (... ... in ...) ... | 1 | CSharp7.cs:287:33:287:33 | String b | CSharp7.cs:287:33:287:33 | b | CSharp7.cs:287:39:287:42 | access to local variable list | CSharp7.cs:287:45:287:47 | {...} | +| CSharp7.cs:289:9:289:44 | foreach (... ... in ...) ... | 0 | CSharp7.cs:289:23:289:23 | Int32 a | CSharp7.cs:289:23:289:23 | a | CSharp7.cs:289:36:289:39 | access to local variable list | CSharp7.cs:289:42:289:44 | {...} | +| CSharp7.cs:289:9:289:44 | foreach (... ... in ...) ... | 1 | CSharp7.cs:289:30:289:30 | String b | CSharp7.cs:289:30:289:30 | b | CSharp7.cs:289:36:289:39 | access to local variable list | CSharp7.cs:289:42:289:44 | {...} | +| CSharp7.cs:291:9:291:40 | foreach (... ... in ...) ... | 0 | CSharp7.cs:291:23:291:23 | Int32 a | CSharp7.cs:291:23:291:23 | a | CSharp7.cs:291:32:291:35 | access to local variable list | CSharp7.cs:291:38:291:40 | {...} | +| CSharp7.cs:291:9:291:40 | foreach (... ... in ...) ... | 1 | CSharp7.cs:291:26:291:26 | String b | CSharp7.cs:291:26:291:26 | b | CSharp7.cs:291:32:291:35 | access to local variable list | CSharp7.cs:291:38:291:40 | {...} | diff --git a/csharp/ql/test/library-tests/csharp7/GlobalFlow.expected b/csharp/ql/test/library-tests/csharp7/GlobalFlow.expected index ffe1e741542..b0b50f92ff6 100644 --- a/csharp/ql/test/library-tests/csharp7/GlobalFlow.expected +++ b/csharp/ql/test/library-tests/csharp7/GlobalFlow.expected @@ -1,5 +1,5 @@ | CSharp7.cs:41:13:41:21 | "tainted" | CSharp7.cs:53:18:53:19 | access to local variable t1 | | CSharp7.cs:57:11:57:19 | "tainted" | CSharp7.cs:58:18:58:19 | access to local variable t4 | -| CSharp7.cs:176:22:176:30 | "tainted" | CSharp7.cs:176:22:176:30 | "tainted" | -| CSharp7.cs:176:22:176:30 | "tainted" | CSharp7.cs:182:21:182:26 | call to local function g | -| CSharp7.cs:176:22:176:30 | "tainted" | CSharp7.cs:183:21:183:26 | call to local function h | +| CSharp7.cs:177:22:177:30 | "tainted" | CSharp7.cs:177:22:177:30 | "tainted" | +| CSharp7.cs:177:22:177:30 | "tainted" | CSharp7.cs:183:21:183:26 | call to local function g | +| CSharp7.cs:177:22:177:30 | "tainted" | CSharp7.cs:184:21:184:26 | call to local function h | diff --git a/csharp/ql/test/library-tests/csharp7/GlobalTaintTracking.expected b/csharp/ql/test/library-tests/csharp7/GlobalTaintTracking.expected index 46a09f16377..e22bec46795 100644 --- a/csharp/ql/test/library-tests/csharp7/GlobalTaintTracking.expected +++ b/csharp/ql/test/library-tests/csharp7/GlobalTaintTracking.expected @@ -2,7 +2,7 @@ | CSharp7.cs:57:11:57:19 | "tainted" | CSharp7.cs:58:18:58:19 | access to local variable t4 | | CSharp7.cs:89:19:89:27 | "tainted" | CSharp7.cs:89:18:89:34 | (..., ...) | | CSharp7.cs:89:19:89:27 | "tainted" | CSharp7.cs:92:18:92:28 | call to method I | -| CSharp7.cs:176:22:176:30 | "tainted" | CSharp7.cs:176:22:176:30 | "tainted" | -| CSharp7.cs:176:22:176:30 | "tainted" | CSharp7.cs:181:21:181:26 | call to local function f | -| CSharp7.cs:176:22:176:30 | "tainted" | CSharp7.cs:182:21:182:26 | call to local function g | -| CSharp7.cs:176:22:176:30 | "tainted" | CSharp7.cs:183:21:183:26 | call to local function h | +| CSharp7.cs:177:22:177:30 | "tainted" | CSharp7.cs:177:22:177:30 | "tainted" | +| CSharp7.cs:177:22:177:30 | "tainted" | CSharp7.cs:182:21:182:26 | call to local function f | +| CSharp7.cs:177:22:177:30 | "tainted" | CSharp7.cs:183:21:183:26 | call to local function g | +| CSharp7.cs:177:22:177:30 | "tainted" | CSharp7.cs:184:21:184:26 | call to local function h | diff --git a/csharp/ql/test/library-tests/csharp7/IsFlow.expected b/csharp/ql/test/library-tests/csharp7/IsFlow.expected index 345e2f6347e..5652f980d7e 100644 --- a/csharp/ql/test/library-tests/csharp7/IsFlow.expected +++ b/csharp/ql/test/library-tests/csharp7/IsFlow.expected @@ -1,73 +1,73 @@ -| CSharp7.cs:249:9:275:9 | switch (...) {...} | CSharp7.cs:249:17:249:17 | access to local variable o | semmle.label | successor | -| CSharp7.cs:249:17:249:17 | access to local variable o | CSharp7.cs:251:13:251:23 | case ...: | semmle.label | successor | -| CSharp7.cs:251:13:251:23 | case ...: | CSharp7.cs:251:18:251:22 | "xyz" | semmle.label | successor | -| CSharp7.cs:251:18:251:22 | "xyz" | CSharp7.cs:252:17:252:22 | break; | semmle.label | match | -| CSharp7.cs:251:18:251:22 | "xyz" | CSharp7.cs:253:13:253:31 | case ...: | semmle.label | no-match | -| CSharp7.cs:252:17:252:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break | -| CSharp7.cs:253:13:253:31 | case ...: | CSharp7.cs:253:18:253:19 | "" | semmle.label | successor | -| CSharp7.cs:253:18:253:19 | "" | CSharp7.cs:253:26:253:26 | 1 | semmle.label | match | -| CSharp7.cs:253:18:253:19 | "" | CSharp7.cs:255:13:255:41 | case ...: | semmle.label | no-match | -| CSharp7.cs:253:26:253:26 | 1 | CSharp7.cs:253:30:253:30 | 2 | semmle.label | successor | -| CSharp7.cs:253:26:253:30 | ... < ... | CSharp7.cs:254:17:254:22 | break; | semmle.label | true | -| CSharp7.cs:253:30:253:30 | 2 | CSharp7.cs:253:26:253:30 | ... < ... | semmle.label | successor | -| CSharp7.cs:254:17:254:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break | -| CSharp7.cs:255:13:255:41 | case ...: | CSharp7.cs:255:18:255:20 | "x" | semmle.label | successor | -| CSharp7.cs:255:18:255:20 | "x" | CSharp7.cs:255:27:255:27 | access to local variable o | semmle.label | match | -| CSharp7.cs:255:18:255:20 | "x" | CSharp7.cs:258:13:258:36 | case ...: | semmle.label | no-match | -| CSharp7.cs:255:27:255:27 | access to local variable o | CSharp7.cs:255:32:255:40 | String s4 | semmle.label | successor | -| CSharp7.cs:255:27:255:40 | ... is ... | CSharp7.cs:256:17:256:45 | ...; | semmle.label | true | -| CSharp7.cs:255:27:255:40 | ... is ... | CSharp7.cs:258:13:258:36 | case ...: | semmle.label | false | -| CSharp7.cs:255:32:255:40 | String s4 | CSharp7.cs:255:27:255:40 | ... is ... | semmle.label | successor | -| CSharp7.cs:256:17:256:44 | call to method WriteLine | CSharp7.cs:257:17:257:22 | break; | semmle.label | successor | -| CSharp7.cs:256:17:256:45 | ...; | CSharp7.cs:256:37:256:38 | "x " | semmle.label | successor | -| CSharp7.cs:256:35:256:43 | $"..." | CSharp7.cs:256:17:256:44 | call to method WriteLine | semmle.label | successor | -| CSharp7.cs:256:37:256:38 | "x " | CSharp7.cs:256:40:256:41 | access to local variable s4 | semmle.label | successor | -| CSharp7.cs:256:40:256:41 | access to local variable s4 | CSharp7.cs:256:35:256:43 | $"..." | semmle.label | successor | -| CSharp7.cs:257:17:257:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break | -| CSharp7.cs:258:13:258:36 | case ...: | CSharp7.cs:258:18:258:23 | Int32 i2 | semmle.label | successor | -| CSharp7.cs:258:18:258:23 | Int32 i2 | CSharp7.cs:258:30:258:31 | access to local variable i2 | semmle.label | match | -| CSharp7.cs:258:18:258:23 | Int32 i2 | CSharp7.cs:261:13:261:24 | case ...: | semmle.label | no-match | -| CSharp7.cs:258:30:258:31 | access to local variable i2 | CSharp7.cs:258:35:258:35 | 0 | semmle.label | successor | -| CSharp7.cs:258:30:258:35 | ... > ... | CSharp7.cs:259:17:259:52 | ...; | semmle.label | true | -| CSharp7.cs:258:30:258:35 | ... > ... | CSharp7.cs:261:13:261:24 | case ...: | semmle.label | false | -| CSharp7.cs:258:35:258:35 | 0 | CSharp7.cs:258:30:258:35 | ... > ... | semmle.label | successor | -| CSharp7.cs:259:17:259:51 | call to method WriteLine | CSharp7.cs:260:17:260:22 | break; | semmle.label | successor | -| CSharp7.cs:259:17:259:52 | ...; | CSharp7.cs:259:37:259:45 | "positive " | semmle.label | successor | -| CSharp7.cs:259:35:259:50 | $"..." | CSharp7.cs:259:17:259:51 | call to method WriteLine | semmle.label | successor | -| CSharp7.cs:259:37:259:45 | "positive " | CSharp7.cs:259:47:259:48 | access to local variable i2 | semmle.label | successor | -| CSharp7.cs:259:47:259:48 | access to local variable i2 | CSharp7.cs:259:35:259:50 | $"..." | semmle.label | successor | -| CSharp7.cs:260:17:260:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break | -| CSharp7.cs:261:13:261:24 | case ...: | CSharp7.cs:261:18:261:23 | Int32 i3 | semmle.label | successor | -| CSharp7.cs:261:18:261:23 | Int32 i3 | CSharp7.cs:262:17:262:47 | ...; | semmle.label | match | -| CSharp7.cs:261:18:261:23 | Int32 i3 | CSharp7.cs:264:13:264:27 | case ...: | semmle.label | no-match | -| CSharp7.cs:262:17:262:46 | call to method WriteLine | CSharp7.cs:263:17:263:22 | break; | semmle.label | successor | -| CSharp7.cs:262:17:262:47 | ...; | CSharp7.cs:262:37:262:40 | "int " | semmle.label | successor | -| CSharp7.cs:262:35:262:45 | $"..." | CSharp7.cs:262:17:262:46 | call to method WriteLine | semmle.label | successor | -| CSharp7.cs:262:37:262:40 | "int " | CSharp7.cs:262:42:262:43 | access to local variable i3 | semmle.label | successor | -| CSharp7.cs:262:42:262:43 | access to local variable i3 | CSharp7.cs:262:35:262:45 | $"..." | semmle.label | successor | -| CSharp7.cs:263:17:263:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break | -| CSharp7.cs:264:13:264:27 | case ...: | CSharp7.cs:264:18:264:26 | String s2 | semmle.label | successor | -| CSharp7.cs:264:18:264:26 | String s2 | CSharp7.cs:265:17:265:50 | ...; | semmle.label | match | -| CSharp7.cs:264:18:264:26 | String s2 | CSharp7.cs:267:13:267:26 | case ...: | semmle.label | no-match | -| CSharp7.cs:265:17:265:49 | call to method WriteLine | CSharp7.cs:266:17:266:22 | break; | semmle.label | successor | -| CSharp7.cs:265:17:265:50 | ...; | CSharp7.cs:265:37:265:43 | "string " | semmle.label | successor | -| CSharp7.cs:265:35:265:48 | $"..." | CSharp7.cs:265:17:265:49 | call to method WriteLine | semmle.label | successor | -| CSharp7.cs:265:37:265:43 | "string " | CSharp7.cs:265:45:265:46 | access to local variable s2 | semmle.label | successor | -| CSharp7.cs:265:45:265:46 | access to local variable s2 | CSharp7.cs:265:35:265:48 | $"..." | semmle.label | successor | -| CSharp7.cs:266:17:266:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break | -| CSharp7.cs:267:13:267:26 | case ...: | CSharp7.cs:267:18:267:23 | access to type Double | semmle.label | successor | -| CSharp7.cs:267:18:267:23 | access to type Double | CSharp7.cs:268:17:268:44 | ...; | semmle.label | match | -| CSharp7.cs:267:18:267:23 | access to type Double | CSharp7.cs:270:13:270:24 | case ...: | semmle.label | no-match | -| CSharp7.cs:268:17:268:43 | call to method WriteLine | CSharp7.cs:269:17:269:22 | break; | semmle.label | successor | -| CSharp7.cs:268:17:268:44 | ...; | CSharp7.cs:268:35:268:42 | "Double" | semmle.label | successor | -| CSharp7.cs:268:35:268:42 | "Double" | CSharp7.cs:268:17:268:43 | call to method WriteLine | semmle.label | successor | -| CSharp7.cs:269:17:269:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break | -| CSharp7.cs:270:13:270:24 | case ...: | CSharp7.cs:270:18:270:23 | Object v2 | semmle.label | successor | -| CSharp7.cs:270:18:270:23 | Object v2 | CSharp7.cs:271:17:271:22 | break; | semmle.label | match | -| CSharp7.cs:270:18:270:23 | Object v2 | CSharp7.cs:272:13:272:20 | default: | semmle.label | no-match | -| CSharp7.cs:271:17:271:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break | -| CSharp7.cs:272:13:272:20 | default: | CSharp7.cs:273:17:273:52 | ...; | semmle.label | successor | -| CSharp7.cs:273:17:273:51 | call to method WriteLine | CSharp7.cs:274:17:274:22 | break; | semmle.label | successor | -| CSharp7.cs:273:17:273:52 | ...; | CSharp7.cs:273:35:273:50 | "Something else" | semmle.label | successor | -| CSharp7.cs:273:35:273:50 | "Something else" | CSharp7.cs:273:17:273:51 | call to method WriteLine | semmle.label | successor | -| CSharp7.cs:274:17:274:22 | break; | CSharp7.cs:231:10:231:13 | exit Test | semmle.label | break | +| CSharp7.cs:250:9:276:9 | switch (...) {...} | CSharp7.cs:250:17:250:17 | access to local variable o | semmle.label | successor | +| CSharp7.cs:250:17:250:17 | access to local variable o | CSharp7.cs:252:13:252:23 | case ...: | semmle.label | successor | +| CSharp7.cs:252:13:252:23 | case ...: | CSharp7.cs:252:18:252:22 | "xyz" | semmle.label | successor | +| CSharp7.cs:252:18:252:22 | "xyz" | CSharp7.cs:253:17:253:22 | break; | semmle.label | match | +| CSharp7.cs:252:18:252:22 | "xyz" | CSharp7.cs:254:13:254:31 | case ...: | semmle.label | no-match | +| CSharp7.cs:253:17:253:22 | break; | CSharp7.cs:232:10:232:13 | exit Test | semmle.label | break | +| CSharp7.cs:254:13:254:31 | case ...: | CSharp7.cs:254:18:254:19 | "" | semmle.label | successor | +| CSharp7.cs:254:18:254:19 | "" | CSharp7.cs:254:26:254:26 | 1 | semmle.label | match | +| CSharp7.cs:254:18:254:19 | "" | CSharp7.cs:256:13:256:41 | case ...: | semmle.label | no-match | +| CSharp7.cs:254:26:254:26 | 1 | CSharp7.cs:254:30:254:30 | 2 | semmle.label | successor | +| CSharp7.cs:254:26:254:30 | ... < ... | CSharp7.cs:255:17:255:22 | break; | semmle.label | true | +| CSharp7.cs:254:30:254:30 | 2 | CSharp7.cs:254:26:254:30 | ... < ... | semmle.label | successor | +| CSharp7.cs:255:17:255:22 | break; | CSharp7.cs:232:10:232:13 | exit Test | semmle.label | break | +| CSharp7.cs:256:13:256:41 | case ...: | CSharp7.cs:256:18:256:20 | "x" | semmle.label | successor | +| CSharp7.cs:256:18:256:20 | "x" | CSharp7.cs:256:27:256:27 | access to local variable o | semmle.label | match | +| CSharp7.cs:256:18:256:20 | "x" | CSharp7.cs:259:13:259:36 | case ...: | semmle.label | no-match | +| CSharp7.cs:256:27:256:27 | access to local variable o | CSharp7.cs:256:32:256:40 | String s4 | semmle.label | successor | +| CSharp7.cs:256:27:256:40 | ... is ... | CSharp7.cs:257:17:257:45 | ...; | semmle.label | true | +| CSharp7.cs:256:27:256:40 | ... is ... | CSharp7.cs:259:13:259:36 | case ...: | semmle.label | false | +| CSharp7.cs:256:32:256:40 | String s4 | CSharp7.cs:256:27:256:40 | ... is ... | semmle.label | successor | +| CSharp7.cs:257:17:257:44 | call to method WriteLine | CSharp7.cs:258:17:258:22 | break; | semmle.label | successor | +| CSharp7.cs:257:17:257:45 | ...; | CSharp7.cs:257:37:257:38 | "x " | semmle.label | successor | +| CSharp7.cs:257:35:257:43 | $"..." | CSharp7.cs:257:17:257:44 | call to method WriteLine | semmle.label | successor | +| CSharp7.cs:257:37:257:38 | "x " | CSharp7.cs:257:40:257:41 | access to local variable s4 | semmle.label | successor | +| CSharp7.cs:257:40:257:41 | access to local variable s4 | CSharp7.cs:257:35:257:43 | $"..." | semmle.label | successor | +| CSharp7.cs:258:17:258:22 | break; | CSharp7.cs:232:10:232:13 | exit Test | semmle.label | break | +| CSharp7.cs:259:13:259:36 | case ...: | CSharp7.cs:259:18:259:23 | Int32 i2 | semmle.label | successor | +| CSharp7.cs:259:18:259:23 | Int32 i2 | CSharp7.cs:259:30:259:31 | access to local variable i2 | semmle.label | match | +| CSharp7.cs:259:18:259:23 | Int32 i2 | CSharp7.cs:262:13:262:24 | case ...: | semmle.label | no-match | +| CSharp7.cs:259:30:259:31 | access to local variable i2 | CSharp7.cs:259:35:259:35 | 0 | semmle.label | successor | +| CSharp7.cs:259:30:259:35 | ... > ... | CSharp7.cs:260:17:260:52 | ...; | semmle.label | true | +| CSharp7.cs:259:30:259:35 | ... > ... | CSharp7.cs:262:13:262:24 | case ...: | semmle.label | false | +| CSharp7.cs:259:35:259:35 | 0 | CSharp7.cs:259:30:259:35 | ... > ... | semmle.label | successor | +| CSharp7.cs:260:17:260:51 | call to method WriteLine | CSharp7.cs:261:17:261:22 | break; | semmle.label | successor | +| CSharp7.cs:260:17:260:52 | ...; | CSharp7.cs:260:37:260:45 | "positive " | semmle.label | successor | +| CSharp7.cs:260:35:260:50 | $"..." | CSharp7.cs:260:17:260:51 | call to method WriteLine | semmle.label | successor | +| CSharp7.cs:260:37:260:45 | "positive " | CSharp7.cs:260:47:260:48 | access to local variable i2 | semmle.label | successor | +| CSharp7.cs:260:47:260:48 | access to local variable i2 | CSharp7.cs:260:35:260:50 | $"..." | semmle.label | successor | +| CSharp7.cs:261:17:261:22 | break; | CSharp7.cs:232:10:232:13 | exit Test | semmle.label | break | +| CSharp7.cs:262:13:262:24 | case ...: | CSharp7.cs:262:18:262:23 | Int32 i3 | semmle.label | successor | +| CSharp7.cs:262:18:262:23 | Int32 i3 | CSharp7.cs:263:17:263:47 | ...; | semmle.label | match | +| CSharp7.cs:262:18:262:23 | Int32 i3 | CSharp7.cs:265:13:265:27 | case ...: | semmle.label | no-match | +| CSharp7.cs:263:17:263:46 | call to method WriteLine | CSharp7.cs:264:17:264:22 | break; | semmle.label | successor | +| CSharp7.cs:263:17:263:47 | ...; | CSharp7.cs:263:37:263:40 | "int " | semmle.label | successor | +| CSharp7.cs:263:35:263:45 | $"..." | CSharp7.cs:263:17:263:46 | call to method WriteLine | semmle.label | successor | +| CSharp7.cs:263:37:263:40 | "int " | CSharp7.cs:263:42:263:43 | access to local variable i3 | semmle.label | successor | +| CSharp7.cs:263:42:263:43 | access to local variable i3 | CSharp7.cs:263:35:263:45 | $"..." | semmle.label | successor | +| CSharp7.cs:264:17:264:22 | break; | CSharp7.cs:232:10:232:13 | exit Test | semmle.label | break | +| CSharp7.cs:265:13:265:27 | case ...: | CSharp7.cs:265:18:265:26 | String s2 | semmle.label | successor | +| CSharp7.cs:265:18:265:26 | String s2 | CSharp7.cs:266:17:266:50 | ...; | semmle.label | match | +| CSharp7.cs:265:18:265:26 | String s2 | CSharp7.cs:268:13:268:26 | case ...: | semmle.label | no-match | +| CSharp7.cs:266:17:266:49 | call to method WriteLine | CSharp7.cs:267:17:267:22 | break; | semmle.label | successor | +| CSharp7.cs:266:17:266:50 | ...; | CSharp7.cs:266:37:266:43 | "string " | semmle.label | successor | +| CSharp7.cs:266:35:266:48 | $"..." | CSharp7.cs:266:17:266:49 | call to method WriteLine | semmle.label | successor | +| CSharp7.cs:266:37:266:43 | "string " | CSharp7.cs:266:45:266:46 | access to local variable s2 | semmle.label | successor | +| CSharp7.cs:266:45:266:46 | access to local variable s2 | CSharp7.cs:266:35:266:48 | $"..." | semmle.label | successor | +| CSharp7.cs:267:17:267:22 | break; | CSharp7.cs:232:10:232:13 | exit Test | semmle.label | break | +| CSharp7.cs:268:13:268:26 | case ...: | CSharp7.cs:268:18:268:23 | access to type Double | semmle.label | successor | +| CSharp7.cs:268:18:268:23 | access to type Double | CSharp7.cs:269:17:269:44 | ...; | semmle.label | match | +| CSharp7.cs:268:18:268:23 | access to type Double | CSharp7.cs:271:13:271:24 | case ...: | semmle.label | no-match | +| CSharp7.cs:269:17:269:43 | call to method WriteLine | CSharp7.cs:270:17:270:22 | break; | semmle.label | successor | +| CSharp7.cs:269:17:269:44 | ...; | CSharp7.cs:269:35:269:42 | "Double" | semmle.label | successor | +| CSharp7.cs:269:35:269:42 | "Double" | CSharp7.cs:269:17:269:43 | call to method WriteLine | semmle.label | successor | +| CSharp7.cs:270:17:270:22 | break; | CSharp7.cs:232:10:232:13 | exit Test | semmle.label | break | +| CSharp7.cs:271:13:271:24 | case ...: | CSharp7.cs:271:18:271:23 | Object v2 | semmle.label | successor | +| CSharp7.cs:271:18:271:23 | Object v2 | CSharp7.cs:272:17:272:22 | break; | semmle.label | match | +| CSharp7.cs:271:18:271:23 | Object v2 | CSharp7.cs:273:13:273:20 | default: | semmle.label | no-match | +| CSharp7.cs:272:17:272:22 | break; | CSharp7.cs:232:10:232:13 | exit Test | semmle.label | break | +| CSharp7.cs:273:13:273:20 | default: | CSharp7.cs:274:17:274:52 | ...; | semmle.label | successor | +| CSharp7.cs:274:17:274:51 | call to method WriteLine | CSharp7.cs:275:17:275:22 | break; | semmle.label | successor | +| CSharp7.cs:274:17:274:52 | ...; | CSharp7.cs:274:35:274:50 | "Something else" | semmle.label | successor | +| CSharp7.cs:274:35:274:50 | "Something else" | CSharp7.cs:274:17:274:51 | call to method WriteLine | semmle.label | successor | +| CSharp7.cs:275:17:275:22 | break; | CSharp7.cs:232:10:232:13 | exit Test | semmle.label | break | diff --git a/csharp/ql/test/library-tests/csharp7/IsPatterns.expected b/csharp/ql/test/library-tests/csharp7/IsPatterns.expected index 63bc4414490..d40737bd462 100644 --- a/csharp/ql/test/library-tests/csharp7/IsPatterns.expected +++ b/csharp/ql/test/library-tests/csharp7/IsPatterns.expected @@ -1,5 +1,5 @@ -| CSharp7.cs:234:13:234:23 | ... is ... | Int32 | CSharp7.cs:234:18:234:23 | Int32 i1 | false | -| CSharp7.cs:238:18:238:31 | ... is ... | String | CSharp7.cs:238:23:238:31 | String s1 | false | -| CSharp7.cs:245:18:245:28 | ... is ... | Object | CSharp7.cs:245:23:245:28 | Object v1 | true | -| CSharp7.cs:255:27:255:40 | ... is ... | String | CSharp7.cs:255:32:255:40 | String s4 | false | -| CSharp7.cs:298:30:298:39 | ... is ... | Int32 | CSharp7.cs:298:35:298:39 | Int32 y | false | +| CSharp7.cs:235:13:235:23 | ... is ... | Int32 | CSharp7.cs:235:18:235:23 | Int32 i1 | false | +| CSharp7.cs:239:18:239:31 | ... is ... | String | CSharp7.cs:239:23:239:31 | String s1 | false | +| CSharp7.cs:246:18:246:28 | ... is ... | Object | CSharp7.cs:246:23:246:28 | Object v1 | true | +| CSharp7.cs:256:27:256:40 | ... is ... | String | CSharp7.cs:256:32:256:40 | String s4 | false | +| CSharp7.cs:299:35:299:44 | ... is ... | Int32 | CSharp7.cs:299:40:299:44 | Int32 y | false | diff --git a/csharp/ql/test/library-tests/csharp7/LocalFunctionCallArguments.expected b/csharp/ql/test/library-tests/csharp7/LocalFunctionCallArguments.expected index 52772ab037e..2cf7be36a11 100644 --- a/csharp/ql/test/library-tests/csharp7/LocalFunctionCallArguments.expected +++ b/csharp/ql/test/library-tests/csharp7/LocalFunctionCallArguments.expected @@ -2,13 +2,13 @@ | CSharp7.cs:143:26:143:30 | call to local function f6 | 0 | CSharp7.cs:143:29:143:29 | access to parameter x | | CSharp7.cs:147:30:147:34 | call to local function f7 | 0 | CSharp7.cs:147:33:147:33 | access to parameter x | | CSharp7.cs:148:20:148:24 | call to local function f9 | 0 | CSharp7.cs:148:23:148:23 | 1 | -| CSharp7.cs:155:16:155:20 | call to local function f1 | 0 | CSharp7.cs:155:19:155:19 | 2 | -| CSharp7.cs:167:20:167:23 | call to local function g | 0 | CSharp7.cs:167:22:167:22 | access to parameter u | -| CSharp7.cs:170:9:170:15 | call to local function h | 0 | CSharp7.cs:170:11:170:11 | 0 | -| CSharp7.cs:170:9:170:15 | call to local function h | 1 | CSharp7.cs:170:14:170:14 | 0 | -| CSharp7.cs:171:9:171:19 | call to local function h | 0 | CSharp7.cs:171:11:171:12 | "" | -| CSharp7.cs:171:9:171:19 | call to local function h | 1 | CSharp7.cs:171:15:171:18 | true | -| CSharp7.cs:177:31:177:34 | call to local function g | 0 | CSharp7.cs:177:33:177:33 | access to parameter s | -| CSharp7.cs:181:21:181:26 | call to local function f | 0 | CSharp7.cs:181:23:181:25 | access to local variable src | -| CSharp7.cs:182:21:182:26 | call to local function g | 0 | CSharp7.cs:182:23:182:25 | access to local variable src | -| CSharp7.cs:183:21:183:26 | call to local function h | 0 | CSharp7.cs:183:23:183:25 | access to local variable src | +| CSharp7.cs:156:16:156:20 | call to local function f1 | 0 | CSharp7.cs:156:19:156:19 | 2 | +| CSharp7.cs:168:20:168:23 | call to local function g | 0 | CSharp7.cs:168:22:168:22 | access to parameter u | +| CSharp7.cs:171:9:171:15 | call to local function h | 0 | CSharp7.cs:171:11:171:11 | 0 | +| CSharp7.cs:171:9:171:15 | call to local function h | 1 | CSharp7.cs:171:14:171:14 | 0 | +| CSharp7.cs:172:9:172:19 | call to local function h | 0 | CSharp7.cs:172:11:172:12 | "" | +| CSharp7.cs:172:9:172:19 | call to local function h | 1 | CSharp7.cs:172:15:172:18 | true | +| CSharp7.cs:178:31:178:34 | call to local function g | 0 | CSharp7.cs:178:33:178:33 | access to parameter s | +| CSharp7.cs:182:21:182:26 | call to local function f | 0 | CSharp7.cs:182:23:182:25 | access to local variable src | +| CSharp7.cs:183:21:183:26 | call to local function g | 0 | CSharp7.cs:183:23:183:25 | access to local variable src | +| CSharp7.cs:184:21:184:26 | call to local function h | 0 | CSharp7.cs:184:23:184:25 | access to local variable src | diff --git a/csharp/ql/test/library-tests/csharp7/LocalFunctionCalls.expected b/csharp/ql/test/library-tests/csharp7/LocalFunctionCalls.expected index 9ecf8790464..f465839b3cf 100644 --- a/csharp/ql/test/library-tests/csharp7/LocalFunctionCalls.expected +++ b/csharp/ql/test/library-tests/csharp7/LocalFunctionCalls.expected @@ -2,13 +2,13 @@ | CSharp7.cs:143:26:143:30 | call to local function f6 | CSharp7.cs:141:9:141:51 | f6 | CSharp7.cs:141:9:141:51 | f6 | | CSharp7.cs:147:30:147:34 | call to local function f7 | CSharp7.cs:143:9:143:31 | f7 | CSharp7.cs:143:9:143:31 | f7 | | CSharp7.cs:148:20:148:24 | call to local function f9 | CSharp7.cs:147:13:147:35 | f9 | CSharp7.cs:147:13:147:35 | f9 | -| CSharp7.cs:155:16:155:20 | call to local function f1 | CSharp7.cs:131:9:131:39 | f1 | CSharp7.cs:131:9:131:39 | f1 | -| CSharp7.cs:165:37:165:42 | call to local function f | CSharp7.cs:160:9:160:24 | f | CSharp7.cs:160:9:160:24 | f | -| CSharp7.cs:166:13:166:18 | call to local function f | CSharp7.cs:160:9:160:24 | f | CSharp7.cs:160:9:160:24 | f | -| CSharp7.cs:167:20:167:23 | call to local function g | CSharp7.cs:161:9:161:25 | g | CSharp7.cs:161:9:161:25 | g | -| CSharp7.cs:170:9:170:15 | call to local function h | CSharp7.cs:163:9:168:9 | h | CSharp7.cs:163:9:168:9 | h | -| CSharp7.cs:171:9:171:19 | call to local function h | CSharp7.cs:163:9:168:9 | h | CSharp7.cs:163:9:168:9 | h | -| CSharp7.cs:177:31:177:34 | call to local function g | CSharp7.cs:178:9:178:32 | g | CSharp7.cs:178:9:178:32 | g | -| CSharp7.cs:181:21:181:26 | call to local function f | CSharp7.cs:177:9:177:40 | f | CSharp7.cs:177:9:177:40 | f | -| CSharp7.cs:182:21:182:26 | call to local function g | CSharp7.cs:178:9:178:32 | g | CSharp7.cs:178:9:178:32 | g | -| CSharp7.cs:183:21:183:26 | call to local function h | CSharp7.cs:179:9:179:40 | h | CSharp7.cs:179:9:179:40 | h | +| CSharp7.cs:156:16:156:20 | call to local function f1 | CSharp7.cs:131:9:131:39 | f1 | CSharp7.cs:131:9:131:39 | f1 | +| CSharp7.cs:166:37:166:42 | call to local function f | CSharp7.cs:161:9:161:24 | f | CSharp7.cs:161:9:161:24 | f | +| CSharp7.cs:167:13:167:18 | call to local function f | CSharp7.cs:161:9:161:24 | f | CSharp7.cs:161:9:161:24 | f | +| CSharp7.cs:168:20:168:23 | call to local function g | CSharp7.cs:162:9:162:25 | g | CSharp7.cs:162:9:162:25 | g | +| CSharp7.cs:171:9:171:15 | call to local function h | CSharp7.cs:164:9:169:9 | h | CSharp7.cs:164:9:169:9 | h | +| CSharp7.cs:172:9:172:19 | call to local function h | CSharp7.cs:164:9:169:9 | h | CSharp7.cs:164:9:169:9 | h | +| CSharp7.cs:178:31:178:34 | call to local function g | CSharp7.cs:179:9:179:32 | g | CSharp7.cs:179:9:179:32 | g | +| CSharp7.cs:182:21:182:26 | call to local function f | CSharp7.cs:178:9:178:40 | f | CSharp7.cs:178:9:178:40 | f | +| CSharp7.cs:183:21:183:26 | call to local function g | CSharp7.cs:179:9:179:32 | g | CSharp7.cs:179:9:179:32 | g | +| CSharp7.cs:184:21:184:26 | call to local function h | CSharp7.cs:180:9:180:40 | h | CSharp7.cs:180:9:180:40 | h | diff --git a/csharp/ql/test/library-tests/csharp7/LocalFunctionParameters.expected b/csharp/ql/test/library-tests/csharp7/LocalFunctionParameters.expected index a3aabd4f16f..a9ae61c7b86 100644 --- a/csharp/ql/test/library-tests/csharp7/LocalFunctionParameters.expected +++ b/csharp/ql/test/library-tests/csharp7/LocalFunctionParameters.expected @@ -4,17 +4,17 @@ | CSharp7.cs:141:9:141:51 | f6 | 0 | CSharp7.cs:141:20:141:20 | x | Int32 | | CSharp7.cs:143:9:143:31 | f7 | 0 | CSharp7.cs:143:20:143:20 | x | Int32 | | CSharp7.cs:147:13:147:35 | f9 | 0 | CSharp7.cs:147:24:147:24 | x | Int32 | -| CSharp7.cs:161:9:161:25 | g | 0 | CSharp7.cs:161:18:161:18 | t | T | -| CSharp7.cs:161:9:161:25 | g | 0 | CSharp7.cs:161:18:161:18 | t | U | -| CSharp7.cs:163:9:168:9 | h | 0 | CSharp7.cs:163:21:163:21 | t | Int32 | -| CSharp7.cs:163:9:168:9 | h | 0 | CSharp7.cs:163:21:163:21 | t | String | -| CSharp7.cs:163:9:168:9 | h | 0 | CSharp7.cs:163:21:163:21 | t | T | -| CSharp7.cs:163:9:168:9 | h | 1 | CSharp7.cs:163:26:163:26 | u | Boolean | -| CSharp7.cs:163:9:168:9 | h | 1 | CSharp7.cs:163:26:163:26 | u | Int32 | -| CSharp7.cs:163:9:168:9 | h | 1 | CSharp7.cs:163:26:163:26 | u | U | -| CSharp7.cs:165:13:165:43 | f2 | 0 | CSharp7.cs:165:25:165:25 | s | S | -| CSharp7.cs:165:13:165:43 | f2 | 1 | CSharp7.cs:165:30:165:31 | _t | T | -| CSharp7.cs:177:9:177:40 | f | 0 | CSharp7.cs:177:25:177:25 | s | String | -| CSharp7.cs:178:9:178:32 | g | 0 | CSharp7.cs:178:25:178:25 | s | String | -| CSharp7.cs:179:9:179:40 | h | 0 | CSharp7.cs:179:25:179:25 | s | String | -| CSharp7.cs:205:9:205:47 | F3 | 0 | CSharp7.cs:205:28:205:28 | q | Int32 | +| CSharp7.cs:162:9:162:25 | g | 0 | CSharp7.cs:162:18:162:18 | t | T | +| CSharp7.cs:162:9:162:25 | g | 0 | CSharp7.cs:162:18:162:18 | t | U | +| CSharp7.cs:164:9:169:9 | h | 0 | CSharp7.cs:164:21:164:21 | t | Int32 | +| CSharp7.cs:164:9:169:9 | h | 0 | CSharp7.cs:164:21:164:21 | t | String | +| CSharp7.cs:164:9:169:9 | h | 0 | CSharp7.cs:164:21:164:21 | t | T | +| CSharp7.cs:164:9:169:9 | h | 1 | CSharp7.cs:164:26:164:26 | u | Boolean | +| CSharp7.cs:164:9:169:9 | h | 1 | CSharp7.cs:164:26:164:26 | u | Int32 | +| CSharp7.cs:164:9:169:9 | h | 1 | CSharp7.cs:164:26:164:26 | u | U | +| CSharp7.cs:166:13:166:43 | f2 | 0 | CSharp7.cs:166:25:166:25 | s | S | +| CSharp7.cs:166:13:166:43 | f2 | 1 | CSharp7.cs:166:30:166:31 | _t | T | +| CSharp7.cs:178:9:178:40 | f | 0 | CSharp7.cs:178:25:178:25 | s | String | +| CSharp7.cs:179:9:179:32 | g | 0 | CSharp7.cs:179:25:179:25 | s | String | +| CSharp7.cs:180:9:180:40 | h | 0 | CSharp7.cs:180:25:180:25 | s | String | +| CSharp7.cs:206:9:206:47 | F3 | 0 | CSharp7.cs:206:28:206:28 | q | Int32 | diff --git a/csharp/ql/test/library-tests/csharp7/LocalFunctionStmts.expected b/csharp/ql/test/library-tests/csharp7/LocalFunctionStmts.expected index 06375392141..748bef67d7e 100644 --- a/csharp/ql/test/library-tests/csharp7/LocalFunctionStmts.expected +++ b/csharp/ql/test/library-tests/csharp7/LocalFunctionStmts.expected @@ -5,12 +5,12 @@ | CSharp7.cs:143:9:143:31 | f7(...) | CSharp7.cs:143:9:143:31 | f7 | | CSharp7.cs:145:9:149:9 | f8(...) | CSharp7.cs:145:9:149:9 | f8 | | CSharp7.cs:147:13:147:35 | f9(...) | CSharp7.cs:147:13:147:35 | f9 | -| CSharp7.cs:152:13:152:26 | f9(...) | CSharp7.cs:152:13:152:26 | f9 | -| CSharp7.cs:160:9:160:24 | f(...) | CSharp7.cs:160:9:160:24 | f | -| CSharp7.cs:161:9:161:25 | g(...) | CSharp7.cs:161:9:161:25 | g | -| CSharp7.cs:163:9:168:9 | h(...) | CSharp7.cs:163:9:168:9 | h | -| CSharp7.cs:165:13:165:43 | f2(...) | CSharp7.cs:165:13:165:43 | f2 | -| CSharp7.cs:177:9:177:40 | f(...) | CSharp7.cs:177:9:177:40 | f | -| CSharp7.cs:178:9:178:32 | g(...) | CSharp7.cs:178:9:178:32 | g | -| CSharp7.cs:179:9:179:40 | h(...) | CSharp7.cs:179:9:179:40 | h | -| CSharp7.cs:205:9:205:47 | F3(...) | CSharp7.cs:205:9:205:47 | F3 | +| CSharp7.cs:153:13:153:26 | f9(...) | CSharp7.cs:153:13:153:26 | f9 | +| CSharp7.cs:161:9:161:24 | f(...) | CSharp7.cs:161:9:161:24 | f | +| CSharp7.cs:162:9:162:25 | g(...) | CSharp7.cs:162:9:162:25 | g | +| CSharp7.cs:164:9:169:9 | h(...) | CSharp7.cs:164:9:169:9 | h | +| CSharp7.cs:166:13:166:43 | f2(...) | CSharp7.cs:166:13:166:43 | f2 | +| CSharp7.cs:178:9:178:40 | f(...) | CSharp7.cs:178:9:178:40 | f | +| CSharp7.cs:179:9:179:32 | g(...) | CSharp7.cs:179:9:179:32 | g | +| CSharp7.cs:180:9:180:40 | h(...) | CSharp7.cs:180:9:180:40 | h | +| CSharp7.cs:206:9:206:47 | F3(...) | CSharp7.cs:206:9:206:47 | F3 | diff --git a/csharp/ql/test/library-tests/csharp7/LocalFunctions.expected b/csharp/ql/test/library-tests/csharp7/LocalFunctions.expected index 89c25f6102d..789895f434d 100644 --- a/csharp/ql/test/library-tests/csharp7/LocalFunctions.expected +++ b/csharp/ql/test/library-tests/csharp7/LocalFunctions.expected @@ -1,20 +1,20 @@ -| CSharp7.cs:131:9:131:39 | f1 | f1 | Int32 | CSharp7.cs:130:5:156:5 | {...} | CSharp7.cs:131:9:131:39 | f1(...) | f1(int) | -| CSharp7.cs:133:9:133:42 | f2 | f2 | T | CSharp7.cs:130:5:156:5 | {...} | CSharp7.cs:133:9:133:42 | f2(...) | f2(T, U) | -| CSharp7.cs:137:9:137:22 | f3 | f3 | Int32 | CSharp7.cs:130:5:156:5 | {...} | CSharp7.cs:137:9:137:22 | f3(...) | f3() | -| CSharp7.cs:141:9:141:51 | f6 | f6 | Int32 | CSharp7.cs:130:5:156:5 | {...} | CSharp7.cs:141:9:141:51 | f6(...) | f6(int) | -| CSharp7.cs:143:9:143:31 | f7 | f7 | Int32 | CSharp7.cs:130:5:156:5 | {...} | CSharp7.cs:143:9:143:31 | f7(...) | f7(int) | -| CSharp7.cs:145:9:149:9 | f8 | f8 | Int32 | CSharp7.cs:130:5:156:5 | {...} | CSharp7.cs:145:9:149:9 | f8(...) | f8() | +| CSharp7.cs:131:9:131:39 | f1 | f1 | Int32 | CSharp7.cs:130:5:157:5 | {...} | CSharp7.cs:131:9:131:39 | f1(...) | f1(int) | +| CSharp7.cs:133:9:133:42 | f2 | f2 | T | CSharp7.cs:130:5:157:5 | {...} | CSharp7.cs:133:9:133:42 | f2(...) | f2(T, U) | +| CSharp7.cs:137:9:137:22 | f3 | f3 | Int32 | CSharp7.cs:130:5:157:5 | {...} | CSharp7.cs:137:9:137:22 | f3(...) | f3() | +| CSharp7.cs:141:9:141:51 | f6 | f6 | Int32 | CSharp7.cs:130:5:157:5 | {...} | CSharp7.cs:141:9:141:51 | f6(...) | f6(int) | +| CSharp7.cs:143:9:143:31 | f7 | f7 | Int32 | CSharp7.cs:130:5:157:5 | {...} | CSharp7.cs:143:9:143:31 | f7(...) | f7(int) | +| CSharp7.cs:145:9:149:9 | f8 | f8 | Int32 | CSharp7.cs:130:5:157:5 | {...} | CSharp7.cs:145:9:149:9 | f8(...) | f8() | | CSharp7.cs:147:13:147:35 | f9 | f9 | Int32 | CSharp7.cs:146:9:149:9 | {...} | CSharp7.cs:147:13:147:35 | f9(...) | f9(int) | -| CSharp7.cs:152:13:152:26 | f9 | f9 | Int32 | CSharp7.cs:151:26:153:9 | {...} | CSharp7.cs:152:13:152:26 | f9(...) | f9() | -| CSharp7.cs:160:9:160:24 | f | f | Int32 | CSharp7.cs:159:5:172:5 | {...} | CSharp7.cs:160:9:160:24 | f(...) | f() | -| CSharp7.cs:160:9:160:24 | f | f | Int32 | CSharp7.cs:159:5:172:5 | {...} | CSharp7.cs:160:9:160:24 | f(...) | f() | -| CSharp7.cs:161:9:161:25 | g | g | T | CSharp7.cs:159:5:172:5 | {...} | CSharp7.cs:161:9:161:25 | g(...) | g(T) | -| CSharp7.cs:161:9:161:25 | g | g | U | CSharp7.cs:159:5:172:5 | {...} | CSharp7.cs:161:9:161:25 | g(...) | g(U) | -| CSharp7.cs:163:9:168:9 | h | h | Boolean | CSharp7.cs:159:5:172:5 | {...} | CSharp7.cs:163:9:168:9 | h(...) | h(string, bool) | -| CSharp7.cs:163:9:168:9 | h | h | Int32 | CSharp7.cs:159:5:172:5 | {...} | CSharp7.cs:163:9:168:9 | h(...) | h(int, int) | -| CSharp7.cs:163:9:168:9 | h | h | U | CSharp7.cs:159:5:172:5 | {...} | CSharp7.cs:163:9:168:9 | h(...) | h(T, U) | -| CSharp7.cs:165:13:165:43 | f2 | f2 | Int32 | CSharp7.cs:164:9:168:9 | {...} | CSharp7.cs:165:13:165:43 | f2(...) | f2(S, T) | -| CSharp7.cs:177:9:177:40 | f | f | String | CSharp7.cs:175:5:184:5 | {...} | CSharp7.cs:177:9:177:40 | f(...) | f(string) | -| CSharp7.cs:178:9:178:32 | g | g | String | CSharp7.cs:175:5:184:5 | {...} | CSharp7.cs:178:9:178:32 | g(...) | g(string) | -| CSharp7.cs:179:9:179:40 | h | h | String | CSharp7.cs:175:5:184:5 | {...} | CSharp7.cs:179:9:179:40 | h(...) | h(string) | -| CSharp7.cs:205:9:205:47 | F3 | F3 | Int32 | CSharp7.cs:204:5:207:5 | {...} | CSharp7.cs:205:9:205:47 | F3(...) | F3(ref int) | +| CSharp7.cs:153:13:153:26 | f9 | f9 | Int32 | CSharp7.cs:152:9:154:9 | {...} | CSharp7.cs:153:13:153:26 | f9(...) | f9() | +| CSharp7.cs:161:9:161:24 | f | f | Int32 | CSharp7.cs:160:5:173:5 | {...} | CSharp7.cs:161:9:161:24 | f(...) | f() | +| CSharp7.cs:161:9:161:24 | f | f | Int32 | CSharp7.cs:160:5:173:5 | {...} | CSharp7.cs:161:9:161:24 | f(...) | f() | +| CSharp7.cs:162:9:162:25 | g | g | T | CSharp7.cs:160:5:173:5 | {...} | CSharp7.cs:162:9:162:25 | g(...) | g(T) | +| CSharp7.cs:162:9:162:25 | g | g | U | CSharp7.cs:160:5:173:5 | {...} | CSharp7.cs:162:9:162:25 | g(...) | g(U) | +| CSharp7.cs:164:9:169:9 | h | h | Boolean | CSharp7.cs:160:5:173:5 | {...} | CSharp7.cs:164:9:169:9 | h(...) | h(string, bool) | +| CSharp7.cs:164:9:169:9 | h | h | Int32 | CSharp7.cs:160:5:173:5 | {...} | CSharp7.cs:164:9:169:9 | h(...) | h(int, int) | +| CSharp7.cs:164:9:169:9 | h | h | U | CSharp7.cs:160:5:173:5 | {...} | CSharp7.cs:164:9:169:9 | h(...) | h(T, U) | +| CSharp7.cs:166:13:166:43 | f2 | f2 | Int32 | CSharp7.cs:165:9:169:9 | {...} | CSharp7.cs:166:13:166:43 | f2(...) | f2(S, T) | +| CSharp7.cs:178:9:178:40 | f | f | String | CSharp7.cs:176:5:185:5 | {...} | CSharp7.cs:178:9:178:40 | f(...) | f(string) | +| CSharp7.cs:179:9:179:32 | g | g | String | CSharp7.cs:176:5:185:5 | {...} | CSharp7.cs:179:9:179:32 | g(...) | g(string) | +| CSharp7.cs:180:9:180:40 | h | h | String | CSharp7.cs:176:5:185:5 | {...} | CSharp7.cs:180:9:180:40 | h(...) | h(string) | +| CSharp7.cs:206:9:206:47 | F3 | F3 | Int32 | CSharp7.cs:205:5:208:5 | {...} | CSharp7.cs:206:9:206:47 | F3(...) | F3(ref int) | diff --git a/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected b/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected index 10c661579f1..e5201d0df7d 100644 --- a/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected +++ b/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected @@ -29,8 +29,8 @@ | CSharp7.cs:54:9:54:17 | this access | CSharp7.cs:57:9:57:32 | this access | | CSharp7.cs:54:15:54:16 | SSA def(t1) | CSharp7.cs:55:14:55:15 | access to local variable t1 | | CSharp7.cs:57:30:57:31 | SSA def(t4) | CSharp7.cs:58:18:58:19 | access to local variable t4 | -| CSharp7.cs:66:17:66:17 | 1 | CSharp7.cs:66:16:66:21 | (..., ...) | -| CSharp7.cs:66:20:66:20 | 2 | CSharp7.cs:66:16:66:21 | (..., ...) | +| CSharp7.cs:66:20:66:20 | 1 | CSharp7.cs:66:16:66:27 | (..., ...) | +| CSharp7.cs:66:26:66:26 | 2 | CSharp7.cs:66:16:66:27 | (..., ...) | | CSharp7.cs:69:10:69:20 | this | CSharp7.cs:71:26:71:28 | this access | | CSharp7.cs:71:26:71:28 | [post] this access | CSharp7.cs:72:17:72:19 | this access | | CSharp7.cs:71:26:71:28 | this access | CSharp7.cs:72:17:72:19 | this access | @@ -40,7 +40,7 @@ | CSharp7.cs:72:17:72:19 | this access | CSharp7.cs:73:18:73:20 | this access | | CSharp7.cs:73:18:73:20 | [post] this access | CSharp7.cs:74:13:74:15 | this access | | CSharp7.cs:73:18:73:20 | this access | CSharp7.cs:74:13:74:15 | this access | -| CSharp7.cs:74:13:74:15 | call to method F | CSharp7.cs:74:13:74:21 | access to field Item1 | +| CSharp7.cs:74:13:74:15 | call to method F | CSharp7.cs:74:13:74:17 | access to field A | | CSharp7.cs:75:16:75:16 | [post] access to local variable z | CSharp7.cs:77:39:77:39 | access to local variable z | | CSharp7.cs:75:16:75:16 | access to local variable z | CSharp7.cs:77:39:77:39 | access to local variable z | | CSharp7.cs:75:28:75:28 | 1 | CSharp7.cs:75:27:75:35 | (..., ...) | @@ -116,7 +116,7 @@ | CSharp7.cs:131:32:131:32 | access to parameter x | CSharp7.cs:131:32:131:36 | ... + ... | | CSharp7.cs:131:36:131:36 | 1 | CSharp7.cs:131:32:131:36 | ... + ... | | CSharp7.cs:133:22:133:22 | t | CSharp7.cs:133:39:133:39 | access to parameter t | -| CSharp7.cs:135:24:135:25 | this access | CSharp7.cs:155:16:155:17 | this access | +| CSharp7.cs:135:24:135:25 | this access | CSharp7.cs:156:16:156:17 | this access | | CSharp7.cs:139:29:139:29 | x | CSharp7.cs:139:34:139:34 | access to parameter x | | CSharp7.cs:139:34:139:34 | access to parameter x | CSharp7.cs:139:34:139:38 | ... + ... | | CSharp7.cs:139:38:139:38 | 1 | CSharp7.cs:139:34:139:38 | ... + ... | @@ -133,119 +133,119 @@ | CSharp7.cs:145:9:149:9 | this | CSharp7.cs:148:20:148:21 | this access | | CSharp7.cs:147:13:147:35 | this | CSharp7.cs:147:30:147:31 | this access | | CSharp7.cs:147:24:147:24 | x | CSharp7.cs:147:33:147:33 | access to parameter x | -| CSharp7.cs:158:10:158:17 | this | CSharp7.cs:170:9:170:9 | this access | -| CSharp7.cs:161:18:161:18 | t | CSharp7.cs:161:24:161:24 | access to parameter t | -| CSharp7.cs:163:9:168:9 | this | CSharp7.cs:166:13:166:16 | this access | -| CSharp7.cs:163:26:163:26 | u | CSharp7.cs:167:22:167:22 | access to parameter u | -| CSharp7.cs:165:13:165:43 | this | CSharp7.cs:165:37:165:40 | this access | -| CSharp7.cs:166:13:166:16 | this access | CSharp7.cs:167:20:167:20 | this access | -| CSharp7.cs:170:9:170:9 | this access | CSharp7.cs:171:9:171:9 | this access | -| CSharp7.cs:174:10:174:19 | this | CSharp7.cs:181:21:181:21 | this access | -| CSharp7.cs:176:16:176:30 | SSA def(src) | CSharp7.cs:181:23:181:25 | access to local variable src | -| CSharp7.cs:176:22:176:30 | "tainted" | CSharp7.cs:176:16:176:30 | SSA def(src) | -| CSharp7.cs:177:9:177:40 | this | CSharp7.cs:177:31:177:31 | this access | -| CSharp7.cs:177:25:177:25 | s | CSharp7.cs:177:33:177:33 | access to parameter s | -| CSharp7.cs:177:31:177:34 | call to local function g | CSharp7.cs:177:31:177:39 | ... + ... | -| CSharp7.cs:177:38:177:39 | "" | CSharp7.cs:177:31:177:39 | ... + ... | -| CSharp7.cs:178:25:178:25 | s | CSharp7.cs:178:31:178:31 | access to parameter s | -| CSharp7.cs:179:25:179:25 | s | CSharp7.cs:179:37:179:37 | access to parameter s | -| CSharp7.cs:181:21:181:21 | this access | CSharp7.cs:182:21:182:21 | this access | -| CSharp7.cs:181:23:181:25 | [post] access to local variable src | CSharp7.cs:182:23:182:25 | access to local variable src | -| CSharp7.cs:181:23:181:25 | access to local variable src | CSharp7.cs:182:23:182:25 | access to local variable src | +| CSharp7.cs:159:10:159:17 | this | CSharp7.cs:171:9:171:9 | this access | +| CSharp7.cs:162:18:162:18 | t | CSharp7.cs:162:24:162:24 | access to parameter t | +| CSharp7.cs:164:9:169:9 | this | CSharp7.cs:167:13:167:16 | this access | +| CSharp7.cs:164:26:164:26 | u | CSharp7.cs:168:22:168:22 | access to parameter u | +| CSharp7.cs:166:13:166:43 | this | CSharp7.cs:166:37:166:40 | this access | +| CSharp7.cs:167:13:167:16 | this access | CSharp7.cs:168:20:168:20 | this access | +| CSharp7.cs:171:9:171:9 | this access | CSharp7.cs:172:9:172:9 | this access | +| CSharp7.cs:175:10:175:19 | this | CSharp7.cs:182:21:182:21 | this access | +| CSharp7.cs:177:16:177:30 | SSA def(src) | CSharp7.cs:182:23:182:25 | access to local variable src | +| CSharp7.cs:177:22:177:30 | "tainted" | CSharp7.cs:177:16:177:30 | SSA def(src) | +| CSharp7.cs:178:9:178:40 | this | CSharp7.cs:178:31:178:31 | this access | +| CSharp7.cs:178:25:178:25 | s | CSharp7.cs:178:33:178:33 | access to parameter s | +| CSharp7.cs:178:31:178:34 | call to local function g | CSharp7.cs:178:31:178:39 | ... + ... | +| CSharp7.cs:178:38:178:39 | "" | CSharp7.cs:178:31:178:39 | ... + ... | +| CSharp7.cs:179:25:179:25 | s | CSharp7.cs:179:31:179:31 | access to parameter s | +| CSharp7.cs:180:25:180:25 | s | CSharp7.cs:180:37:180:37 | access to parameter s | | CSharp7.cs:182:21:182:21 | this access | CSharp7.cs:183:21:183:21 | this access | | CSharp7.cs:182:23:182:25 | [post] access to local variable src | CSharp7.cs:183:23:183:25 | access to local variable src | | CSharp7.cs:182:23:182:25 | access to local variable src | CSharp7.cs:183:23:183:25 | access to local variable src | -| CSharp7.cs:189:10:189:11 | this | CSharp7.cs:198:14:198:23 | this access | -| CSharp7.cs:191:13:191:18 | SSA def(v1) | CSharp7.cs:192:26:192:27 | access to local variable v1 | -| CSharp7.cs:191:18:191:18 | 2 | CSharp7.cs:191:13:191:18 | SSA def(v1) | -| CSharp7.cs:192:22:192:27 | ref ... | CSharp7.cs:192:17:192:27 | SSA def(r1) | -| CSharp7.cs:192:26:192:27 | access to local variable v1 | CSharp7.cs:198:21:198:22 | access to local variable v1 | -| CSharp7.cs:193:13:193:31 | SSA def(array) | CSharp7.cs:195:14:195:18 | access to local variable array | -| CSharp7.cs:193:21:193:31 | array creation of type Int32[] | CSharp7.cs:193:13:193:31 | SSA def(array) | -| CSharp7.cs:194:14:194:14 | 3 | CSharp7.cs:194:9:194:14 | SSA def(r1) | -| CSharp7.cs:195:9:195:21 | SSA def(r1) | CSharp7.cs:197:26:197:27 | access to local variable r1 | -| CSharp7.cs:195:14:195:18 | access to local variable array | CSharp7.cs:195:14:195:21 | access to array element | -| CSharp7.cs:195:14:195:18 | access to local variable array | CSharp7.cs:196:26:196:30 | access to local variable array | -| CSharp7.cs:195:14:195:21 | access to array element | CSharp7.cs:195:9:195:21 | SSA def(r1) | -| CSharp7.cs:196:26:196:30 | access to local variable array | CSharp7.cs:196:26:196:33 | access to array element | -| CSharp7.cs:197:26:197:27 | access to local variable r1 | CSharp7.cs:199:33:199:34 | access to local variable r1 | -| CSharp7.cs:198:14:198:23 | [post] this access | CSharp7.cs:199:26:199:35 | this access | -| CSharp7.cs:198:14:198:23 | this access | CSharp7.cs:199:26:199:35 | this access | -| CSharp7.cs:199:26:199:35 | [post] this access | CSharp7.cs:200:9:200:18 | this access | -| CSharp7.cs:199:26:199:35 | this access | CSharp7.cs:200:9:200:18 | this access | -| CSharp7.cs:199:33:199:34 | access to local variable r1 | CSharp7.cs:200:16:200:17 | access to local variable r1 | -| CSharp7.cs:203:24:203:24 | p | CSharp7.cs:206:20:206:20 | access to parameter p | -| CSharp7.cs:205:28:205:28 | q | CSharp7.cs:205:44:205:44 | access to parameter q | -| CSharp7.cs:216:13:216:17 | false | CSharp7.cs:216:9:216:17 | SSA def(x) | -| CSharp7.cs:217:17:217:17 | 0 | CSharp7.cs:217:16:217:23 | (..., ...) | -| CSharp7.cs:217:20:217:22 | 0 | CSharp7.cs:217:16:217:23 | (..., ...) | -| CSharp7.cs:220:10:220:13 | this | CSharp7.cs:222:13:222:20 | this access | -| CSharp7.cs:222:13:222:20 | [post] this access | CSharp7.cs:223:18:223:25 | this access | -| CSharp7.cs:222:13:222:20 | this access | CSharp7.cs:223:18:223:25 | this access | -| CSharp7.cs:223:18:223:25 | [post] this access | CSharp7.cs:224:22:224:29 | this access | -| CSharp7.cs:223:18:223:25 | this access | CSharp7.cs:224:22:224:29 | this access | -| CSharp7.cs:224:22:224:29 | [post] this access | CSharp7.cs:225:22:225:33 | this access | -| CSharp7.cs:224:22:224:29 | this access | CSharp7.cs:225:22:225:33 | this access | -| CSharp7.cs:233:16:233:23 | SSA def(o) | CSharp7.cs:234:13:234:13 | access to local variable o | -| CSharp7.cs:233:20:233:23 | null | CSharp7.cs:233:16:233:23 | SSA def(o) | -| CSharp7.cs:234:13:234:13 | access to local variable o | CSharp7.cs:234:18:234:23 | SSA def(i1) | -| CSharp7.cs:234:13:234:13 | access to local variable o | CSharp7.cs:238:18:238:18 | access to local variable o | -| CSharp7.cs:234:13:234:13 | access to local variable o | CSharp7.cs:249:17:249:17 | access to local variable o | -| CSharp7.cs:234:13:234:23 | ... is ... | CSharp7.cs:234:13:234:33 | ... && ... | -| CSharp7.cs:234:18:234:23 | SSA def(i1) | CSharp7.cs:234:28:234:29 | access to local variable i1 | -| CSharp7.cs:234:28:234:29 | access to local variable i1 | CSharp7.cs:234:28:234:33 | ... > ... | -| CSharp7.cs:234:28:234:29 | access to local variable i1 | CSharp7.cs:236:38:236:39 | access to local variable i1 | -| CSharp7.cs:234:28:234:33 | ... > ... | CSharp7.cs:234:13:234:33 | ... && ... | -| CSharp7.cs:236:33:236:36 | "int " | CSharp7.cs:236:31:236:41 | $"..." | -| CSharp7.cs:236:38:236:39 | access to local variable i1 | CSharp7.cs:236:31:236:41 | $"..." | -| CSharp7.cs:238:18:238:18 | access to local variable o | CSharp7.cs:238:23:238:31 | SSA def(s1) | -| CSharp7.cs:238:18:238:18 | access to local variable o | CSharp7.cs:242:18:242:18 | access to local variable o | -| CSharp7.cs:238:18:238:18 | access to local variable o | CSharp7.cs:249:17:249:17 | access to local variable o | -| CSharp7.cs:238:23:238:31 | SSA def(s1) | CSharp7.cs:240:41:240:42 | access to local variable s1 | -| CSharp7.cs:240:33:240:39 | "string " | CSharp7.cs:240:31:240:44 | $"..." | -| CSharp7.cs:240:41:240:42 | access to local variable s1 | CSharp7.cs:240:31:240:44 | $"..." | -| CSharp7.cs:242:18:242:18 | access to local variable o | CSharp7.cs:245:18:245:18 | access to local variable o | -| CSharp7.cs:242:18:242:18 | access to local variable o | CSharp7.cs:249:17:249:17 | access to local variable o | -| CSharp7.cs:245:18:245:18 | access to local variable o | CSharp7.cs:249:17:249:17 | access to local variable o | -| CSharp7.cs:249:17:249:17 | access to local variable o | CSharp7.cs:255:27:255:27 | access to local variable o | -| CSharp7.cs:249:17:249:17 | access to local variable o | CSharp7.cs:258:18:258:23 | SSA def(i2) | -| CSharp7.cs:249:17:249:17 | access to local variable o | CSharp7.cs:261:18:261:23 | SSA def(i3) | -| CSharp7.cs:249:17:249:17 | access to local variable o | CSharp7.cs:264:18:264:26 | SSA def(s2) | -| CSharp7.cs:253:26:253:26 | 1 | CSharp7.cs:253:26:253:30 | ... < ... | -| CSharp7.cs:253:30:253:30 | 2 | CSharp7.cs:253:26:253:30 | ... < ... | -| CSharp7.cs:255:27:255:27 | access to local variable o | CSharp7.cs:255:32:255:40 | SSA def(s4) | -| CSharp7.cs:255:32:255:40 | SSA def(s4) | CSharp7.cs:256:40:256:41 | access to local variable s4 | -| CSharp7.cs:256:37:256:38 | "x " | CSharp7.cs:256:35:256:43 | $"..." | -| CSharp7.cs:256:40:256:41 | access to local variable s4 | CSharp7.cs:256:35:256:43 | $"..." | -| CSharp7.cs:258:18:258:23 | SSA def(i2) | CSharp7.cs:258:30:258:31 | access to local variable i2 | -| CSharp7.cs:258:30:258:31 | access to local variable i2 | CSharp7.cs:258:30:258:35 | ... > ... | -| CSharp7.cs:258:30:258:31 | access to local variable i2 | CSharp7.cs:259:47:259:48 | access to local variable i2 | -| CSharp7.cs:259:37:259:45 | "positive " | CSharp7.cs:259:35:259:50 | $"..." | -| CSharp7.cs:259:47:259:48 | access to local variable i2 | CSharp7.cs:259:35:259:50 | $"..." | -| CSharp7.cs:261:18:261:23 | SSA def(i3) | CSharp7.cs:262:42:262:43 | access to local variable i3 | -| CSharp7.cs:262:37:262:40 | "int " | CSharp7.cs:262:35:262:45 | $"..." | -| CSharp7.cs:262:42:262:43 | access to local variable i3 | CSharp7.cs:262:35:262:45 | $"..." | -| CSharp7.cs:264:18:264:26 | SSA def(s2) | CSharp7.cs:265:45:265:46 | access to local variable s2 | -| CSharp7.cs:265:37:265:43 | "string " | CSharp7.cs:265:35:265:48 | $"..." | -| CSharp7.cs:265:45:265:46 | access to local variable s2 | CSharp7.cs:265:35:265:48 | $"..." | -| CSharp7.cs:283:13:283:48 | SSA def(dict) | CSharp7.cs:284:20:284:23 | access to local variable dict | -| CSharp7.cs:283:20:283:48 | object creation of type Dictionary | CSharp7.cs:283:13:283:48 | SSA def(dict) | -| CSharp7.cs:284:13:284:62 | SSA def(list) | CSharp7.cs:286:39:286:42 | access to local variable list | -| CSharp7.cs:284:20:284:62 | call to method Select | CSharp7.cs:284:13:284:62 | SSA def(list) | -| CSharp7.cs:284:32:284:35 | item | CSharp7.cs:284:41:284:44 | access to parameter item | -| CSharp7.cs:284:41:284:44 | access to parameter item | CSharp7.cs:284:51:284:54 | access to parameter item | -| CSharp7.cs:284:41:284:48 | access to property Key | CSharp7.cs:284:40:284:61 | (..., ...) | -| CSharp7.cs:284:51:284:60 | access to property Value | CSharp7.cs:284:40:284:61 | (..., ...) | -| CSharp7.cs:286:39:286:42 | access to local variable list | CSharp7.cs:288:36:288:39 | access to local variable list | -| CSharp7.cs:288:36:288:39 | access to local variable list | CSharp7.cs:290:32:290:35 | access to local variable list | -| CSharp7.cs:298:17:298:19 | SSA def(x) | CSharp7.cs:298:22:298:39 | SSA phi(x) | -| CSharp7.cs:298:19:298:19 | 0 | CSharp7.cs:298:17:298:19 | SSA def(x) | -| CSharp7.cs:298:22:298:22 | access to local variable x | CSharp7.cs:298:22:298:25 | ... < ... | -| CSharp7.cs:298:22:298:22 | access to local variable x | CSharp7.cs:298:30:298:30 | access to local variable x | -| CSharp7.cs:298:22:298:25 | ... < ... | CSharp7.cs:298:22:298:39 | ... && ... | -| CSharp7.cs:298:22:298:39 | SSA phi(x) | CSharp7.cs:298:22:298:22 | access to local variable x | -| CSharp7.cs:298:30:298:30 | access to local variable x | CSharp7.cs:298:35:298:39 | SSA def(y) | -| CSharp7.cs:298:30:298:30 | access to local variable x | CSharp7.cs:298:44:298:44 | access to local variable x | -| CSharp7.cs:298:30:298:39 | ... is ... | CSharp7.cs:298:22:298:39 | ... && ... | -| CSharp7.cs:298:35:298:39 | SSA def(y) | CSharp7.cs:300:31:300:31 | access to local variable y | -| CSharp7.cs:298:42:298:44 | SSA def(x) | CSharp7.cs:298:22:298:39 | SSA phi(x) | +| CSharp7.cs:183:21:183:21 | this access | CSharp7.cs:184:21:184:21 | this access | +| CSharp7.cs:183:23:183:25 | [post] access to local variable src | CSharp7.cs:184:23:184:25 | access to local variable src | +| CSharp7.cs:183:23:183:25 | access to local variable src | CSharp7.cs:184:23:184:25 | access to local variable src | +| CSharp7.cs:190:10:190:11 | this | CSharp7.cs:199:14:199:23 | this access | +| CSharp7.cs:192:13:192:18 | SSA def(v1) | CSharp7.cs:193:26:193:27 | access to local variable v1 | +| CSharp7.cs:192:18:192:18 | 2 | CSharp7.cs:192:13:192:18 | SSA def(v1) | +| CSharp7.cs:193:22:193:27 | ref ... | CSharp7.cs:193:17:193:27 | SSA def(r1) | +| CSharp7.cs:193:26:193:27 | access to local variable v1 | CSharp7.cs:199:21:199:22 | access to local variable v1 | +| CSharp7.cs:194:13:194:31 | SSA def(array) | CSharp7.cs:196:14:196:18 | access to local variable array | +| CSharp7.cs:194:21:194:31 | array creation of type Int32[] | CSharp7.cs:194:13:194:31 | SSA def(array) | +| CSharp7.cs:195:14:195:14 | 3 | CSharp7.cs:195:9:195:14 | SSA def(r1) | +| CSharp7.cs:196:9:196:21 | SSA def(r1) | CSharp7.cs:198:26:198:27 | access to local variable r1 | +| CSharp7.cs:196:14:196:18 | access to local variable array | CSharp7.cs:196:14:196:21 | access to array element | +| CSharp7.cs:196:14:196:18 | access to local variable array | CSharp7.cs:197:26:197:30 | access to local variable array | +| CSharp7.cs:196:14:196:21 | access to array element | CSharp7.cs:196:9:196:21 | SSA def(r1) | +| CSharp7.cs:197:26:197:30 | access to local variable array | CSharp7.cs:197:26:197:33 | access to array element | +| CSharp7.cs:198:26:198:27 | access to local variable r1 | CSharp7.cs:200:33:200:34 | access to local variable r1 | +| CSharp7.cs:199:14:199:23 | [post] this access | CSharp7.cs:200:26:200:35 | this access | +| CSharp7.cs:199:14:199:23 | this access | CSharp7.cs:200:26:200:35 | this access | +| CSharp7.cs:200:26:200:35 | [post] this access | CSharp7.cs:201:9:201:18 | this access | +| CSharp7.cs:200:26:200:35 | this access | CSharp7.cs:201:9:201:18 | this access | +| CSharp7.cs:200:33:200:34 | access to local variable r1 | CSharp7.cs:201:16:201:17 | access to local variable r1 | +| CSharp7.cs:204:24:204:24 | p | CSharp7.cs:207:20:207:20 | access to parameter p | +| CSharp7.cs:206:28:206:28 | q | CSharp7.cs:206:44:206:44 | access to parameter q | +| CSharp7.cs:217:13:217:17 | false | CSharp7.cs:217:9:217:17 | SSA def(x) | +| CSharp7.cs:218:17:218:17 | 0 | CSharp7.cs:218:16:218:23 | (..., ...) | +| CSharp7.cs:218:20:218:22 | 0 | CSharp7.cs:218:16:218:23 | (..., ...) | +| CSharp7.cs:221:10:221:13 | this | CSharp7.cs:223:13:223:20 | this access | +| CSharp7.cs:223:13:223:20 | [post] this access | CSharp7.cs:224:18:224:25 | this access | +| CSharp7.cs:223:13:223:20 | this access | CSharp7.cs:224:18:224:25 | this access | +| CSharp7.cs:224:18:224:25 | [post] this access | CSharp7.cs:225:22:225:29 | this access | +| CSharp7.cs:224:18:224:25 | this access | CSharp7.cs:225:22:225:29 | this access | +| CSharp7.cs:225:22:225:29 | [post] this access | CSharp7.cs:226:22:226:33 | this access | +| CSharp7.cs:225:22:225:29 | this access | CSharp7.cs:226:22:226:33 | this access | +| CSharp7.cs:234:16:234:23 | SSA def(o) | CSharp7.cs:235:13:235:13 | access to local variable o | +| CSharp7.cs:234:20:234:23 | null | CSharp7.cs:234:16:234:23 | SSA def(o) | +| CSharp7.cs:235:13:235:13 | access to local variable o | CSharp7.cs:235:18:235:23 | SSA def(i1) | +| CSharp7.cs:235:13:235:13 | access to local variable o | CSharp7.cs:239:18:239:18 | access to local variable o | +| CSharp7.cs:235:13:235:13 | access to local variable o | CSharp7.cs:250:17:250:17 | access to local variable o | +| CSharp7.cs:235:13:235:23 | ... is ... | CSharp7.cs:235:13:235:33 | ... && ... | +| CSharp7.cs:235:18:235:23 | SSA def(i1) | CSharp7.cs:235:28:235:29 | access to local variable i1 | +| CSharp7.cs:235:28:235:29 | access to local variable i1 | CSharp7.cs:235:28:235:33 | ... > ... | +| CSharp7.cs:235:28:235:29 | access to local variable i1 | CSharp7.cs:237:38:237:39 | access to local variable i1 | +| CSharp7.cs:235:28:235:33 | ... > ... | CSharp7.cs:235:13:235:33 | ... && ... | +| CSharp7.cs:237:33:237:36 | "int " | CSharp7.cs:237:31:237:41 | $"..." | +| CSharp7.cs:237:38:237:39 | access to local variable i1 | CSharp7.cs:237:31:237:41 | $"..." | +| CSharp7.cs:239:18:239:18 | access to local variable o | CSharp7.cs:239:23:239:31 | SSA def(s1) | +| CSharp7.cs:239:18:239:18 | access to local variable o | CSharp7.cs:243:18:243:18 | access to local variable o | +| CSharp7.cs:239:18:239:18 | access to local variable o | CSharp7.cs:250:17:250:17 | access to local variable o | +| CSharp7.cs:239:23:239:31 | SSA def(s1) | CSharp7.cs:241:41:241:42 | access to local variable s1 | +| CSharp7.cs:241:33:241:39 | "string " | CSharp7.cs:241:31:241:44 | $"..." | +| CSharp7.cs:241:41:241:42 | access to local variable s1 | CSharp7.cs:241:31:241:44 | $"..." | +| CSharp7.cs:243:18:243:18 | access to local variable o | CSharp7.cs:246:18:246:18 | access to local variable o | +| CSharp7.cs:243:18:243:18 | access to local variable o | CSharp7.cs:250:17:250:17 | access to local variable o | +| CSharp7.cs:246:18:246:18 | access to local variable o | CSharp7.cs:250:17:250:17 | access to local variable o | +| CSharp7.cs:250:17:250:17 | access to local variable o | CSharp7.cs:256:27:256:27 | access to local variable o | +| CSharp7.cs:250:17:250:17 | access to local variable o | CSharp7.cs:259:18:259:23 | SSA def(i2) | +| CSharp7.cs:250:17:250:17 | access to local variable o | CSharp7.cs:262:18:262:23 | SSA def(i3) | +| CSharp7.cs:250:17:250:17 | access to local variable o | CSharp7.cs:265:18:265:26 | SSA def(s2) | +| CSharp7.cs:254:26:254:26 | 1 | CSharp7.cs:254:26:254:30 | ... < ... | +| CSharp7.cs:254:30:254:30 | 2 | CSharp7.cs:254:26:254:30 | ... < ... | +| CSharp7.cs:256:27:256:27 | access to local variable o | CSharp7.cs:256:32:256:40 | SSA def(s4) | +| CSharp7.cs:256:32:256:40 | SSA def(s4) | CSharp7.cs:257:40:257:41 | access to local variable s4 | +| CSharp7.cs:257:37:257:38 | "x " | CSharp7.cs:257:35:257:43 | $"..." | +| CSharp7.cs:257:40:257:41 | access to local variable s4 | CSharp7.cs:257:35:257:43 | $"..." | +| CSharp7.cs:259:18:259:23 | SSA def(i2) | CSharp7.cs:259:30:259:31 | access to local variable i2 | +| CSharp7.cs:259:30:259:31 | access to local variable i2 | CSharp7.cs:259:30:259:35 | ... > ... | +| CSharp7.cs:259:30:259:31 | access to local variable i2 | CSharp7.cs:260:47:260:48 | access to local variable i2 | +| CSharp7.cs:260:37:260:45 | "positive " | CSharp7.cs:260:35:260:50 | $"..." | +| CSharp7.cs:260:47:260:48 | access to local variable i2 | CSharp7.cs:260:35:260:50 | $"..." | +| CSharp7.cs:262:18:262:23 | SSA def(i3) | CSharp7.cs:263:42:263:43 | access to local variable i3 | +| CSharp7.cs:263:37:263:40 | "int " | CSharp7.cs:263:35:263:45 | $"..." | +| CSharp7.cs:263:42:263:43 | access to local variable i3 | CSharp7.cs:263:35:263:45 | $"..." | +| CSharp7.cs:265:18:265:26 | SSA def(s2) | CSharp7.cs:266:45:266:46 | access to local variable s2 | +| CSharp7.cs:266:37:266:43 | "string " | CSharp7.cs:266:35:266:48 | $"..." | +| CSharp7.cs:266:45:266:46 | access to local variable s2 | CSharp7.cs:266:35:266:48 | $"..." | +| CSharp7.cs:284:13:284:48 | SSA def(dict) | CSharp7.cs:285:20:285:23 | access to local variable dict | +| CSharp7.cs:284:20:284:48 | object creation of type Dictionary | CSharp7.cs:284:13:284:48 | SSA def(dict) | +| CSharp7.cs:285:13:285:62 | SSA def(list) | CSharp7.cs:287:39:287:42 | access to local variable list | +| CSharp7.cs:285:20:285:62 | call to method Select | CSharp7.cs:285:13:285:62 | SSA def(list) | +| CSharp7.cs:285:32:285:35 | item | CSharp7.cs:285:41:285:44 | access to parameter item | +| CSharp7.cs:285:41:285:44 | access to parameter item | CSharp7.cs:285:51:285:54 | access to parameter item | +| CSharp7.cs:285:41:285:48 | access to property Key | CSharp7.cs:285:40:285:61 | (..., ...) | +| CSharp7.cs:285:51:285:60 | access to property Value | CSharp7.cs:285:40:285:61 | (..., ...) | +| CSharp7.cs:287:39:287:42 | access to local variable list | CSharp7.cs:289:36:289:39 | access to local variable list | +| CSharp7.cs:289:36:289:39 | access to local variable list | CSharp7.cs:291:32:291:35 | access to local variable list | +| CSharp7.cs:299:18:299:22 | SSA def(x) | CSharp7.cs:299:25:299:44 | SSA phi(x) | +| CSharp7.cs:299:22:299:22 | 0 | CSharp7.cs:299:18:299:22 | SSA def(x) | +| CSharp7.cs:299:25:299:25 | access to local variable x | CSharp7.cs:299:25:299:30 | ... < ... | +| CSharp7.cs:299:25:299:25 | access to local variable x | CSharp7.cs:299:35:299:35 | access to local variable x | +| CSharp7.cs:299:25:299:30 | ... < ... | CSharp7.cs:299:25:299:44 | ... && ... | +| CSharp7.cs:299:25:299:44 | SSA phi(x) | CSharp7.cs:299:25:299:25 | access to local variable x | +| CSharp7.cs:299:35:299:35 | access to local variable x | CSharp7.cs:299:40:299:44 | SSA def(y) | +| CSharp7.cs:299:35:299:35 | access to local variable x | CSharp7.cs:299:49:299:49 | access to local variable x | +| CSharp7.cs:299:35:299:44 | ... is ... | CSharp7.cs:299:25:299:44 | ... && ... | +| CSharp7.cs:299:40:299:44 | SSA def(y) | CSharp7.cs:301:31:301:31 | access to local variable y | +| CSharp7.cs:299:47:299:49 | SSA def(x) | CSharp7.cs:299:25:299:44 | SSA phi(x) | diff --git a/csharp/ql/test/library-tests/csharp7/LocalVariables.expected b/csharp/ql/test/library-tests/csharp7/LocalVariables.expected index 06f61a52f91..7e0793d3b43 100644 --- a/csharp/ql/test/library-tests/csharp7/LocalVariables.expected +++ b/csharp/ql/test/library-tests/csharp7/LocalVariables.expected @@ -36,35 +36,35 @@ | CSharp7.cs:135:19:135:20 | f4 | Func | | CSharp7.cs:139:24:139:25 | f5 | Func | | CSharp7.cs:151:16:151:16 | a | Action | -| CSharp7.cs:176:16:176:18 | src | string | -| CSharp7.cs:181:13:181:17 | sink1 | string | -| CSharp7.cs:182:13:182:17 | sink2 | string | -| CSharp7.cs:183:13:183:17 | sink3 | string | -| CSharp7.cs:191:13:191:14 | v1 | int | -| CSharp7.cs:192:17:192:18 | r1 | int | -| CSharp7.cs:193:13:193:17 | array | Int32[] | -| CSharp7.cs:196:17:196:18 | r2 | int | -| CSharp7.cs:197:17:197:18 | r3 | int | -| CSharp7.cs:199:17:199:18 | r4 | int | -| CSharp7.cs:224:14:224:14 | x | int | -| CSharp7.cs:225:17:225:17 | y | double | -| CSharp7.cs:225:32:225:32 | z | bool | -| CSharp7.cs:233:16:233:16 | o | object | -| CSharp7.cs:234:22:234:23 | i1 | int | -| CSharp7.cs:238:30:238:31 | s1 | string | -| CSharp7.cs:245:27:245:28 | v1 | object | -| CSharp7.cs:255:39:255:40 | s4 | string | -| CSharp7.cs:258:22:258:23 | i2 | int | -| CSharp7.cs:261:22:261:23 | i3 | int | -| CSharp7.cs:264:25:264:26 | s2 | string | -| CSharp7.cs:270:22:270:23 | v2 | object | -| CSharp7.cs:283:13:283:16 | dict | Dictionary | -| CSharp7.cs:284:13:284:16 | list | IEnumerable<(Int32,String)> | -| CSharp7.cs:286:23:286:23 | a | int | -| CSharp7.cs:286:33:286:33 | b | string | -| CSharp7.cs:288:23:288:23 | a | int | -| CSharp7.cs:288:30:288:30 | b | string | -| CSharp7.cs:290:23:290:23 | a | int | -| CSharp7.cs:290:26:290:26 | b | string | -| CSharp7.cs:298:17:298:17 | x | int | -| CSharp7.cs:298:39:298:39 | y | int | +| CSharp7.cs:177:16:177:18 | src | string | +| CSharp7.cs:182:13:182:17 | sink1 | string | +| CSharp7.cs:183:13:183:17 | sink2 | string | +| CSharp7.cs:184:13:184:17 | sink3 | string | +| CSharp7.cs:192:13:192:14 | v1 | int | +| CSharp7.cs:193:17:193:18 | r1 | int | +| CSharp7.cs:194:13:194:17 | array | Int32[] | +| CSharp7.cs:197:17:197:18 | r2 | int | +| CSharp7.cs:198:17:198:18 | r3 | int | +| CSharp7.cs:200:17:200:18 | r4 | int | +| CSharp7.cs:225:14:225:14 | x | int | +| CSharp7.cs:226:17:226:17 | y | double | +| CSharp7.cs:226:32:226:32 | z | bool | +| CSharp7.cs:234:16:234:16 | o | object | +| CSharp7.cs:235:22:235:23 | i1 | int | +| CSharp7.cs:239:30:239:31 | s1 | string | +| CSharp7.cs:246:27:246:28 | v1 | object | +| CSharp7.cs:256:39:256:40 | s4 | string | +| CSharp7.cs:259:22:259:23 | i2 | int | +| CSharp7.cs:262:22:262:23 | i3 | int | +| CSharp7.cs:265:25:265:26 | s2 | string | +| CSharp7.cs:271:22:271:23 | v2 | object | +| CSharp7.cs:284:13:284:16 | dict | Dictionary | +| CSharp7.cs:285:13:285:16 | list | IEnumerable<(Int32,String)> | +| CSharp7.cs:287:23:287:23 | a | int | +| CSharp7.cs:287:33:287:33 | b | string | +| CSharp7.cs:289:23:289:23 | a | int | +| CSharp7.cs:289:30:289:30 | b | string | +| CSharp7.cs:291:23:291:23 | a | int | +| CSharp7.cs:291:26:291:26 | b | string | +| CSharp7.cs:299:18:299:18 | x | int | +| CSharp7.cs:299:44:299:44 | y | int | diff --git a/csharp/ql/test/library-tests/csharp7/PrintAst.expected b/csharp/ql/test/library-tests/csharp7/PrintAst.expected index eb89509351f..a3d0e25e815 100644 --- a/csharp/ql/test/library-tests/csharp7/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp7/PrintAst.expected @@ -131,7 +131,7 @@ CSharp7.cs: # 73| 1: [LocalVariableAccess] access to local variable y # 74| 3: [ExprStmt] ...; # 74| 0: [AssignExpr] ... = ... -# 74| 0: [FieldAccess] access to field Item1 +# 74| 0: [FieldAccess] access to field A # 74| -1: [MethodCall] call to method F # 74| 1: [LocalVariableAccess] access to local variable x # 75| 4: [ExprStmt] ...; @@ -403,391 +403,391 @@ CSharp7.cs: # 151| 8: [LocalVariableDeclStmt] ... ...; # 151| 0: [LocalVariableDeclAndInitExpr] Action a = ... # 151| 0: [LambdaExpr] (...) => ... -# 151| 4: [BlockStmt] {...} -# 152| 0: [LocalFunctionStmt] f9(...) -# 152| 0: [LocalFunction] f9 -# 152| 4: [IntLiteral] 0 +# 152| 4: [BlockStmt] {...} +# 153| 0: [LocalFunctionStmt] f9(...) +# 153| 0: [LocalFunction] f9 +# 153| 4: [IntLiteral] 0 # 151| 1: [LocalVariableAccess] access to local variable a -# 155| 9: [ReturnStmt] return ...; -# 155| 0: [LocalFunctionCall] call to local function f1 -# 155| -1: [LocalFunctionAccess] access to local function f1 -# 155| 0: [IntLiteral] 2 -# 158| 6: [Method] Generics -# 159| 4: [BlockStmt] {...} -# 160| 0: [LocalFunctionStmt] f(...) -# 160| 0: [LocalFunction] f -#-----| 1: (Type parameters) -# 160| 0: [TypeParameter] T -# 160| 4: [IntLiteral] 1 -# 161| 1: [LocalFunctionStmt] g(...) -# 161| 0: [LocalFunction] g +# 156| 9: [ReturnStmt] return ...; +# 156| 0: [LocalFunctionCall] call to local function f1 +# 156| -1: [LocalFunctionAccess] access to local function f1 +# 156| 0: [IntLiteral] 2 +# 159| 6: [Method] Generics +# 160| 4: [BlockStmt] {...} +# 161| 0: [LocalFunctionStmt] f(...) +# 161| 0: [LocalFunction] f #-----| 1: (Type parameters) # 161| 0: [TypeParameter] T -#-----| 2: (Parameters) -# 161| 0: [Parameter] t -# 161| 4: [ParameterAccess] access to parameter t -# 163| 2: [LocalFunctionStmt] h(...) -# 163| 0: [LocalFunction] h +# 161| 4: [IntLiteral] 1 +# 162| 1: [LocalFunctionStmt] g(...) +# 162| 0: [LocalFunction] g #-----| 1: (Type parameters) -# 163| 0: [TypeParameter] T -# 163| 1: [TypeParameter] U +# 162| 0: [TypeParameter] T #-----| 2: (Parameters) -# 163| 0: [Parameter] t -# 163| 1: [Parameter] u -# 164| 4: [BlockStmt] {...} -# 165| 0: [LocalFunctionStmt] f2(...) -# 165| 0: [LocalFunction] f2 +# 162| 0: [Parameter] t +# 162| 4: [ParameterAccess] access to parameter t +# 164| 2: [LocalFunctionStmt] h(...) +# 164| 0: [LocalFunction] h +#-----| 1: (Type parameters) +# 164| 0: [TypeParameter] T +# 164| 1: [TypeParameter] U +#-----| 2: (Parameters) +# 164| 0: [Parameter] t +# 164| 1: [Parameter] u +# 165| 4: [BlockStmt] {...} +# 166| 0: [LocalFunctionStmt] f2(...) +# 166| 0: [LocalFunction] f2 #-----| 1: (Type parameters) -# 165| 0: [TypeParameter] S +# 166| 0: [TypeParameter] S #-----| 2: (Parameters) -# 165| 0: [Parameter] s -# 165| 1: [Parameter] _t -# 165| 4: [LocalFunctionCall] call to local function f -# 165| -1: [LocalFunctionAccess] access to local function f -# 166| 1: [ExprStmt] ...; -# 166| 0: [LocalFunctionCall] call to local function f -# 166| -1: [LocalFunctionAccess] access to local function f -# 167| 2: [ReturnStmt] return ...; -# 167| 0: [LocalFunctionCall] call to local function g -# 167| -1: [LocalFunctionAccess] access to local function g -# 167| 0: [ParameterAccess] access to parameter u -# 170| 3: [ExprStmt] ...; -# 170| 0: [LocalFunctionCall] call to local function h -# 170| -1: [LocalFunctionAccess] access to local function h -# 170| 0: [IntLiteral] 0 -# 170| 1: [IntLiteral] 0 -# 171| 4: [ExprStmt] ...; +# 166| 0: [Parameter] s +# 166| 1: [Parameter] _t +# 166| 4: [LocalFunctionCall] call to local function f +# 166| -1: [LocalFunctionAccess] access to local function f +# 167| 1: [ExprStmt] ...; +# 167| 0: [LocalFunctionCall] call to local function f +# 167| -1: [LocalFunctionAccess] access to local function f +# 168| 2: [ReturnStmt] return ...; +# 168| 0: [LocalFunctionCall] call to local function g +# 168| -1: [LocalFunctionAccess] access to local function g +# 168| 0: [ParameterAccess] access to parameter u +# 171| 3: [ExprStmt] ...; # 171| 0: [LocalFunctionCall] call to local function h # 171| -1: [LocalFunctionAccess] access to local function h -# 171| 0: [StringLiteral] "" -# 171| 1: [BoolLiteral] true -# 174| 7: [Method] GlobalFlow -# 175| 4: [BlockStmt] {...} -# 176| 0: [LocalVariableDeclStmt] ... ...; -# 176| 0: [LocalVariableDeclAndInitExpr] String src = ... -# 176| 0: [StringLiteral] "tainted" -# 176| 1: [LocalVariableAccess] access to local variable src -# 177| 1: [LocalFunctionStmt] f(...) -# 177| 0: [LocalFunction] f -#-----| 2: (Parameters) -# 177| 0: [Parameter] s -# 177| 4: [AddExpr] ... + ... -# 177| 0: [LocalFunctionCall] call to local function g -# 177| -1: [LocalFunctionAccess] access to local function g -# 177| 0: [ParameterAccess] access to parameter s -# 177| 1: [StringLiteral] "" -# 178| 2: [LocalFunctionStmt] g(...) -# 178| 0: [LocalFunction] g +# 171| 0: [IntLiteral] 0 +# 171| 1: [IntLiteral] 0 +# 172| 4: [ExprStmt] ...; +# 172| 0: [LocalFunctionCall] call to local function h +# 172| -1: [LocalFunctionAccess] access to local function h +# 172| 0: [StringLiteral] "" +# 172| 1: [BoolLiteral] true +# 175| 7: [Method] GlobalFlow +# 176| 4: [BlockStmt] {...} +# 177| 0: [LocalVariableDeclStmt] ... ...; +# 177| 0: [LocalVariableDeclAndInitExpr] String src = ... +# 177| 0: [StringLiteral] "tainted" +# 177| 1: [LocalVariableAccess] access to local variable src +# 178| 1: [LocalFunctionStmt] f(...) +# 178| 0: [LocalFunction] f #-----| 2: (Parameters) # 178| 0: [Parameter] s -# 178| 4: [ParameterAccess] access to parameter s -# 179| 3: [LocalFunctionStmt] h(...) -# 179| 0: [LocalFunction] h +# 178| 4: [AddExpr] ... + ... +# 178| 0: [LocalFunctionCall] call to local function g +# 178| -1: [LocalFunctionAccess] access to local function g +# 178| 0: [ParameterAccess] access to parameter s +# 178| 1: [StringLiteral] "" +# 179| 2: [LocalFunctionStmt] g(...) +# 179| 0: [LocalFunction] g #-----| 2: (Parameters) # 179| 0: [Parameter] s -# 179| 4: [BlockStmt] {...} -# 179| 0: [ReturnStmt] return ...; -# 179| 0: [ParameterAccess] access to parameter s -# 181| 4: [LocalVariableDeclStmt] ... ...; -# 181| 0: [LocalVariableDeclAndInitExpr] String sink1 = ... -# 181| 0: [LocalFunctionCall] call to local function f -# 181| -1: [LocalFunctionAccess] access to local function f -# 181| 0: [LocalVariableAccess] access to local variable src -# 181| 1: [LocalVariableAccess] access to local variable sink1 -# 182| 5: [LocalVariableDeclStmt] ... ...; -# 182| 0: [LocalVariableDeclAndInitExpr] String sink2 = ... -# 182| 0: [LocalFunctionCall] call to local function g -# 182| -1: [LocalFunctionAccess] access to local function g -# 182| 0: [LocalVariableAccess] access to local variable src -# 182| 1: [LocalVariableAccess] access to local variable sink2 -# 183| 6: [LocalVariableDeclStmt] ... ...; -# 183| 0: [LocalVariableDeclAndInitExpr] String sink3 = ... -# 183| 0: [LocalFunctionCall] call to local function h -# 183| -1: [LocalFunctionAccess] access to local function h -# 183| 0: [LocalVariableAccess] access to local variable src -# 183| 1: [LocalVariableAccess] access to local variable sink3 -# 187| [Class] Refs -# 189| 5: [Method] F1 -# 190| 4: [BlockStmt] {...} -# 191| 0: [LocalVariableDeclStmt] ... ...; -# 191| 0: [LocalVariableDeclAndInitExpr] Int32 v1 = ... -# 191| 0: [IntLiteral] 2 -# 191| 1: [LocalVariableAccess] access to local variable v1 -# 192| 1: [LocalVariableDeclStmt] ... ...; -# 192| 0: [LocalVariableDeclAndInitExpr] Int32 r1 = ... -# 192| 0: [RefExpr] ref ... -# 192| 0: [LocalVariableAccess] access to local variable v1 -# 192| 1: [LocalVariableAccess] access to local variable r1 -# 193| 2: [LocalVariableDeclStmt] ... ...; -# 193| 0: [LocalVariableDeclAndInitExpr] Int32[] array = ... -# 193| 0: [ArrayCreation] array creation of type Int32[] -# 193| 0: [IntLiteral] 10 -# 193| 1: [LocalVariableAccess] access to local variable array -# 194| 3: [ExprStmt] ...; -# 194| 0: [AssignExpr] ... = ... -# 194| 0: [IntLiteral] 3 -# 194| 1: [LocalVariableAccess] access to local variable r1 -# 195| 4: [ExprStmt] ...; -# 195| 0: [AssignExpr] ... = ... -# 195| 0: [ArrayAccess] access to array element -# 195| -1: [LocalVariableAccess] access to local variable array -# 195| 0: [IntLiteral] 1 -# 195| 1: [LocalVariableAccess] access to local variable r1 -# 196| 5: [LocalVariableDeclStmt] ... ...; -# 196| 0: [LocalVariableDeclAndInitExpr] Int32 r2 = ... -# 196| 0: [RefExpr] ref ... -# 196| 0: [ArrayAccess] access to array element -# 196| -1: [LocalVariableAccess] access to local variable array -# 196| 0: [IntLiteral] 3 -# 196| 1: [LocalVariableAccess] access to local variable r2 -# 197| 6: [LocalVariableDeclStmt] ... ...; -# 197| 0: [LocalVariableDeclAndInitExpr] Int32 r3 = ... -# 197| 0: [RefExpr] ref ... -# 197| 0: [LocalVariableAccess] access to local variable r1 -# 197| 1: [LocalVariableAccess] access to local variable r3 -# 198| 7: [ExprStmt] ...; -# 198| 0: [AssignExpr] ... = ... -# 198| 0: [MethodCall] call to method F2 -# 198| 0: [LocalVariableAccess] access to local variable v1 -# 198| 1: [LocalVariableAccess] access to local variable v1 -# 199| 8: [LocalVariableDeclStmt] ... ...; -# 199| 0: [LocalVariableDeclAndInitExpr] Int32 r4 = ... -# 199| 0: [RefExpr] ref ... -# 199| 0: [MethodCall] call to method F2 -# 199| 0: [LocalVariableAccess] access to local variable r1 -# 199| 1: [LocalVariableAccess] access to local variable r4 -# 200| 9: [ExprStmt] ...; -# 200| 0: [AssignExpr] ... = ... -# 200| 0: [IntLiteral] 3 -# 200| 1: [MethodCall] call to method F2 -# 200| 0: [LocalVariableAccess] access to local variable r1 -# 203| 6: [Method] F2 -#-----| 2: (Parameters) -# 203| 0: [Parameter] p -# 204| 4: [BlockStmt] {...} -# 205| 0: [LocalFunctionStmt] F3(...) -# 205| 0: [LocalFunction] F3 +# 179| 4: [ParameterAccess] access to parameter s +# 180| 3: [LocalFunctionStmt] h(...) +# 180| 0: [LocalFunction] h #-----| 2: (Parameters) -# 205| 0: [Parameter] q -# 205| 4: [BlockStmt] {...} -# 205| 0: [ReturnStmt] return ...; -# 205| 0: [RefExpr] ref ... -# 205| 0: [ParameterAccess] access to parameter q -# 206| 1: [ReturnStmt] return ...; -# 206| 0: [RefExpr] ref ... -# 206| 0: [ParameterAccess] access to parameter p -# 209| 7: [DelegateType] RefFn +# 180| 0: [Parameter] s +# 180| 4: [BlockStmt] {...} +# 180| 0: [ReturnStmt] return ...; +# 180| 0: [ParameterAccess] access to parameter s +# 182| 4: [LocalVariableDeclStmt] ... ...; +# 182| 0: [LocalVariableDeclAndInitExpr] String sink1 = ... +# 182| 0: [LocalFunctionCall] call to local function f +# 182| -1: [LocalFunctionAccess] access to local function f +# 182| 0: [LocalVariableAccess] access to local variable src +# 182| 1: [LocalVariableAccess] access to local variable sink1 +# 183| 5: [LocalVariableDeclStmt] ... ...; +# 183| 0: [LocalVariableDeclAndInitExpr] String sink2 = ... +# 183| 0: [LocalFunctionCall] call to local function g +# 183| -1: [LocalFunctionAccess] access to local function g +# 183| 0: [LocalVariableAccess] access to local variable src +# 183| 1: [LocalVariableAccess] access to local variable sink2 +# 184| 6: [LocalVariableDeclStmt] ... ...; +# 184| 0: [LocalVariableDeclAndInitExpr] String sink3 = ... +# 184| 0: [LocalFunctionCall] call to local function h +# 184| -1: [LocalFunctionAccess] access to local function h +# 184| 0: [LocalVariableAccess] access to local variable src +# 184| 1: [LocalVariableAccess] access to local variable sink3 +# 188| [Class] Refs +# 190| 5: [Method] F1 +# 191| 4: [BlockStmt] {...} +# 192| 0: [LocalVariableDeclStmt] ... ...; +# 192| 0: [LocalVariableDeclAndInitExpr] Int32 v1 = ... +# 192| 0: [IntLiteral] 2 +# 192| 1: [LocalVariableAccess] access to local variable v1 +# 193| 1: [LocalVariableDeclStmt] ... ...; +# 193| 0: [LocalVariableDeclAndInitExpr] Int32 r1 = ... +# 193| 0: [RefExpr] ref ... +# 193| 0: [LocalVariableAccess] access to local variable v1 +# 193| 1: [LocalVariableAccess] access to local variable r1 +# 194| 2: [LocalVariableDeclStmt] ... ...; +# 194| 0: [LocalVariableDeclAndInitExpr] Int32[] array = ... +# 194| 0: [ArrayCreation] array creation of type Int32[] +# 194| 0: [IntLiteral] 10 +# 194| 1: [LocalVariableAccess] access to local variable array +# 195| 3: [ExprStmt] ...; +# 195| 0: [AssignExpr] ... = ... +# 195| 0: [IntLiteral] 3 +# 195| 1: [LocalVariableAccess] access to local variable r1 +# 196| 4: [ExprStmt] ...; +# 196| 0: [AssignExpr] ... = ... +# 196| 0: [ArrayAccess] access to array element +# 196| -1: [LocalVariableAccess] access to local variable array +# 196| 0: [IntLiteral] 1 +# 196| 1: [LocalVariableAccess] access to local variable r1 +# 197| 5: [LocalVariableDeclStmt] ... ...; +# 197| 0: [LocalVariableDeclAndInitExpr] Int32 r2 = ... +# 197| 0: [RefExpr] ref ... +# 197| 0: [ArrayAccess] access to array element +# 197| -1: [LocalVariableAccess] access to local variable array +# 197| 0: [IntLiteral] 3 +# 197| 1: [LocalVariableAccess] access to local variable r2 +# 198| 6: [LocalVariableDeclStmt] ... ...; +# 198| 0: [LocalVariableDeclAndInitExpr] Int32 r3 = ... +# 198| 0: [RefExpr] ref ... +# 198| 0: [LocalVariableAccess] access to local variable r1 +# 198| 1: [LocalVariableAccess] access to local variable r3 +# 199| 7: [ExprStmt] ...; +# 199| 0: [AssignExpr] ... = ... +# 199| 0: [MethodCall] call to method F2 +# 199| 0: [LocalVariableAccess] access to local variable v1 +# 199| 1: [LocalVariableAccess] access to local variable v1 +# 200| 8: [LocalVariableDeclStmt] ... ...; +# 200| 0: [LocalVariableDeclAndInitExpr] Int32 r4 = ... +# 200| 0: [RefExpr] ref ... +# 200| 0: [MethodCall] call to method F2 +# 200| 0: [LocalVariableAccess] access to local variable r1 +# 200| 1: [LocalVariableAccess] access to local variable r4 +# 201| 9: [ExprStmt] ...; +# 201| 0: [AssignExpr] ... = ... +# 201| 0: [IntLiteral] 3 +# 201| 1: [MethodCall] call to method F2 +# 201| 0: [LocalVariableAccess] access to local variable r1 +# 204| 6: [Method] F2 #-----| 2: (Parameters) -# 209| 0: [Parameter] p -# 212| [Class] Discards -# 214| 5: [Method] f +# 204| 0: [Parameter] p +# 205| 4: [BlockStmt] {...} +# 206| 0: [LocalFunctionStmt] F3(...) +# 206| 0: [LocalFunction] F3 +#-----| 2: (Parameters) +# 206| 0: [Parameter] q +# 206| 4: [BlockStmt] {...} +# 206| 0: [ReturnStmt] return ...; +# 206| 0: [RefExpr] ref ... +# 206| 0: [ParameterAccess] access to parameter q +# 207| 1: [ReturnStmt] return ...; +# 207| 0: [RefExpr] ref ... +# 207| 0: [ParameterAccess] access to parameter p +# 210| 7: [DelegateType] RefFn #-----| 2: (Parameters) -# 214| 0: [Parameter] x -# 215| 4: [BlockStmt] {...} -# 216| 0: [ExprStmt] ...; -# 216| 0: [AssignExpr] ... = ... -# 216| 0: [BoolLiteral] false -# 216| 1: [ParameterAccess] access to parameter x -# 217| 1: [ReturnStmt] return ...; -# 217| 0: [TupleExpr] (..., ...) -# 217| 0: [IntLiteral] 0 -# 217| 1: [DoubleLiteral] 0 -# 220| 6: [Method] Test -# 221| 4: [BlockStmt] {...} -# 222| 0: [ExprStmt] ...; -# 222| 0: [AssignExpr] ... = ... -# 222| 0: [MethodCall] call to method f -# 222| 0: [DiscardExpr] _ -# 222| 1: [DiscardExpr] _ -# 223| 1: [ExprStmt] ...; +# 210| 0: [Parameter] p +# 213| [Class] Discards +# 215| 5: [Method] f +#-----| 2: (Parameters) +# 215| 0: [Parameter] x +# 216| 4: [BlockStmt] {...} +# 217| 0: [ExprStmt] ...; +# 217| 0: [AssignExpr] ... = ... +# 217| 0: [BoolLiteral] false +# 217| 1: [ParameterAccess] access to parameter x +# 218| 1: [ReturnStmt] return ...; +# 218| 0: [TupleExpr] (..., ...) +# 218| 0: [IntLiteral] 0 +# 218| 1: [DoubleLiteral] 0 +# 221| 6: [Method] Test +# 222| 4: [BlockStmt] {...} +# 223| 0: [ExprStmt] ...; # 223| 0: [AssignExpr] ... = ... # 223| 0: [MethodCall] call to method f # 223| 0: [DiscardExpr] _ -# 223| 1: [TupleExpr] (..., ...) -# 223| 0: [DiscardExpr] _ -# 223| 1: [DiscardExpr] _ -# 224| 2: [ExprStmt] ...; +# 223| 1: [DiscardExpr] _ +# 224| 1: [ExprStmt] ...; # 224| 0: [AssignExpr] ... = ... # 224| 0: [MethodCall] call to method f # 224| 0: [DiscardExpr] _ # 224| 1: [TupleExpr] (..., ...) -# 224| 0: [LocalVariableDeclExpr] Int32 x +# 224| 0: [DiscardExpr] _ # 224| 1: [DiscardExpr] _ -# 225| 3: [ExprStmt] ...; +# 225| 2: [ExprStmt] ...; # 225| 0: [AssignExpr] ... = ... # 225| 0: [MethodCall] call to method f -# 225| 0: [LocalVariableAccess,LocalVariableDeclExpr] Boolean z -# 225| 1: [TupleExpr] (..., ...) # 225| 0: [DiscardExpr] _ -# 225| 1: [LocalVariableDeclExpr] Double y -# 229| [Class] Patterns -# 231| 5: [Method] Test -# 232| 4: [BlockStmt] {...} -# 233| 0: [LocalVariableDeclStmt] ... ...; -# 233| 0: [LocalVariableDeclAndInitExpr] Object o = ... -# 233| 0: [NullLiteral] null -# 233| 1: [LocalVariableAccess] access to local variable o -# 234| 1: [IfStmt] if (...) ... -# 234| 0: [LogicalAndExpr] ... && ... -# 234| 0: [IsExpr] ... is ... -# 234| 0: [LocalVariableAccess] access to local variable o -# 234| 1: [VariablePatternExpr] Int32 i1 -# 234| 1: [GTExpr] ... > ... -# 234| 0: [LocalVariableAccess] access to local variable i1 -# 234| 1: [IntLiteral] 0 -# 235| 1: [BlockStmt] {...} -# 236| 0: [ExprStmt] ...; -# 236| 0: [MethodCall] call to method WriteLine -# 236| -1: [TypeAccess] access to type Console -# 236| 0: [InterpolatedStringExpr] $"..." -# 236| 0: [StringLiteral] "int " -# 236| 1: [LocalVariableAccess] access to local variable i1 -# 238| 2: [IfStmt] if (...) ... -# 238| 0: [IsExpr] ... is ... -# 238| 0: [LocalVariableAccess] access to local variable o -# 238| 1: [VariablePatternExpr] String s1 -# 239| 1: [BlockStmt] {...} -# 240| 0: [ExprStmt] ...; -# 240| 0: [MethodCall] call to method WriteLine -# 240| -1: [TypeAccess] access to type Console -# 240| 0: [InterpolatedStringExpr] $"..." -# 240| 0: [StringLiteral] "string " -# 240| 1: [LocalVariableAccess] access to local variable s1 -# 242| 2: [IfStmt] if (...) ... -# 242| 0: [IsExpr] ... is ... -# 242| 0: [LocalVariableAccess] access to local variable o -# 242| 1: [TypeAccessPatternExpr] access to type Double -# 243| 1: [BlockStmt] {...} -# 245| 2: [IfStmt] if (...) ... -# 245| 0: [IsExpr] ... is ... -# 245| 0: [LocalVariableAccess] access to local variable o -# 245| 1: [VariablePatternExpr] Object v1 -# 246| 1: [BlockStmt] {...} -# 249| 2: [SwitchStmt] switch (...) {...} -# 249| 0: [LocalVariableAccess] access to local variable o -# 251| 0: [ConstCase] case ...: -# 251| 0: [ConstantPatternExpr,StringLiteral] "xyz" -# 252| 1: [BreakStmt] break; -# 253| 2: [ConstCase] case ...: -# 253| 0: [ConstantPatternExpr,StringLiteral] "" -# 253| 1: [LTExpr] ... < ... -# 253| 0: [IntLiteral] 1 -# 253| 1: [IntLiteral] 2 -# 254| 3: [BreakStmt] break; -# 255| 4: [ConstCase] case ...: -# 255| 0: [ConstantPatternExpr,StringLiteral] "x" -# 255| 1: [IsExpr] ... is ... -# 255| 0: [LocalVariableAccess] access to local variable o -# 255| 1: [VariablePatternExpr] String s4 -# 256| 5: [ExprStmt] ...; -# 256| 0: [MethodCall] call to method WriteLine -# 256| -1: [TypeAccess] access to type Console -# 256| 0: [InterpolatedStringExpr] $"..." -# 256| 0: [StringLiteral] "x " -# 256| 1: [LocalVariableAccess] access to local variable s4 -# 257| 6: [BreakStmt] break; -# 258| 7: [CaseStmt] case ...: -# 258| 0: [VariablePatternExpr] Int32 i2 -# 258| 1: [GTExpr] ... > ... -# 258| 0: [LocalVariableAccess] access to local variable i2 -# 258| 1: [IntLiteral] 0 -# 259| 8: [ExprStmt] ...; -# 259| 0: [MethodCall] call to method WriteLine -# 259| -1: [TypeAccess] access to type Console -# 259| 0: [InterpolatedStringExpr] $"..." -# 259| 0: [StringLiteral] "positive " -# 259| 1: [LocalVariableAccess] access to local variable i2 -# 260| 9: [BreakStmt] break; -# 261| 10: [CaseStmt] case ...: -# 261| 0: [VariablePatternExpr] Int32 i3 -# 262| 11: [ExprStmt] ...; -# 262| 0: [MethodCall] call to method WriteLine -# 262| -1: [TypeAccess] access to type Console -# 262| 0: [InterpolatedStringExpr] $"..." -# 262| 0: [StringLiteral] "int " -# 262| 1: [LocalVariableAccess] access to local variable i3 -# 263| 12: [BreakStmt] break; -# 264| 13: [CaseStmt] case ...: -# 264| 0: [VariablePatternExpr] String s2 -# 265| 14: [ExprStmt] ...; -# 265| 0: [MethodCall] call to method WriteLine -# 265| -1: [TypeAccess] access to type Console -# 265| 0: [InterpolatedStringExpr] $"..." -# 265| 0: [StringLiteral] "string " -# 265| 1: [LocalVariableAccess] access to local variable s2 -# 266| 15: [BreakStmt] break; -# 267| 16: [CaseStmt] case ...: -# 267| 0: [TypeAccessPatternExpr] access to type Double -# 268| 17: [ExprStmt] ...; -# 268| 0: [MethodCall] call to method WriteLine -# 268| -1: [TypeAccess] access to type Console -# 268| 0: [StringLiteral] "Double" -# 269| 18: [BreakStmt] break; -# 270| 19: [CaseStmt] case ...: -# 270| 0: [VariablePatternExpr] Object v2 -# 271| 20: [BreakStmt] break; -# 272| 21: [DefaultCase] default: -# 273| 22: [ExprStmt] ...; -# 273| 0: [MethodCall] call to method WriteLine -# 273| -1: [TypeAccess] access to type Console -# 273| 0: [StringLiteral] "Something else" -# 274| 23: [BreakStmt] break; -# 279| [Class] ForeachStatements -# 281| 5: [Method] Test -# 282| 4: [BlockStmt] {...} -# 283| 0: [LocalVariableDeclStmt] ... ...; -# 283| 0: [LocalVariableDeclAndInitExpr] Dictionary dict = ... -# 283| 0: [ObjectCreation] object creation of type Dictionary -# 283| 1: [LocalVariableAccess] access to local variable dict -# 284| 1: [LocalVariableDeclStmt] ... ...; -# 284| 0: [LocalVariableDeclAndInitExpr] IEnumerable<(Int32,String)> list = ... -# 284| 0: [MethodCall] call to method Select -# 284| -1: [LocalVariableAccess] access to local variable dict -# 284| 0: [LambdaExpr] (...) => ... +# 225| 1: [TupleExpr] (..., ...) +# 225| 0: [LocalVariableDeclExpr] Int32 x +# 225| 1: [DiscardExpr] _ +# 226| 3: [ExprStmt] ...; +# 226| 0: [AssignExpr] ... = ... +# 226| 0: [MethodCall] call to method f +# 226| 0: [LocalVariableAccess,LocalVariableDeclExpr] Boolean z +# 226| 1: [TupleExpr] (..., ...) +# 226| 0: [DiscardExpr] _ +# 226| 1: [LocalVariableDeclExpr] Double y +# 230| [Class] Patterns +# 232| 5: [Method] Test +# 233| 4: [BlockStmt] {...} +# 234| 0: [LocalVariableDeclStmt] ... ...; +# 234| 0: [LocalVariableDeclAndInitExpr] Object o = ... +# 234| 0: [NullLiteral] null +# 234| 1: [LocalVariableAccess] access to local variable o +# 235| 1: [IfStmt] if (...) ... +# 235| 0: [LogicalAndExpr] ... && ... +# 235| 0: [IsExpr] ... is ... +# 235| 0: [LocalVariableAccess] access to local variable o +# 235| 1: [VariablePatternExpr] Int32 i1 +# 235| 1: [GTExpr] ... > ... +# 235| 0: [LocalVariableAccess] access to local variable i1 +# 235| 1: [IntLiteral] 0 +# 236| 1: [BlockStmt] {...} +# 237| 0: [ExprStmt] ...; +# 237| 0: [MethodCall] call to method WriteLine +# 237| -1: [TypeAccess] access to type Console +# 237| 0: [InterpolatedStringExpr] $"..." +# 237| 0: [StringLiteral] "int " +# 237| 1: [LocalVariableAccess] access to local variable i1 +# 239| 2: [IfStmt] if (...) ... +# 239| 0: [IsExpr] ... is ... +# 239| 0: [LocalVariableAccess] access to local variable o +# 239| 1: [VariablePatternExpr] String s1 +# 240| 1: [BlockStmt] {...} +# 241| 0: [ExprStmt] ...; +# 241| 0: [MethodCall] call to method WriteLine +# 241| -1: [TypeAccess] access to type Console +# 241| 0: [InterpolatedStringExpr] $"..." +# 241| 0: [StringLiteral] "string " +# 241| 1: [LocalVariableAccess] access to local variable s1 +# 243| 2: [IfStmt] if (...) ... +# 243| 0: [IsExpr] ... is ... +# 243| 0: [LocalVariableAccess] access to local variable o +# 243| 1: [TypeAccessPatternExpr] access to type Double +# 244| 1: [BlockStmt] {...} +# 246| 2: [IfStmt] if (...) ... +# 246| 0: [IsExpr] ... is ... +# 246| 0: [LocalVariableAccess] access to local variable o +# 246| 1: [VariablePatternExpr] Object v1 +# 247| 1: [BlockStmt] {...} +# 250| 2: [SwitchStmt] switch (...) {...} +# 250| 0: [LocalVariableAccess] access to local variable o +# 252| 0: [ConstCase] case ...: +# 252| 0: [ConstantPatternExpr,StringLiteral] "xyz" +# 253| 1: [BreakStmt] break; +# 254| 2: [ConstCase] case ...: +# 254| 0: [ConstantPatternExpr,StringLiteral] "" +# 254| 1: [LTExpr] ... < ... +# 254| 0: [IntLiteral] 1 +# 254| 1: [IntLiteral] 2 +# 255| 3: [BreakStmt] break; +# 256| 4: [ConstCase] case ...: +# 256| 0: [ConstantPatternExpr,StringLiteral] "x" +# 256| 1: [IsExpr] ... is ... +# 256| 0: [LocalVariableAccess] access to local variable o +# 256| 1: [VariablePatternExpr] String s4 +# 257| 5: [ExprStmt] ...; +# 257| 0: [MethodCall] call to method WriteLine +# 257| -1: [TypeAccess] access to type Console +# 257| 0: [InterpolatedStringExpr] $"..." +# 257| 0: [StringLiteral] "x " +# 257| 1: [LocalVariableAccess] access to local variable s4 +# 258| 6: [BreakStmt] break; +# 259| 7: [CaseStmt] case ...: +# 259| 0: [VariablePatternExpr] Int32 i2 +# 259| 1: [GTExpr] ... > ... +# 259| 0: [LocalVariableAccess] access to local variable i2 +# 259| 1: [IntLiteral] 0 +# 260| 8: [ExprStmt] ...; +# 260| 0: [MethodCall] call to method WriteLine +# 260| -1: [TypeAccess] access to type Console +# 260| 0: [InterpolatedStringExpr] $"..." +# 260| 0: [StringLiteral] "positive " +# 260| 1: [LocalVariableAccess] access to local variable i2 +# 261| 9: [BreakStmt] break; +# 262| 10: [CaseStmt] case ...: +# 262| 0: [VariablePatternExpr] Int32 i3 +# 263| 11: [ExprStmt] ...; +# 263| 0: [MethodCall] call to method WriteLine +# 263| -1: [TypeAccess] access to type Console +# 263| 0: [InterpolatedStringExpr] $"..." +# 263| 0: [StringLiteral] "int " +# 263| 1: [LocalVariableAccess] access to local variable i3 +# 264| 12: [BreakStmt] break; +# 265| 13: [CaseStmt] case ...: +# 265| 0: [VariablePatternExpr] String s2 +# 266| 14: [ExprStmt] ...; +# 266| 0: [MethodCall] call to method WriteLine +# 266| -1: [TypeAccess] access to type Console +# 266| 0: [InterpolatedStringExpr] $"..." +# 266| 0: [StringLiteral] "string " +# 266| 1: [LocalVariableAccess] access to local variable s2 +# 267| 15: [BreakStmt] break; +# 268| 16: [CaseStmt] case ...: +# 268| 0: [TypeAccessPatternExpr] access to type Double +# 269| 17: [ExprStmt] ...; +# 269| 0: [MethodCall] call to method WriteLine +# 269| -1: [TypeAccess] access to type Console +# 269| 0: [StringLiteral] "Double" +# 270| 18: [BreakStmt] break; +# 271| 19: [CaseStmt] case ...: +# 271| 0: [VariablePatternExpr] Object v2 +# 272| 20: [BreakStmt] break; +# 273| 21: [DefaultCase] default: +# 274| 22: [ExprStmt] ...; +# 274| 0: [MethodCall] call to method WriteLine +# 274| -1: [TypeAccess] access to type Console +# 274| 0: [StringLiteral] "Something else" +# 275| 23: [BreakStmt] break; +# 280| [Class] ForeachStatements +# 282| 5: [Method] Test +# 283| 4: [BlockStmt] {...} +# 284| 0: [LocalVariableDeclStmt] ... ...; +# 284| 0: [LocalVariableDeclAndInitExpr] Dictionary dict = ... +# 284| 0: [ObjectCreation] object creation of type Dictionary +# 284| 1: [LocalVariableAccess] access to local variable dict +# 285| 1: [LocalVariableDeclStmt] ... ...; +# 285| 0: [LocalVariableDeclAndInitExpr] IEnumerable<(Int32,String)> list = ... +# 285| 0: [MethodCall] call to method Select +# 285| -1: [LocalVariableAccess] access to local variable dict +# 285| 0: [LambdaExpr] (...) => ... #-----| 2: (Parameters) -# 284| 0: [Parameter] item -# 284| 4: [TupleExpr] (..., ...) -# 284| 0: [PropertyCall] access to property Key -# 284| -1: [ParameterAccess] access to parameter item -# 284| 1: [PropertyCall] access to property Value -# 284| -1: [ParameterAccess] access to parameter item -# 284| 1: [LocalVariableAccess] access to local variable list -# 286| 2: [ForeachStmt] foreach (... ... in ...) ... -# 286| 0: [TupleExpr] (..., ...) -# 286| 0: [LocalVariableDeclExpr] Int32 a -# 286| 1: [LocalVariableDeclExpr] String b -# 286| 1: [LocalVariableAccess] access to local variable list -# 286| 2: [BlockStmt] {...} -# 288| 3: [ForeachStmt] foreach (... ... in ...) ... -# 288| 0: [TupleExpr] (..., ...) -# 288| 0: [LocalVariableDeclExpr] Int32 a -# 288| 1: [LocalVariableDeclExpr] String b -# 288| 1: [LocalVariableAccess] access to local variable list -# 288| 2: [BlockStmt] {...} -# 290| 4: [ForeachStmt] foreach (... ... in ...) ... -# 290| 0: [TupleExpr] (..., ...) -# 290| 0: [LocalVariableDeclExpr] Int32 a -# 290| 1: [LocalVariableDeclExpr] String b -# 290| 1: [LocalVariableAccess] access to local variable list -# 290| 2: [BlockStmt] {...} -# 294| [Class] ForLoops -# 296| 5: [Method] Test -# 297| 4: [BlockStmt] {...} -# 298| 0: [ForStmt] for (...;...;...) ... -# 298| -1: [LocalVariableDeclAndInitExpr] Int32 x = ... -# 298| 0: [IntLiteral] 0 -# 298| 1: [LocalVariableAccess] access to local variable x -# 298| 0: [LogicalAndExpr] ... && ... -# 298| 0: [LTExpr] ... < ... -# 298| 0: [LocalVariableAccess] access to local variable x -# 298| 1: [IntLiteral] 10 -# 298| 1: [IsExpr] ... is ... -# 298| 0: [LocalVariableAccess] access to local variable x -# 298| 1: [VariablePatternExpr] Int32 y -# 298| 1: [PreIncrExpr] ++... -# 298| 0: [LocalVariableAccess] access to local variable x -# 299| 2: [BlockStmt] {...} -# 300| 0: [ExprStmt] ...; -# 300| 0: [MethodCall] call to method WriteLine -# 300| -1: [TypeAccess] access to type Console -# 300| 0: [LocalVariableAccess] access to local variable y +# 285| 0: [Parameter] item +# 285| 4: [TupleExpr] (..., ...) +# 285| 0: [PropertyCall] access to property Key +# 285| -1: [ParameterAccess] access to parameter item +# 285| 1: [PropertyCall] access to property Value +# 285| -1: [ParameterAccess] access to parameter item +# 285| 1: [LocalVariableAccess] access to local variable list +# 287| 2: [ForeachStmt] foreach (... ... in ...) ... +# 287| 0: [TupleExpr] (..., ...) +# 287| 0: [LocalVariableDeclExpr] Int32 a +# 287| 1: [LocalVariableDeclExpr] String b +# 287| 1: [LocalVariableAccess] access to local variable list +# 287| 2: [BlockStmt] {...} +# 289| 3: [ForeachStmt] foreach (... ... in ...) ... +# 289| 0: [TupleExpr] (..., ...) +# 289| 0: [LocalVariableDeclExpr] Int32 a +# 289| 1: [LocalVariableDeclExpr] String b +# 289| 1: [LocalVariableAccess] access to local variable list +# 289| 2: [BlockStmt] {...} +# 291| 4: [ForeachStmt] foreach (... ... in ...) ... +# 291| 0: [TupleExpr] (..., ...) +# 291| 0: [LocalVariableDeclExpr] Int32 a +# 291| 1: [LocalVariableDeclExpr] String b +# 291| 1: [LocalVariableAccess] access to local variable list +# 291| 2: [BlockStmt] {...} +# 295| [Class] ForLoops +# 297| 5: [Method] Test +# 298| 4: [BlockStmt] {...} +# 299| 0: [ForStmt] for (...;...;...) ... +# 299| -1: [LocalVariableDeclAndInitExpr] Int32 x = ... +# 299| 0: [IntLiteral] 0 +# 299| 1: [LocalVariableAccess] access to local variable x +# 299| 0: [LogicalAndExpr] ... && ... +# 299| 0: [LTExpr] ... < ... +# 299| 0: [LocalVariableAccess] access to local variable x +# 299| 1: [IntLiteral] 10 +# 299| 1: [IsExpr] ... is ... +# 299| 0: [LocalVariableAccess] access to local variable x +# 299| 1: [VariablePatternExpr] Int32 y +# 299| 1: [PreIncrExpr] ++... +# 299| 0: [LocalVariableAccess] access to local variable x +# 300| 2: [BlockStmt] {...} +# 301| 0: [ExprStmt] ...; +# 301| 0: [MethodCall] call to method WriteLine +# 301| -1: [TypeAccess] access to type Console +# 301| 0: [LocalVariableAccess] access to local variable y diff --git a/csharp/ql/test/library-tests/csharp7/RefDelegates.expected b/csharp/ql/test/library-tests/csharp7/RefDelegates.expected index b84804d88c3..b26c77efc50 100644 --- a/csharp/ql/test/library-tests/csharp7/RefDelegates.expected +++ b/csharp/ql/test/library-tests/csharp7/RefDelegates.expected @@ -1 +1 @@ -| CSharp7.cs:209:22:209:26 | RefFn | +| CSharp7.cs:210:22:210:26 | RefFn | diff --git a/csharp/ql/test/library-tests/csharp7/RefExprs.expected b/csharp/ql/test/library-tests/csharp7/RefExprs.expected index f8882edbe6b..bb1a22d1e19 100644 --- a/csharp/ql/test/library-tests/csharp7/RefExprs.expected +++ b/csharp/ql/test/library-tests/csharp7/RefExprs.expected @@ -1,6 +1,6 @@ -| CSharp7.cs:192:22:192:27 | ref ... | CSharp7.cs:192:26:192:27 | access to local variable v1 | Int32 | -| CSharp7.cs:196:22:196:33 | ref ... | CSharp7.cs:196:26:196:33 | access to array element | Int32 | -| CSharp7.cs:197:22:197:27 | ref ... | CSharp7.cs:197:26:197:27 | access to local variable r1 | Int32 | -| CSharp7.cs:199:22:199:35 | ref ... | CSharp7.cs:199:26:199:35 | call to method F2 | Int32 | -| CSharp7.cs:205:40:205:44 | ref ... | CSharp7.cs:205:44:205:44 | access to parameter q | Int32 | -| CSharp7.cs:206:16:206:20 | ref ... | CSharp7.cs:206:20:206:20 | access to parameter p | Int32 | +| CSharp7.cs:193:22:193:27 | ref ... | CSharp7.cs:193:26:193:27 | access to local variable v1 | Int32 | +| CSharp7.cs:197:22:197:33 | ref ... | CSharp7.cs:197:26:197:33 | access to array element | Int32 | +| CSharp7.cs:198:22:198:27 | ref ... | CSharp7.cs:198:26:198:27 | access to local variable r1 | Int32 | +| CSharp7.cs:200:22:200:35 | ref ... | CSharp7.cs:200:26:200:35 | call to method F2 | Int32 | +| CSharp7.cs:206:40:206:44 | ref ... | CSharp7.cs:206:44:206:44 | access to parameter q | Int32 | +| CSharp7.cs:207:16:207:20 | ref ... | CSharp7.cs:207:20:207:20 | access to parameter p | Int32 | diff --git a/csharp/ql/test/library-tests/csharp7/RefFunctions.expected b/csharp/ql/test/library-tests/csharp7/RefFunctions.expected index a9740121ee4..c2899f5443f 100644 --- a/csharp/ql/test/library-tests/csharp7/RefFunctions.expected +++ b/csharp/ql/test/library-tests/csharp7/RefFunctions.expected @@ -1,2 +1,2 @@ -| CSharp7.cs:203:13:203:14 | F2 | -| CSharp7.cs:205:9:205:47 | F3 | +| CSharp7.cs:204:13:204:14 | F2 | +| CSharp7.cs:206:9:206:47 | F3 | diff --git a/csharp/ql/test/library-tests/csharp7/RefVariables.expected b/csharp/ql/test/library-tests/csharp7/RefVariables.expected index 5d065352dd2..ed8f2d59b45 100644 --- a/csharp/ql/test/library-tests/csharp7/RefVariables.expected +++ b/csharp/ql/test/library-tests/csharp7/RefVariables.expected @@ -1,4 +1,4 @@ -| CSharp7.cs:192:17:192:18 | r1 | -| CSharp7.cs:196:17:196:18 | r2 | -| CSharp7.cs:197:17:197:18 | r3 | -| CSharp7.cs:199:17:199:18 | r4 | +| CSharp7.cs:193:17:193:18 | r1 | +| CSharp7.cs:197:17:197:18 | r2 | +| CSharp7.cs:198:17:198:18 | r3 | +| CSharp7.cs:200:17:200:18 | r4 | diff --git a/csharp/ql/test/library-tests/csharp7/TaintReaches.expected b/csharp/ql/test/library-tests/csharp7/TaintReaches.expected index d5d232488ad..88c531506d9 100644 --- a/csharp/ql/test/library-tests/csharp7/TaintReaches.expected +++ b/csharp/ql/test/library-tests/csharp7/TaintReaches.expected @@ -25,14 +25,14 @@ | CSharp7.cs:114:50:114:58 | "DefUse2" | CSharp7.cs:114:38:114:67 | ... = ... | | CSharp7.cs:114:50:114:58 | "DefUse2" | CSharp7.cs:114:49:114:67 | (..., ...) | | CSharp7.cs:123:28:123:36 | "DefUse3" | CSharp7.cs:123:22:123:36 | ... = ... | -| CSharp7.cs:176:22:176:30 | "tainted" | CSharp7.cs:176:16:176:30 | SSA def(src) | -| CSharp7.cs:176:22:176:30 | "tainted" | CSharp7.cs:181:23:181:25 | access to local variable src | -| CSharp7.cs:176:22:176:30 | "tainted" | CSharp7.cs:182:23:182:25 | access to local variable src | -| CSharp7.cs:176:22:176:30 | "tainted" | CSharp7.cs:183:23:183:25 | access to local variable src | -| CSharp7.cs:177:38:177:39 | "" | CSharp7.cs:177:31:177:39 | ... + ... | -| CSharp7.cs:236:33:236:36 | "int " | CSharp7.cs:236:31:236:41 | $"..." | -| CSharp7.cs:240:33:240:39 | "string " | CSharp7.cs:240:31:240:44 | $"..." | -| CSharp7.cs:256:37:256:38 | "x " | CSharp7.cs:256:35:256:43 | $"..." | -| CSharp7.cs:259:37:259:45 | "positive " | CSharp7.cs:259:35:259:50 | $"..." | -| CSharp7.cs:262:37:262:40 | "int " | CSharp7.cs:262:35:262:45 | $"..." | -| CSharp7.cs:265:37:265:43 | "string " | CSharp7.cs:265:35:265:48 | $"..." | +| CSharp7.cs:177:22:177:30 | "tainted" | CSharp7.cs:177:16:177:30 | SSA def(src) | +| CSharp7.cs:177:22:177:30 | "tainted" | CSharp7.cs:182:23:182:25 | access to local variable src | +| CSharp7.cs:177:22:177:30 | "tainted" | CSharp7.cs:183:23:183:25 | access to local variable src | +| CSharp7.cs:177:22:177:30 | "tainted" | CSharp7.cs:184:23:184:25 | access to local variable src | +| CSharp7.cs:178:38:178:39 | "" | CSharp7.cs:178:31:178:39 | ... + ... | +| CSharp7.cs:237:33:237:36 | "int " | CSharp7.cs:237:31:237:41 | $"..." | +| CSharp7.cs:241:33:241:39 | "string " | CSharp7.cs:241:31:241:44 | $"..." | +| CSharp7.cs:257:37:257:38 | "x " | CSharp7.cs:257:35:257:43 | $"..." | +| CSharp7.cs:260:37:260:45 | "positive " | CSharp7.cs:260:35:260:50 | $"..." | +| CSharp7.cs:263:37:263:40 | "int " | CSharp7.cs:263:35:263:45 | $"..." | +| CSharp7.cs:266:37:266:43 | "string " | CSharp7.cs:266:35:266:48 | $"..." | diff --git a/csharp/ql/test/library-tests/csharp7/TupleAccess.expected b/csharp/ql/test/library-tests/csharp7/TupleAccess.expected index 437ee46820d..978a9b041c0 100644 --- a/csharp/ql/test/library-tests/csharp7/TupleAccess.expected +++ b/csharp/ql/test/library-tests/csharp7/TupleAccess.expected @@ -1,4 +1,4 @@ -| CSharp7.cs:66:16:66:21 | (..., ...) | read | +| CSharp7.cs:66:16:66:27 | (..., ...) | read | | CSharp7.cs:71:9:71:22 | (..., ...) | write | | CSharp7.cs:73:9:73:14 | (..., ...) | write | | CSharp7.cs:75:9:75:23 | (..., ...) | write | @@ -35,11 +35,11 @@ | CSharp7.cs:114:38:114:45 | (..., ...) | write | | CSharp7.cs:114:49:114:67 | (..., ...) | read | | CSharp7.cs:114:61:114:66 | (..., ...) | read | -| CSharp7.cs:217:16:217:23 | (..., ...) | read | -| CSharp7.cs:223:9:223:14 | (..., ...) | write | -| CSharp7.cs:224:9:224:18 | (..., ...) | write | +| CSharp7.cs:218:16:218:23 | (..., ...) | read | +| CSharp7.cs:224:9:224:14 | (..., ...) | write | | CSharp7.cs:225:9:225:18 | (..., ...) | write | -| CSharp7.cs:284:40:284:61 | (..., ...) | read | -| CSharp7.cs:286:18:286:34 | (..., ...) | write | -| CSharp7.cs:288:18:288:31 | (..., ...) | write | -| CSharp7.cs:290:18:290:27 | (..., ...) | write | +| CSharp7.cs:226:9:226:18 | (..., ...) | write | +| CSharp7.cs:285:40:285:61 | (..., ...) | read | +| CSharp7.cs:287:18:287:34 | (..., ...) | write | +| CSharp7.cs:289:18:289:31 | (..., ...) | write | +| CSharp7.cs:291:18:291:27 | (..., ...) | write | diff --git a/csharp/ql/test/library-tests/csharp7/TupleExpr.expected b/csharp/ql/test/library-tests/csharp7/TupleExpr.expected index ec92d01d1ee..7e3a52e86cd 100644 --- a/csharp/ql/test/library-tests/csharp7/TupleExpr.expected +++ b/csharp/ql/test/library-tests/csharp7/TupleExpr.expected @@ -1,5 +1,5 @@ -| CSharp7.cs:66:16:66:21 | (..., ...) | 0 | CSharp7.cs:66:17:66:17 | 1 | -| CSharp7.cs:66:16:66:21 | (..., ...) | 1 | CSharp7.cs:66:20:66:20 | 2 | +| CSharp7.cs:66:16:66:27 | (..., ...) | 0 | CSharp7.cs:66:20:66:20 | 1 | +| CSharp7.cs:66:16:66:27 | (..., ...) | 1 | CSharp7.cs:66:26:66:26 | 2 | | CSharp7.cs:71:9:71:22 | (..., ...) | 0 | CSharp7.cs:71:14:71:14 | Int32 x | | CSharp7.cs:71:9:71:22 | (..., ...) | 1 | CSharp7.cs:71:21:71:21 | Int32 y | | CSharp7.cs:73:9:73:14 | (..., ...) | 0 | CSharp7.cs:73:10:73:10 | access to local variable x | @@ -74,19 +74,19 @@ | CSharp7.cs:114:49:114:67 | (..., ...) | 1 | CSharp7.cs:114:61:114:66 | (..., ...) | | CSharp7.cs:114:61:114:66 | (..., ...) | 0 | CSharp7.cs:114:62:114:62 | 0 | | CSharp7.cs:114:61:114:66 | (..., ...) | 1 | CSharp7.cs:114:65:114:65 | 1 | -| CSharp7.cs:217:16:217:23 | (..., ...) | 0 | CSharp7.cs:217:17:217:17 | 0 | -| CSharp7.cs:217:16:217:23 | (..., ...) | 1 | CSharp7.cs:217:20:217:22 | 0 | -| CSharp7.cs:223:9:223:14 | (..., ...) | 0 | CSharp7.cs:223:10:223:10 | _ | -| CSharp7.cs:223:9:223:14 | (..., ...) | 1 | CSharp7.cs:223:13:223:13 | _ | -| CSharp7.cs:224:9:224:18 | (..., ...) | 0 | CSharp7.cs:224:14:224:14 | Int32 x | -| CSharp7.cs:224:9:224:18 | (..., ...) | 1 | CSharp7.cs:224:17:224:17 | _ | -| CSharp7.cs:225:9:225:18 | (..., ...) | 0 | CSharp7.cs:225:10:225:10 | _ | -| CSharp7.cs:225:9:225:18 | (..., ...) | 1 | CSharp7.cs:225:17:225:17 | Double y | -| CSharp7.cs:284:40:284:61 | (..., ...) | 0 | CSharp7.cs:284:41:284:48 | access to property Key | -| CSharp7.cs:284:40:284:61 | (..., ...) | 1 | CSharp7.cs:284:51:284:60 | access to property Value | -| CSharp7.cs:286:18:286:34 | (..., ...) | 0 | CSharp7.cs:286:23:286:23 | Int32 a | -| CSharp7.cs:286:18:286:34 | (..., ...) | 1 | CSharp7.cs:286:33:286:33 | String b | -| CSharp7.cs:288:18:288:31 | (..., ...) | 0 | CSharp7.cs:288:23:288:23 | Int32 a | -| CSharp7.cs:288:18:288:31 | (..., ...) | 1 | CSharp7.cs:288:30:288:30 | String b | -| CSharp7.cs:290:18:290:27 | (..., ...) | 0 | CSharp7.cs:290:23:290:23 | Int32 a | -| CSharp7.cs:290:18:290:27 | (..., ...) | 1 | CSharp7.cs:290:26:290:26 | String b | +| CSharp7.cs:218:16:218:23 | (..., ...) | 0 | CSharp7.cs:218:17:218:17 | 0 | +| CSharp7.cs:218:16:218:23 | (..., ...) | 1 | CSharp7.cs:218:20:218:22 | 0 | +| CSharp7.cs:224:9:224:14 | (..., ...) | 0 | CSharp7.cs:224:10:224:10 | _ | +| CSharp7.cs:224:9:224:14 | (..., ...) | 1 | CSharp7.cs:224:13:224:13 | _ | +| CSharp7.cs:225:9:225:18 | (..., ...) | 0 | CSharp7.cs:225:14:225:14 | Int32 x | +| CSharp7.cs:225:9:225:18 | (..., ...) | 1 | CSharp7.cs:225:17:225:17 | _ | +| CSharp7.cs:226:9:226:18 | (..., ...) | 0 | CSharp7.cs:226:10:226:10 | _ | +| CSharp7.cs:226:9:226:18 | (..., ...) | 1 | CSharp7.cs:226:17:226:17 | Double y | +| CSharp7.cs:285:40:285:61 | (..., ...) | 0 | CSharp7.cs:285:41:285:48 | access to property Key | +| CSharp7.cs:285:40:285:61 | (..., ...) | 1 | CSharp7.cs:285:51:285:60 | access to property Value | +| CSharp7.cs:287:18:287:34 | (..., ...) | 0 | CSharp7.cs:287:23:287:23 | Int32 a | +| CSharp7.cs:287:18:287:34 | (..., ...) | 1 | CSharp7.cs:287:33:287:33 | String b | +| CSharp7.cs:289:18:289:31 | (..., ...) | 0 | CSharp7.cs:289:23:289:23 | Int32 a | +| CSharp7.cs:289:18:289:31 | (..., ...) | 1 | CSharp7.cs:289:30:289:30 | String b | +| CSharp7.cs:291:18:291:27 | (..., ...) | 0 | CSharp7.cs:291:23:291:23 | Int32 a | +| CSharp7.cs:291:18:291:27 | (..., ...) | 1 | CSharp7.cs:291:26:291:26 | String b | diff --git a/csharp/ql/test/library-tests/csharp7/TupleTypes.expected b/csharp/ql/test/library-tests/csharp7/TupleTypes.expected index 7168e2b833f..7a375de1fb8 100644 --- a/csharp/ql/test/library-tests/csharp7/TupleTypes.expected +++ b/csharp/ql/test/library-tests/csharp7/TupleTypes.expected @@ -6,19 +6,19 @@ | (Int32,(Int32,Int32)) | (int, (int, int)) | ValueTuple | 2 | 1 | CSharp7.cs:78:27:78:32 | Item2 | | (Int32,(String,Int32)) | (int, (string, int)) | ValueTuple | 2 | 0 | CSharp7.cs:98:19:98:19 | Item1 | | (Int32,(String,Int32)) | (int, (string, int)) | ValueTuple | 2 | 1 | CSharp7.cs:98:22:98:42 | Item2 | -| (Int32,Double) | (int, double) | ValueTuple | 2 | 0 | CSharp7.cs:214:6:214:8 | Item1 | -| (Int32,Double) | (int, double) | ValueTuple | 2 | 0 | CSharp7.cs:224:10:224:14 | x | -| (Int32,Double) | (int, double) | ValueTuple | 2 | 0 | CSharp7.cs:225:10:225:10 | Item1 | -| (Int32,Double) | (int, double) | ValueTuple | 2 | 1 | CSharp7.cs:214:11:214:16 | Item2 | -| (Int32,Double) | (int, double) | ValueTuple | 2 | 1 | CSharp7.cs:224:17:224:17 | Item2 | -| (Int32,Double) | (int, double) | ValueTuple | 2 | 1 | CSharp7.cs:225:13:225:17 | y | -| (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:64:6:64:8 | Item1 | +| (Int32,Double) | (int, double) | ValueTuple | 2 | 0 | CSharp7.cs:215:6:215:8 | Item1 | +| (Int32,Double) | (int, double) | ValueTuple | 2 | 0 | CSharp7.cs:225:10:225:14 | x | +| (Int32,Double) | (int, double) | ValueTuple | 2 | 0 | CSharp7.cs:226:10:226:10 | Item1 | +| (Int32,Double) | (int, double) | ValueTuple | 2 | 1 | CSharp7.cs:215:11:215:16 | Item2 | +| (Int32,Double) | (int, double) | ValueTuple | 2 | 1 | CSharp7.cs:225:17:225:17 | Item2 | +| (Int32,Double) | (int, double) | ValueTuple | 2 | 1 | CSharp7.cs:226:13:226:17 | y | +| (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:64:10:64:10 | A | | (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:71:10:71:14 | x | | (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:77:18:77:22 | b | | (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:78:28:78:28 | c | | (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:112:15:112:16 | m4 | | (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:114:19:114:24 | m8 | -| (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:64:11:64:13 | Item2 | +| (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:64:17:64:17 | B | | (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:71:17:71:21 | y | | (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:77:25:77:29 | c | | (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:78:31:78:31 | a | @@ -27,10 +27,10 @@ | (Int32,Int32,Int32) | (int, int, int) | ValueTuple | 3 | 0 | CSharp7.cs:75:10:75:10 | x | | (Int32,Int32,Int32) | (int, int, int) | ValueTuple | 3 | 1 | CSharp7.cs:75:13:75:13 | y | | (Int32,Int32,Int32) | (int, int, int) | ValueTuple | 3 | 2 | CSharp7.cs:75:16:75:22 | Item3 | -| (Int32,String) | (int, string) | ValueTuple | 2 | 0 | CSharp7.cs:284:41:284:48 | Key | -| (Int32,String) | (int, string) | ValueTuple | 2 | 0 | CSharp7.cs:286:19:286:23 | a | -| (Int32,String) | (int, string) | ValueTuple | 2 | 1 | CSharp7.cs:284:51:284:60 | Value | -| (Int32,String) | (int, string) | ValueTuple | 2 | 1 | CSharp7.cs:286:26:286:33 | b | +| (Int32,String) | (int, string) | ValueTuple | 2 | 0 | CSharp7.cs:285:41:285:48 | Key | +| (Int32,String) | (int, string) | ValueTuple | 2 | 0 | CSharp7.cs:287:19:287:23 | a | +| (Int32,String) | (int, string) | ValueTuple | 2 | 1 | CSharp7.cs:285:51:285:60 | Value | +| (Int32,String) | (int, string) | ValueTuple | 2 | 1 | CSharp7.cs:287:26:287:33 | b | | (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple | 2 | 0 | CSharp7.cs:109:10:109:15 | m1 | | (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple | 2 | 0 | CSharp7.cs:112:10:112:11 | m3 | | (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple | 2 | 0 | CSharp7.cs:114:10:114:15 | m7 | diff --git a/csharp/ql/test/library-tests/csharp7/TypeCase1.expected b/csharp/ql/test/library-tests/csharp7/TypeCase1.expected index 92c23564233..f5feda6b24b 100644 --- a/csharp/ql/test/library-tests/csharp7/TypeCase1.expected +++ b/csharp/ql/test/library-tests/csharp7/TypeCase1.expected @@ -1,9 +1,9 @@ -| CSharp7.cs:251:13:251:23 | case ...: | -| CSharp7.cs:253:13:253:31 | case ...: | -| CSharp7.cs:255:13:255:41 | case ...: | -| CSharp7.cs:258:13:258:36 | case ...: | -| CSharp7.cs:261:13:261:24 | case ...: | -| CSharp7.cs:264:13:264:27 | case ...: | -| CSharp7.cs:267:13:267:26 | case ...: | -| CSharp7.cs:270:13:270:24 | case ...: | -| CSharp7.cs:272:13:272:20 | default: | +| CSharp7.cs:252:13:252:23 | case ...: | +| CSharp7.cs:254:13:254:31 | case ...: | +| CSharp7.cs:256:13:256:41 | case ...: | +| CSharp7.cs:259:13:259:36 | case ...: | +| CSharp7.cs:262:13:262:24 | case ...: | +| CSharp7.cs:265:13:265:27 | case ...: | +| CSharp7.cs:268:13:268:26 | case ...: | +| CSharp7.cs:271:13:271:24 | case ...: | +| CSharp7.cs:273:13:273:20 | default: | diff --git a/csharp/ql/test/library-tests/csharp7/TypeCase2.expected b/csharp/ql/test/library-tests/csharp7/TypeCase2.expected index 3825dd93fe6..bace5da4c04 100644 --- a/csharp/ql/test/library-tests/csharp7/TypeCase2.expected +++ b/csharp/ql/test/library-tests/csharp7/TypeCase2.expected @@ -1,4 +1,4 @@ -| CSharp7.cs:258:13:258:36 | case ...: | CSharp7.cs:258:18:258:23 | Int32 i2 | Int32 | false | -| CSharp7.cs:261:13:261:24 | case ...: | CSharp7.cs:261:18:261:23 | Int32 i3 | Int32 | false | -| CSharp7.cs:264:13:264:27 | case ...: | CSharp7.cs:264:18:264:26 | String s2 | String | false | -| CSharp7.cs:270:13:270:24 | case ...: | CSharp7.cs:270:18:270:23 | Object v2 | Object | true | +| CSharp7.cs:259:13:259:36 | case ...: | CSharp7.cs:259:18:259:23 | Int32 i2 | Int32 | false | +| CSharp7.cs:262:13:262:24 | case ...: | CSharp7.cs:262:18:262:23 | Int32 i3 | Int32 | false | +| CSharp7.cs:265:13:265:27 | case ...: | CSharp7.cs:265:18:265:26 | String s2 | String | false | +| CSharp7.cs:271:13:271:24 | case ...: | CSharp7.cs:271:18:271:23 | Object v2 | Object | true | diff --git a/csharp/ql/test/library-tests/csharp7/TypeCase3.expected b/csharp/ql/test/library-tests/csharp7/TypeCase3.expected index 93eb7af459b..abab42820f8 100644 --- a/csharp/ql/test/library-tests/csharp7/TypeCase3.expected +++ b/csharp/ql/test/library-tests/csharp7/TypeCase3.expected @@ -1 +1 @@ -| CSharp7.cs:258:13:258:36 | case ...: | CSharp7.cs:258:30:258:35 | ... > ... | +| CSharp7.cs:259:13:259:36 | case ...: | CSharp7.cs:259:30:259:35 | ... > ... | diff --git a/csharp/ql/test/library-tests/csharp7/UnboundLocalFunctions.expected b/csharp/ql/test/library-tests/csharp7/UnboundLocalFunctions.expected index 594f51bac56..8629d9d496c 100644 --- a/csharp/ql/test/library-tests/csharp7/UnboundLocalFunctions.expected +++ b/csharp/ql/test/library-tests/csharp7/UnboundLocalFunctions.expected @@ -1,7 +1,7 @@ | CSharp7.cs:133:9:133:42 | f2 | 0 | CSharp7.cs:133:14:133:14 | T | | CSharp7.cs:133:9:133:42 | f2 | 1 | CSharp7.cs:133:17:133:17 | U | -| CSharp7.cs:160:9:160:24 | f | 0 | CSharp7.cs:160:15:160:15 | T | -| CSharp7.cs:161:9:161:25 | g | 0 | CSharp7.cs:161:13:161:13 | T | -| CSharp7.cs:163:9:168:9 | h | 0 | CSharp7.cs:163:13:163:13 | T | -| CSharp7.cs:163:9:168:9 | h | 1 | CSharp7.cs:163:16:163:16 | U | -| CSharp7.cs:165:13:165:43 | f2 | 0 | CSharp7.cs:165:20:165:20 | S | +| CSharp7.cs:161:9:161:24 | f | 0 | CSharp7.cs:161:15:161:15 | T | +| CSharp7.cs:162:9:162:25 | g | 0 | CSharp7.cs:162:13:162:13 | T | +| CSharp7.cs:164:9:169:9 | h | 0 | CSharp7.cs:164:13:164:13 | T | +| CSharp7.cs:164:9:169:9 | h | 1 | CSharp7.cs:164:16:164:16 | U | +| CSharp7.cs:166:13:166:43 | f2 | 0 | CSharp7.cs:166:20:166:20 | S | From 0220ab678416490042a4fdc76932c37c97dafe50 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 27 May 2020 11:15:16 +0100 Subject: [PATCH 241/411] JS: Move some TypeScript classes into .ts.extractor --- .../extractor/src/com/semmle/js/extractor/AutoBuild.java | 2 +- .../src/com/semmle/js/extractor/ExtractorState.java | 2 +- javascript/extractor/src/com/semmle/js/extractor/Main.java | 2 +- .../src/com/semmle/js/extractor/TypeScriptExtractor.java | 1 + .../{js/parser => ts/extractor}/TypeScriptASTConverter.java | 3 ++- .../semmle/{js/parser => ts/extractor}/TypeScriptParser.java | 5 +++-- .../parser => ts/extractor}/TypeScriptParserMetadata.java | 2 +- 7 files changed, 10 insertions(+), 7 deletions(-) rename javascript/extractor/src/com/semmle/{js/parser => ts/extractor}/TypeScriptASTConverter.java (99%) rename javascript/extractor/src/com/semmle/{js/parser => ts/extractor}/TypeScriptParser.java (99%) rename javascript/extractor/src/com/semmle/{js/parser => ts/extractor}/TypeScriptParserMetadata.java (98%) diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index edff3c8a857..7d6bd93d3cd 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -46,8 +46,8 @@ import com.semmle.js.extractor.trapcache.DefaultTrapCache; import com.semmle.js.extractor.trapcache.DummyTrapCache; import com.semmle.js.extractor.trapcache.ITrapCache; import com.semmle.js.parser.ParsedProject; -import com.semmle.js.parser.TypeScriptParser; import com.semmle.ts.extractor.TypeExtractor; +import com.semmle.ts.extractor.TypeScriptParser; import com.semmle.ts.extractor.TypeTable; import com.semmle.util.data.StringUtil; import com.semmle.util.exception.CatastrophicError; diff --git a/javascript/extractor/src/com/semmle/js/extractor/ExtractorState.java b/javascript/extractor/src/com/semmle/js/extractor/ExtractorState.java index 85b929f6ffb..8aa4eb7a2b4 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ExtractorState.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ExtractorState.java @@ -6,7 +6,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.Optional; -import com.semmle.js.parser.TypeScriptParser; +import com.semmle.ts.extractor.TypeScriptParser; /** * Contains the state to be shared between extractions of different files. diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index a7b209bc7ce..f035e5842d9 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -19,8 +19,8 @@ import com.semmle.js.extractor.trapcache.DefaultTrapCache; import com.semmle.js.extractor.trapcache.DummyTrapCache; import com.semmle.js.extractor.trapcache.ITrapCache; import com.semmle.js.parser.ParsedProject; -import com.semmle.js.parser.TypeScriptParser; import com.semmle.ts.extractor.TypeExtractor; +import com.semmle.ts.extractor.TypeScriptParser; import com.semmle.ts.extractor.TypeTable; import com.semmle.util.data.StringUtil; import com.semmle.util.data.UnitParser; diff --git a/javascript/extractor/src/com/semmle/js/extractor/TypeScriptExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/TypeScriptExtractor.java index e43178748e5..b12790cc9c3 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/TypeScriptExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/TypeScriptExtractor.java @@ -5,6 +5,7 @@ import java.io.File; import com.semmle.js.extractor.ExtractorConfig.ECMAVersion; import com.semmle.js.extractor.ExtractorConfig.SourceType; import com.semmle.js.parser.JSParser.Result; +import com.semmle.ts.extractor.TypeScriptParser; import com.semmle.js.parser.ParseError; public class TypeScriptExtractor implements IExtractor { diff --git a/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java b/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptASTConverter.java similarity index 99% rename from javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java rename to javascript/extractor/src/com/semmle/ts/extractor/TypeScriptASTConverter.java index d2e5a0448c3..0950e16b501 100644 --- a/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java +++ b/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptASTConverter.java @@ -1,4 +1,4 @@ -package com.semmle.js.parser; +package com.semmle.ts.extractor; import java.util.ArrayList; import java.util.Collections; @@ -113,6 +113,7 @@ import com.semmle.js.ast.jsx.JSXOpeningElement; import com.semmle.js.ast.jsx.JSXSpreadAttribute; import com.semmle.js.ast.jsx.JSXThisExpr; import com.semmle.js.parser.JSParser.Result; +import com.semmle.js.parser.ParseError; import com.semmle.ts.ast.ArrayTypeExpr; import com.semmle.ts.ast.ConditionalTypeExpr; import com.semmle.ts.ast.DecoratorList; diff --git a/javascript/extractor/src/com/semmle/js/parser/TypeScriptParser.java b/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptParser.java similarity index 99% rename from javascript/extractor/src/com/semmle/js/parser/TypeScriptParser.java rename to javascript/extractor/src/com/semmle/ts/extractor/TypeScriptParser.java index c091e39af55..36792f2d204 100644 --- a/javascript/extractor/src/com/semmle/js/parser/TypeScriptParser.java +++ b/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptParser.java @@ -1,4 +1,4 @@ -package com.semmle.js.parser; +package com.semmle.ts.extractor; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -32,8 +32,9 @@ import com.semmle.js.extractor.DependencyInstallationResult; import com.semmle.js.extractor.EnvironmentVariables; import com.semmle.js.extractor.ExtractionMetrics; import com.semmle.js.extractor.VirtualSourceRoot; +import com.semmle.js.parser.JSParser; +import com.semmle.js.parser.ParsedProject; import com.semmle.js.parser.JSParser.Result; -import com.semmle.ts.extractor.TypeTable; import com.semmle.util.data.StringUtil; import com.semmle.util.data.UnitParser; import com.semmle.util.exception.CatastrophicError; diff --git a/javascript/extractor/src/com/semmle/js/parser/TypeScriptParserMetadata.java b/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptParserMetadata.java similarity index 98% rename from javascript/extractor/src/com/semmle/js/parser/TypeScriptParserMetadata.java rename to javascript/extractor/src/com/semmle/ts/extractor/TypeScriptParserMetadata.java index 1ba390098a8..cb9eec9cbca 100644 --- a/javascript/extractor/src/com/semmle/js/parser/TypeScriptParserMetadata.java +++ b/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptParserMetadata.java @@ -1,4 +1,4 @@ -package com.semmle.js.parser; +package com.semmle.ts.extractor; import java.util.LinkedHashMap; import java.util.Map; From f5c3aa3d39b451bdd68ee8334e6bed294650fd89 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Sat, 5 Sep 2020 10:16:53 +0100 Subject: [PATCH 242/411] JS: Handle types/typings fields in package.json --- .../extractor/lib/typescript/src/common.ts | 2 +- .../extractor/lib/typescript/src/main.ts | 122 ++++++++++++++++-- .../lib/typescript/src/virtual_source_root.ts | 11 ++ 3 files changed, 123 insertions(+), 12 deletions(-) diff --git a/javascript/extractor/lib/typescript/src/common.ts b/javascript/extractor/lib/typescript/src/common.ts index c660b7bcb5e..ba06a0195c9 100644 --- a/javascript/extractor/lib/typescript/src/common.ts +++ b/javascript/extractor/lib/typescript/src/common.ts @@ -9,7 +9,7 @@ import { VirtualSourceRoot } from "./virtual_source_root"; const packageNameRex = /^(?:@[\w.-]+[/\\]+)?\w[\w.-]*(?=[/\\]|$)/; const extensions = ['.ts', '.tsx', '.d.ts', '.js', '.jsx']; -function getPackageName(importString: string) { +export function getPackageName(importString: string) { let packageNameMatch = packageNameRex.exec(importString); if (packageNameMatch == null) return null; let packageName = packageNameMatch[0]; diff --git a/javascript/extractor/lib/typescript/src/main.ts b/javascript/extractor/lib/typescript/src/main.ts index 4452ef0e5d6..0d43a011761 100644 --- a/javascript/extractor/lib/typescript/src/main.ts +++ b/javascript/extractor/lib/typescript/src/main.ts @@ -95,11 +95,85 @@ class State { /** Next response to be delivered. */ public pendingResponse: string = null; + + /** Map from `package.json` files to their contents. */ + public parsedPackageJson = new Map(); + + /** Map from `package.json` files to the file referenced in its `types` or `typings` field. */ + public packageTypings = new Map(); + + /** Map from file path to the enclosing `package.json` file, if any. Will not traverse outside node_modules. */ + public enclosingPackageJson = new Map(); } let state = new State(); const reloadMemoryThresholdMb = getEnvironmentVariable("SEMMLE_TYPESCRIPT_MEMORY_THRESHOLD", Number, 1000); +function getPackageJson(file: string): any { + let cache = state.parsedPackageJson; + if (cache.has(file)) return cache.get(file); + let result = getPackageJsonRaw(file); + cache.set(file, result); + return result; +} + +function getPackageJsonRaw(file: string): any { + if (!ts.sys.fileExists(file)) return undefined; + try { + let json = JSON.parse(ts.sys.readFile(file)); + if (typeof json !== 'object') return undefined; + return json; + } catch (e) { + return undefined; + } +} + +function getPackageTypings(file: string): string | undefined { + let cache = state.packageTypings; + if (cache.has(file)) return cache.get(file); + let result = getPackageTypingsRaw(file); + cache.set(file, result); + return result; +} + +function getPackageTypingsRaw(packageJsonFile: string): string | undefined { + let json = getPackageJson(packageJsonFile); + if (json == null) return undefined; + let typings = json.types || json.typings; + if (typeof typings !== 'string') return undefined; + let absolutePath = pathlib.join(pathlib.dirname(packageJsonFile), typings); + if (ts.sys.directoryExists(absolutePath)) { + absolutePath = pathlib.join(absolutePath, 'index.d.ts'); + } else if (!absolutePath.endsWith('.ts')) { + absolutePath += '.d.ts'; + } + if (!ts.sys.fileExists(absolutePath)) return undefined; + return ts.sys.resolvePath(absolutePath); +} + +function getEnclosingPackageJson(file: string): string | undefined { + let cache = state.packageTypings; + if (cache.has(file)) return cache.get(file); + let result = getEnclosingPackageJsonRaw(file); + cache.set(file, result); + return result; +} + +function getEnclosingPackageJsonRaw(file: string): string | undefined { + let packageJson = pathlib.join(file, 'package.json'); + if (ts.sys.fileExists(packageJson)) { + return packageJson; + } + if (pathlib.basename(file) === 'node_modules') { + return undefined; + } + let dirname = pathlib.dirname(file); + if (dirname.length < file.length) { + return getEnclosingPackageJson(dirname); + } + return undefined; +} + /** * Debugging method for finding cycles in the TypeScript AST. Should not be used in production. * @@ -505,14 +579,18 @@ function handleOpenProjectCommand(command: OpenProjectCommand) { // inverse mapping, nor a way to enumerate all known module names. So we discover all // modules on the type roots (usually "node_modules/@types" but this is configurable). let typeRoots = ts.getEffectiveTypeRoots(config.options, { - directoryExists: (path) => fs.existsSync(path), + directoryExists: (path) => ts.sys.directoryExists(path), getCurrentDirectory: () => basePath, }); for (let typeRoot of typeRoots || []) { - if (fs.existsSync(typeRoot) && fs.statSync(typeRoot).isDirectory()) { + if (ts.sys.directoryExists(typeRoot)) { traverseTypeRoot(typeRoot, ""); } + let virtualTypeRoot = virtualSourceRoot.toVirtualPathIfDirectoryExists(typeRoot); + if (virtualTypeRoot != null) { + traverseTypeRoot(virtualTypeRoot, ""); + } } for (let sourceFile of program.getSourceFiles()) { @@ -549,22 +627,25 @@ function handleOpenProjectCommand(command: OpenProjectCommand) { if (sourceFile == null) { continue; } - addModuleBindingFromRelativePath(sourceFile, importPrefix, child); + let importPath = getImportPathFromFileInFolder(importPrefix, child); + addModuleBindingFromImportPath(sourceFile, importPath); } } + function getImportPathFromFileInFolder(folder: string, baseName: string) { + let stem = getStem(baseName); + return (stem === "index") + ? folder + : joinModulePath(folder, stem); + } + /** * Emits module bindings for a module with relative path `folder/baseName`. */ - function addModuleBindingFromRelativePath(sourceFile: ts.SourceFile, folder: string, baseName: string) { + function addModuleBindingFromImportPath(sourceFile: ts.SourceFile, importPath: string) { let symbol = typeChecker.getSymbolAtLocation(sourceFile); if (symbol == null) return; // Happens if the source file is not a module. - let stem = getStem(baseName); - let importPath = (stem === "index") - ? folder - : joinModulePath(folder, stem); - let canonicalSymbol = getEffectiveExportTarget(symbol); // Follow `export = X` declarations. let symbolId = state.typeTable.getSymbolId(canonicalSymbol); @@ -576,7 +657,7 @@ function handleOpenProjectCommand(command: OpenProjectCommand) { // Note: the `globalExports` map is stored on the original symbol, not the target of `export=`. if (symbol.globalExports != null) { symbol.globalExports.forEach((global: ts.Symbol) => { - state.typeTable.addGlobalMapping(symbolId, global.name); + state.typeTable.addGlobalMapping(symbolId, global.name); }); } } @@ -605,11 +686,30 @@ function handleOpenProjectCommand(command: OpenProjectCommand) { let fullPath = sourceFile.fileName; let index = fullPath.lastIndexOf('/node_modules/'); if (index === -1) return; + let relativePath = fullPath.substring(index + '/node_modules/'.length); + // Ignore node_modules/@types folders here as they are typically handled as type roots. if (relativePath.startsWith("@types/")) return; + + // If the enclosing package has a "typings" field, only add module bindings for that file. + let packageJsonFile = getEnclosingPackageJson(fullPath); + if (packageJsonFile != null) { + let json = getPackageJson(packageJsonFile); + let typings = getPackageTypings(packageJsonFile); + if (json != null && typings != null) { + let name = json.name; + if (typings === fullPath && typeof name === 'string') { + addModuleBindingFromImportPath(sourceFile, name); + } else if (typings != null) { + return; // Typings field prevents access to other files in package. + } + } + } + + // Add module bindings relative to package directory. let { dir, base } = pathlib.parse(relativePath); - addModuleBindingFromRelativePath(sourceFile, dir, base); + addModuleBindingFromImportPath(sourceFile, getImportPathFromFileInFolder(dir, base)); } /** diff --git a/javascript/extractor/lib/typescript/src/virtual_source_root.ts b/javascript/extractor/lib/typescript/src/virtual_source_root.ts index 4753818ef16..6ca9a580b56 100644 --- a/javascript/extractor/lib/typescript/src/virtual_source_root.ts +++ b/javascript/extractor/lib/typescript/src/virtual_source_root.ts @@ -55,4 +55,15 @@ export class VirtualSourceRoot { } return null; } + + /** + * Maps a path under the real source root to the corresponding path in the virtual source root. + */ + public toVirtualPathIfDirectoryExists(path: string) { + let virtualPath = this.toVirtualPath(path); + if (virtualPath != null && ts.sys.directoryExists(virtualPath)) { + return virtualPath; + } + return null; + } } From c84e43d95b0ee3100dc332c5ee179625c60aa873 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 27 May 2020 17:24:07 +0100 Subject: [PATCH 243/411] JS: Replace yarn with manual dependency resolution --- .../semmle/js/dependencies/AsyncFetcher.java | 84 +++++++ .../js/dependencies/DependencyResolver.java | 221 ++++++++++++++++++ .../com/semmle/js/dependencies/Fetcher.java | 140 +++++++++++ .../com/semmle/js/dependencies/SemVer.java | 106 +++++++++ .../js/dependencies/VersionConstraint.java | 57 +++++ .../dependencies/packument/PackageJson.java | 95 ++++++++ .../js/dependencies/packument/Packument.java | 24 ++ .../com/semmle/js/extractor/AutoBuild.java | 158 +++---------- 8 files changed, 756 insertions(+), 129 deletions(-) create mode 100644 javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java create mode 100644 javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java create mode 100644 javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java create mode 100644 javascript/extractor/src/com/semmle/js/dependencies/SemVer.java create mode 100644 javascript/extractor/src/com/semmle/js/dependencies/VersionConstraint.java create mode 100644 javascript/extractor/src/com/semmle/js/dependencies/packument/PackageJson.java create mode 100644 javascript/extractor/src/com/semmle/js/dependencies/packument/Packument.java diff --git a/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java b/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java new file mode 100644 index 00000000000..2dbac252eb2 --- /dev/null +++ b/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java @@ -0,0 +1,84 @@ +package com.semmle.js.dependencies; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutorService; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import com.semmle.js.dependencies.packument.Packument; + +/** + * Asynchronous I/O operations needed for dependency installation. + *

    + * The methods in this class are non-blocking, that is, they return more or less immediately, always scheduling the work + * in the provided executor service. Requests are cached where it makes sense. + */ +public class AsyncFetcher { + private Fetcher fetcher = new Fetcher(); + private ExecutorService executor; + private Consumer errorReporter; + + /** + * @param executor thread pool to perform I/O tasks + * @param errorReporter called once for each error from the underlying I/O tasks + */ + public AsyncFetcher(ExecutorService executor, Consumer errorReporter) { + this.executor = executor; + this.errorReporter = errorReporter; + } + + private CompletionException makeError(String message, Exception cause) { + CompletionException ex = new CompletionException(message, cause); + errorReporter.accept(ex); // Handle here to ensure each exception is logged at most once, not once per consumer + throw ex; + } + + class CachedOperation { + private Map> cache = new LinkedHashMap<>(); + + public synchronized CompletableFuture get(K key, Supplier builder) { + CompletableFuture future = cache.get(key); + if (future == null) { + future = CompletableFuture.supplyAsync(() -> builder.get(), executor); + cache.put(key, future); + } + return future; + } + } + + private CachedOperation packuments = new CachedOperation<>(); + + /** + * Returns a future that completes with the packument for the given package. + *

    + * At most one fetch will be performed. + */ + public CompletableFuture getPackument(String packageName) { + return packuments.get(packageName, () -> { + try { + return fetcher.getPackument(packageName); + } catch (IOException e) { + throw makeError("Could not fetch packument for " + packageName, e); + } + }); + } + + /** + * Extracts the relevant contents of the given tarball URL in the given folder; + * the returned future completes when done. + */ + public CompletableFuture installFromTarballUrl(String tarballUrl, Path destDir) { + return CompletableFuture.runAsync(() -> { + try { + fetcher.extractFromTarballUrl(tarballUrl, destDir); + } catch (IOException e) { + throw makeError("Could not install package from " + tarballUrl, e); + } + }, executor); + } +} diff --git a/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java b/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java new file mode 100644 index 00000000000..318725fd75b --- /dev/null +++ b/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java @@ -0,0 +1,221 @@ +package com.semmle.js.dependencies; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import com.google.gson.Gson; +import com.semmle.js.dependencies.packument.PackageJson; +import com.semmle.util.data.Pair; + +public class DependencyResolver { + private AsyncFetcher fetcher; + private List constraints = new ArrayList<>(); + + /** Packages we don't try to install because it is part of the same monorepo. */ + private Set packagesInRepo; + + private static class Constraint { + final PackageJson targetPackage; + final SemVer targetPackageVersion; + final PackageJson demandingPackage; + final int depth; + + Constraint(PackageJson targetPackage, SemVer targetPackageVersion, PackageJson demandingPackage, int depth) { + this.targetPackage = targetPackage; + this.targetPackageVersion = targetPackageVersion; + this.demandingPackage = demandingPackage; + this.depth = depth; + } + + String getTargetPackageName() { + return targetPackage.getName(); // Must exist as you can't depend on a package without a name + } + } + + public DependencyResolver(ExecutorService threadPool, Set packagesInRepo) { + this.fetcher = new AsyncFetcher(threadPool, this::reportError); + this.packagesInRepo = packagesInRepo; + } + + private void reportError(CompletionException ex) { + System.err.println(ex); + } + + private void addConstraint(Constraint constraint) { + synchronized(constraints) { + constraints.add(constraint); + } + } + + /** + * Returns the first version number mentioned in the given constraints, excluding upper bounds such as `< 2.0.0`, + * or `null` if no such version number was found. + *

    + * To help ensure deterministic version resolution, we prefer the version mentioned in the constraint, rather than + * the latest version satisfying the constraint (as the latter can change in time). + */ + private SemVer getPreferredVersionFromConstraints(List constraints) { + for (VersionConstraint constraint : constraints) { + if (!constraint.getOperator().equals("<") && constraint.getVersion() != null) { + return constraint.getVersion(); + } + } + return null; + } + + /** + * Given a set of available versions, pick the oldest version no older than preferredVersion. + */ + private Pair getTargetVersion(Map versions, SemVer preferredVersion) { + PackageJson result = versions.get(preferredVersion.toString()); + if (result != null) return Pair.make(preferredVersion, result); + SemVer bestVersion = null; + for (Map.Entry entry : versions.entrySet()) { + SemVer version = SemVer.tryParse(entry.getKey()); + if (version == null) continue; // Could not parse version + if (version.compareTo(preferredVersion) < 0) continue; // Version is older than preferred version, ignore + if (bestVersion != null && bestVersion.compareTo(version) < 0) continue; // We already found an older version + bestVersion = version; + result = entry.getValue(); + } + return Pair.make(bestVersion, result); + } + + /** + * Fetches all packages and builds up the constraint system needed for resolving. + */ + private CompletableFuture fetchRelevantPackages(PackageJson pack, int depth) { + List> futures = new ArrayList<>(); + List> dependencyMaps = depth == 0 + ? Arrays.asList(pack.getDependencies(), pack.getPeerDependencies(), pack.getDevDependencies()) + : Arrays.asList(pack.getDependencies()); // for transitive dependencies, only follow explicit dependencies + for (Map dependencies : dependencyMaps) { + if (dependencies == null) continue; + dependencies.forEach((targetName, targetVersions) -> { + if (packagesInRepo.contains(targetName)) { + return; + } + List constraints = VersionConstraint.parseVersionConstraints(targetVersions); + SemVer preferredVersion = getPreferredVersionFromConstraints(constraints); + if (preferredVersion == null) return; + futures.add(fetcher.getPackument(targetName).exceptionally(ex -> null).thenCompose(targetPackument -> { + if (targetPackument == null) { + return CompletableFuture.completedFuture(null); + } + Map versions = targetPackument.getVersions(); + if (versions == null) return CompletableFuture.completedFuture(null); + + // Pick the matching version + Pair targetVersionAndPackage = getTargetVersion(versions, preferredVersion); + SemVer targetVersion = targetVersionAndPackage.fst(); + PackageJson targetPackage = targetVersionAndPackage.snd(); + if (targetPackage == null) return CompletableFuture.completedFuture(null); + + if (targetName.startsWith("@types/")) { + // Deeply install dependencies in `@types` + addConstraint(new Constraint(targetPackage, targetVersion, pack, depth)); + return fetchRelevantPackages(targetPackage, depth + 1); + } else if (dependencies != pack.getDevDependencies() && (targetPackage.getTypes() != null || targetPackage.getTypings() != null)) { + // If a non-dev dependency contains its own typings, do a shallow install of that package + addConstraint(new Constraint(targetPackage, targetVersion, pack, depth)); + } + return CompletableFuture.completedFuture(null); + })); + }); + } + return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); + } + + /** + * Resolves the dependencies of the given package in a deterministic way. + */ + private CompletableFuture> resolvePackages(PackageJson rootPackage) { + return fetchRelevantPackages(rootPackage, 0).thenApply(void_ -> { + // Compute the minimum depth from which each dependency is requested. + Map packageDepth = new LinkedHashMap<>(); + for (Constraint constraint : constraints) { + Integer currentDepth = packageDepth.get(constraint.getTargetPackageName()); + if (currentDepth == null || currentDepth > constraint.depth) { + packageDepth.put(constraint.getTargetPackageName(), constraint.depth); + } + } + + // We use a greedy solver: sort the constraints and then satisfy them eagerly in that order. + constraints.sort((c1, c2) -> { + int cmp; + + cmp = Integer.compare(packageDepth.get(c1.getTargetPackageName()), packageDepth.get(c2.getTargetPackageName())); + if (cmp != 0) return cmp; + + cmp = c1.getTargetPackageName().compareTo(c2.getTargetPackageName()); + if (cmp != 0) return cmp; + + // Pick the most recent version, so reverse-sort by package version. + cmp = -c1.targetPackageVersion.compareTo(c2.targetPackageVersion); + if (cmp != 0) return cmp; + + return 0; + }); + + Map selectedPackages = new LinkedHashMap<>(); + for (Constraint constraint : constraints) { + if (selectedPackages.containsKey(constraint.getTargetPackageName())) { + // Too bad, we already picked a version for this package. Ignore the constraint. + continue; + } + if (constraint.demandingPackage != rootPackage) { + PackageJson selectedDemander = selectedPackages.get(constraint.demandingPackage.getName()); + if (selectedDemander != null && selectedDemander != constraint.demandingPackage) { + // The constraint comes from a package version we already decided not to install (a different version was picked). + // There is no need to try to satisfy this constraint, so ignore it. + continue; + } + } + System.out.println("Picked " + constraint.getTargetPackageName() + "@" + constraint.targetPackageVersion); + selectedPackages.put(constraint.getTargetPackageName(), constraint.targetPackage); + } + + return selectedPackages; + }); + } + + public CompletableFuture installDependencies(PackageJson rootPackage, Path nodeModulesDir) { + return resolvePackages(rootPackage).thenCompose(resolvedPackages -> { + List> futures = new ArrayList<>(); + resolvedPackages.forEach((name, targetPackage) -> { + Path destinationDir = nodeModulesDir.resolve(Fetcher.toSafePath(name)); + futures.add(fetcher.installFromTarballUrl(targetPackage.getDist().getTarball(), destinationDir)); + }); + return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); + }); + } + + /** Entry point which installs dependencies from a given `package.json`, used for testing andbenchmarking. */ + public static void main(String[] args) throws IOException { + ExecutorService executors = Executors.newFixedThreadPool(50); + try { + DependencyResolver resolver = new DependencyResolver(executors, Collections.emptySet()); + for (String packageJsonPath : args) { + Path path = Paths.get(packageJsonPath).toAbsolutePath(); + PackageJson packageJson = new Gson().fromJson(Files.newBufferedReader(path), PackageJson.class); + resolver.installDependencies(packageJson, path.getParent().resolve("node_modules")).join(); + } + System.out.println("Done"); + } finally { + executors.shutdown(); + } + } +} diff --git a/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java b/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java new file mode 100644 index 00000000000..019eedee370 --- /dev/null +++ b/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java @@ -0,0 +1,140 @@ +package com.semmle.js.dependencies; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PushbackInputStream; +import java.io.Reader; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.regex.Pattern; + +import com.google.gson.Gson; +import com.semmle.js.dependencies.packument.Packument; + +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; +import org.apache.commons.compress.utils.IOUtils; + +/** + * Synchronous I/O operations needed for dependency installation. + *

    + * By design, the methods in this class are thread-safe, synchronous (blocking), and do not cache anything. + *

    + * Should only be used through the {@link AsyncFetcher} class, which wraps this class with scheduling and caching. + */ +public class Fetcher { + private Object mkdirpLock = new Object(); + + /** Creates the given directory and its parent directories. Only one thread is allowed to create directories at once. */ + private void mkdirp(Path dir) throws IOException { + synchronized (mkdirpLock) { + Files.createDirectories(dir); + } + } + + private static final Pattern validPackageName = Pattern.compile("(?:@[\\w.-]+\\/)?\\w[\\w.-]*"); + + private boolean isValidPackageName(String name) { + return validPackageName.matcher(name).matches(); + } + + public static Path toSafePath(String string) { + if (string == null) return null; + Path path = Paths.get(string).normalize(); + if (path.startsWith("..") || path.isAbsolute()) { + return null; + } + return path; + } + + /** + * Submits a GET request to the given URL and returns an input with the response. + */ + private InputStream fetch(String url) throws IOException { + URLConnection connection = new URL(url).openConnection(); + connection.setRequestProperty("Accept-Encoding", "gzip, identity, *"); + connection.setDoInput(true); + connection.connect(); + InputStream input = connection.getInputStream(); + String encoding = connection.getContentEncoding(); + if ("gzip".equals(encoding)) { + return new GzipCompressorInputStream(new BufferedInputStream(input)); + } else { + return input; + } + } + + /** + * Fetches the packument for the given package (containing all versions of the package.json). + */ + public Packument getPackument(String packageName) throws IOException { + if (!isValidPackageName(packageName)) { + throw new IOException("Package name contains unexpected characters:" + packageName); + } + System.out.println("Fetching package metadata for " + packageName); + try (Reader reader = new BufferedReader(new InputStreamReader(fetch("https://registry.npmjs.org/" + packageName)))) { + return new Gson().fromJson(reader, Packument.class); + } + } + + /** + * Extracts the package at the given tarball URL into the given directory. + * + * Only `package.json` and `.d.ts` files are extracted. + */ + public void extractFromTarballUrl(String tarballUrl, Path destDir) throws IOException { + if (!tarballUrl.startsWith("https://registry.npmjs.org/") || !tarballUrl.endsWith(".tgz")) { // Paranoid check + throw new IOException("Tarball URL has unexpected format: " + tarballUrl); + } + System.out.println("Unpacking " + tarballUrl + " to " + destDir); + try (InputStream rawStream = new URL(tarballUrl).openStream()) { + // Despite having the .tgz extension, the file is not always gzipped, sometimes it's just a raw tar archive, + // regardless of what Accept-Encoding header we send. + // Sniff the header to detect which is the case. + PushbackInputStream pushback = new PushbackInputStream(rawStream, 2); + int byte1 = pushback.read(); + int byte2 = pushback.read(); + pushback.unread(byte2); + pushback.unread(byte1); + InputStream decompressedStream = (byte1 == 31 && byte2 == 139) + ? new GzipCompressorInputStream(new BufferedInputStream(pushback)) + : pushback; + TarArchiveInputStream stream = new TarArchiveInputStream(new BufferedInputStream(decompressedStream)); + TarArchiveEntry tarEntry; + while ((tarEntry = stream.getNextTarEntry()) != null) { + if (!stream.canReadEntryData(tarEntry)) { + continue; + } + if (tarEntry.isDirectory()) { + continue; // We create directories on demand. + } + Path entryPath = toSafePath(tarEntry.getName()); + if (entryPath == null) continue; + + // Strip off the leading folder name. + // The entire package is inside a folder, but the name of that folder is unspecified and its name varies. + if (entryPath.getNameCount() < 2) continue; + entryPath = entryPath.subpath(1, entryPath.getNameCount()); + + String filename = entryPath.getFileName().toString(); + if (!filename.endsWith(".d.ts") && !filename.equals("package.json")) { + continue; // Only extract .d.ts files and package.json + } + Path outputFile = destDir.resolve(entryPath); + mkdirp(outputFile.getParent()); + try (OutputStream output = new BufferedOutputStream(Files.newOutputStream(outputFile))) { + IOUtils.copy(stream, output); + } + } + } + } +} diff --git a/javascript/extractor/src/com/semmle/js/dependencies/SemVer.java b/javascript/extractor/src/com/semmle/js/dependencies/SemVer.java new file mode 100644 index 00000000000..2ef9dc9b37f --- /dev/null +++ b/javascript/extractor/src/com/semmle/js/dependencies/SemVer.java @@ -0,0 +1,106 @@ +package com.semmle.js.dependencies; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class SemVer implements Comparable { + private int major, minor, patch; + private String preRelease; + + public SemVer(int major, int minor, int patch, String preRelease) { + this.major = major; + this.minor = minor; + this.patch = patch; + if (preRelease == null) { + preRelease = ""; + } + this.preRelease = preRelease; + } + + public int getMajor() { + return major; + } + + public int getMinor() { + return minor; + } + + public int getPatch() { + return patch; + } + + public String getPreRelease() { + return preRelease; + } + + private static final Pattern pattern = Pattern.compile("(\\d+)(?:\\.(\\d+)(?:\\.(\\d+))?)?(-[0-9A-Za-z.-]*)?(\\+.*)?"); + + public static SemVer tryParse(String str) { + Matcher m = pattern.matcher(str); + if (m.matches()) { + int major = Integer.parseInt(m.group(1)); + int minor = m.group(2) == null ? 0 : Integer.parseInt(m.group(2)); + int patch = m.group(3) == null ? 0 : Integer.parseInt(m.group(3)); + String preRelease = m.group(4); + return new SemVer(major, minor, patch, preRelease); + } else { + return null; + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + major; + result = prime * result + minor; + result = prime * result + patch; + result = prime * result + ((preRelease == null) ? 0 : preRelease.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SemVer other = (SemVer) obj; + if (major != other.major) + return false; + if (minor != other.minor) + return false; + if (patch != other.patch) + return false; + if (preRelease == null) { + if (other.preRelease != null) + return false; + } else if (!preRelease.equals(other.preRelease)) + return false; + return true; + } + + @Override + public int compareTo(SemVer other) { + if (major != other.major) { + return Integer.compare(major, other.major); + } + if (minor != other.minor) { + return Integer.compare(minor, other.minor); + } + if (patch != other.patch) { + return Integer.compare(patch, other.patch); + } + if (!preRelease.equals(other.preRelease)) { + return preRelease.compareTo(other.preRelease); + } + return 0; + } + + @Override + public String toString() { + return major + "." + minor + "." + patch + (preRelease.isEmpty() ? "" : "-" + preRelease); + } +} diff --git a/javascript/extractor/src/com/semmle/js/dependencies/VersionConstraint.java b/javascript/extractor/src/com/semmle/js/dependencies/VersionConstraint.java new file mode 100644 index 00000000000..da66bd32eac --- /dev/null +++ b/javascript/extractor/src/com/semmle/js/dependencies/VersionConstraint.java @@ -0,0 +1,57 @@ +package com.semmle.js.dependencies; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class VersionConstraint { + private String operator; + private SemVer version; + + public VersionConstraint(String operator, SemVer version) { + this.operator = operator; + this.version = version; + } + + public static VersionConstraint exact(String version) { + return new VersionConstraint("", SemVer.tryParse(version)); + } + + public String getOperator() { + return operator; + } + + public SemVer getVersion() { + return version; + } + + private static final Pattern pattern = Pattern.compile("([~^<>=]*)\\s*(\\d.*)"); + + public static List parseVersionConstraints(String str) { + String[] parts = str.split(","); + List constraints = new ArrayList<>(); + for (String part : parts) { + part = part.trim(); + if (part.equals("*")) { + constraints.add(new VersionConstraint("*", null)); + continue; + } + Matcher matcher = pattern.matcher(str); + if (matcher.matches()) { + String operator = matcher.group(1); + String versionStr = matcher.group(2); + if (operator.isEmpty() && versionStr.contains("x")) { + // Normalize "1.x" to ">= 1.0" + operator = ">="; + versionStr = versionStr.replaceAll("x", "0"); + } + SemVer version = SemVer.tryParse(versionStr); + if (version != null) { + constraints.add(new VersionConstraint(operator, version)); + } + } + } + return constraints; + } +} diff --git a/javascript/extractor/src/com/semmle/js/dependencies/packument/PackageJson.java b/javascript/extractor/src/com/semmle/js/dependencies/packument/PackageJson.java new file mode 100644 index 00000000000..283fa8baa7b --- /dev/null +++ b/javascript/extractor/src/com/semmle/js/dependencies/packument/PackageJson.java @@ -0,0 +1,95 @@ +package com.semmle.js.dependencies.packument; + +import java.util.Map; + +public class PackageJson { + private String name; + private String version; + private Map dependencies; + private Map devDependencies; + private Map peerDependencies; + private String types; + private String typings; + private String main; + private Dist dist; + + public static class Dist { + private String tarball; + + public String getTarball() { + return tarball; + } + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public Map getDependencies() { + return dependencies; + } + + public void setDependencies(Map dependencies) { + this.dependencies = dependencies; + } + + public Map getDevDependencies() { + return devDependencies; + } + + public void setDevDependencies(Map devDependencies) { + this.devDependencies = devDependencies; + } + + public Map getPeerDependencies() { + return peerDependencies; + } + + public void setPeerDependencies(Map peerDependencies) { + this.peerDependencies = peerDependencies; + } + + public String getTypes() { + return types; + } + + public void setTypes(String types) { + this.types = types; + } + + public String getTypings() { + return typings; + } + + public void setTypings(String typings) { + this.typings = typings; + } + + public String getMain() { + return main; + } + + public void setMain(String main) { + this.main = main; + } + + public Dist getDist() { + return dist; + } + + public void setDist(Dist dist) { + this.dist = dist; + } +} diff --git a/javascript/extractor/src/com/semmle/js/dependencies/packument/Packument.java b/javascript/extractor/src/com/semmle/js/dependencies/packument/Packument.java new file mode 100644 index 00000000000..74c7882e0b4 --- /dev/null +++ b/javascript/extractor/src/com/semmle/js/dependencies/packument/Packument.java @@ -0,0 +1,24 @@ +package com.semmle.js.dependencies.packument; + +import java.util.Map; + +public class Packument { + private String name; + private Map versions; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Map getVersions() { + return versions; + } + + public void setVersions(Map versions) { + this.versions = versions; + } +} diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index 7d6bd93d3cd..04b6e07bece 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -1,11 +1,8 @@ package com.semmle.js.extractor; -import java.io.BufferedReader; import java.io.File; import java.io.IOException; -import java.io.InputStreamReader; import java.io.Reader; -import java.io.Writer; import java.lang.ProcessBuilder.Redirect; import java.net.URI; import java.net.URISyntaxException; @@ -38,8 +35,9 @@ import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; -import com.google.gson.JsonParser; import com.google.gson.JsonPrimitive; +import com.semmle.js.dependencies.DependencyResolver; +import com.semmle.js.dependencies.packument.PackageJson; import com.semmle.js.extractor.ExtractorConfig.SourceType; import com.semmle.js.extractor.FileExtractor.FileType; import com.semmle.js.extractor.trapcache.DefaultTrapCache; @@ -213,11 +211,10 @@ public class AutoBuild { private volatile boolean seenCode = false; private volatile boolean seenFiles = false; private boolean installDependencies = false; - private int installDependenciesTimeout; private final VirtualSourceRoot virtualSourceRoot; private ExtractorState state; - /** The default timeout when running yarn, in milliseconds. */ + /** The default timeout when installing dependencies, in milliseconds. */ public static final int INSTALL_DEPENDENCIES_DEFAULT_TIMEOUT = 10 * 60 * 1000; // 10 minutes public AutoBuild() { @@ -229,10 +226,6 @@ public class AutoBuild { getEnumFromEnvVar("LGTM_INDEX_TYPESCRIPT", TypeScriptMode.class, TypeScriptMode.FULL); this.defaultEncoding = getEnvVar("LGTM_INDEX_DEFAULT_ENCODING"); this.installDependencies = Boolean.valueOf(getEnvVar("LGTM_INDEX_TYPESCRIPT_INSTALL_DEPS")); - this.installDependenciesTimeout = - Env.systemEnv() - .getInt( - "LGTM_INDEX_TYPESCRIPT_INSTALL_DEPS_TIMEOUT", INSTALL_DEPENDENCIES_DEFAULT_TIMEOUT); this.virtualSourceRoot = makeVirtualSourceRoot(); setupFileTypes(); setupXmlMode(); @@ -690,28 +683,6 @@ public class AutoBuild { return false; } - /** Returns true if yarn is installed, otherwise prints a warning and returns false. */ - private boolean verifyYarnInstallation() { - ProcessBuilder pb = new ProcessBuilder(Arrays.asList("yarn", "-v")); - try { - Process process = pb.start(); - boolean completed = process.waitFor(this.installDependenciesTimeout, TimeUnit.MILLISECONDS); - if (!completed) { - System.err.println("Yarn could not be launched. Timeout during 'yarn -v'."); - return false; - } - BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - String version = reader.readLine(); - System.out.println("Found yarn version: " + version); - return true; - } catch (IOException | InterruptedException ex) { - System.err.println( - "Yarn not found. Please put 'yarn' on the PATH for automatic dependency installation."); - Exceptions.ignore(ex, "Continue without dependency installation"); - return false; - } - } - /** * Returns an existing file named dir/stem.ext where .ext is any * of the given extensions, or null if no such file exists. @@ -736,17 +707,6 @@ public class AutoBuild { return tryResolveWithExtensions(dir, stem, FileType.JS.getExtensions()); } - /** - * Gets a child of a JSON object as a string, or null. - */ - private String getChildAsString(JsonObject obj, String name) { - JsonElement child = obj.get(name); - if (child instanceof JsonPrimitive && ((JsonPrimitive)child).isString()) { - return child.getAsString(); - } - return null; - } - /** * Gets a relative path from from to to provided * the latter is contained in the former. Otherwise returns null. @@ -769,11 +729,8 @@ public class AutoBuild { *

    * Downloaded packages are intalled under SCRATCH_DIR, in a mirrored directory hierarchy * we call the "virtual source root". - * Each package.json file is rewritten and copied to the virtual source root, - * where yarn install is invoked. *

    - * Packages that exists within the repo are stripped from the dependencies - * before installation, so they are not downloaded. Since they are part of the main source tree, + * Packages that exists within the repo are not downloaded. Since they are part of the main source tree, * these packages are not mirrored under the virtual source root. * Instead, an explicit package location mapping is passed to the TypeScript parser wrapper. *

    @@ -784,23 +741,20 @@ protected DependencyInstallationResult preparePackagesAndDependencies(Set final Path sourceRoot = LGTM_SRC; // Read all package.json files and index them by name. - Map packageJsonFiles = new LinkedHashMap<>(); + Map packageJsonFiles = new LinkedHashMap<>(); Map packagesInRepo = new LinkedHashMap<>(); Map packageMainFile = new LinkedHashMap<>(); for (Path file : filesToExtract) { if (file.getFileName().toString().equals("package.json")) { try { - String text = new WholeIO().read(file); - JsonElement json = new JsonParser().parse(text); - if (!(json instanceof JsonObject)) continue; - JsonObject jsonObject = (JsonObject) json; + PackageJson packageJson = new Gson().fromJson(new WholeIO().read(file), PackageJson.class); file = file.toAbsolutePath(); if (tryRelativize(sourceRoot, file) == null) { continue; // Ignore package.json files outside the source root. } - packageJsonFiles.put(file, jsonObject); + packageJsonFiles.put(file, packageJson); - String name = getChildAsString(jsonObject, "name"); + String name = packageJson.getName(); if (name != null) { packagesInRepo.put(name, file); } @@ -812,45 +766,12 @@ protected DependencyInstallationResult preparePackagesAndDependencies(Set } } - // Process all package.json files now that we know the names of all local packages. - // - remove dependencies on local packages - // - guess the main file for each package - // Note that we ignore optional dependencies during installation, so "optionalDependencies" - // is ignored here as well. - final List dependencyFields = - Arrays.asList("dependencies", "devDependencies", "peerDependencies"); + // Guess the main file for each package. packageJsonFiles.forEach( - (path, packageJson) -> { + (path, packageJson) -> { Path relativePath = sourceRoot.relativize(path); - for (String dependencyField : dependencyFields) { - JsonElement dependencyElm = packageJson.get(dependencyField); - if (!(dependencyElm instanceof JsonObject)) continue; - JsonObject dependencyObj = (JsonObject) dependencyElm; - List propsToRemove = new ArrayList<>(); - for (String packageName : dependencyObj.keySet()) { - if (packagesInRepo.containsKey(packageName)) { - // Remove dependency on local package - propsToRemove.add(packageName); - } else { - // Remove file dependency on a package that doesn't exist in the checkout. - String dependency = getChildAsString(dependencyObj, packageName); - if (dependency != null && (dependency.startsWith("file:") || dependency.startsWith("./") || dependency.startsWith("../"))) { - if (dependency.startsWith("file:")) { - dependency = dependency.substring("file:".length()); - } - Path resolvedPackage = path.getParent().resolve(dependency + "/package.json"); - if (!Files.exists(resolvedPackage)) { - propsToRemove.add(packageName); - } - } - } - } - for (String prop : propsToRemove) { - dependencyObj.remove(prop); - } - } // For named packages, find the main file. - String name = getChildAsString(packageJson, "name"); + String name = packageJson.getName(); if (name != null) { Path entryPoint = guessPackageMainFile(path, packageJson, FileType.TYPESCRIPT.getExtensions()); if (entryPoint == null) { @@ -866,45 +787,24 @@ protected DependencyInstallationResult preparePackagesAndDependencies(Set } }); - // Write the new package.json files to disk - for (Path file : packageJsonFiles.keySet()) { - Path virtualFile = virtualSourceRoot.toVirtualFile(file); - + if (installDependencies) { + // Use more threads for dependency installation than for extraction, as this is mainly I/O bound and we want + // many concurrent HTTP requests. + ExecutorService installationThreadPool = Executors.newFixedThreadPool(50); try { - Files.createDirectories(virtualFile.getParent()); - try (Writer writer = Files.newBufferedWriter(virtualFile)) { - new Gson().toJson(packageJsonFiles.get(file), writer); - } - } catch (IOException e) { - throw new ResourceError("Could not rewrite package.json file: " + virtualFile, e); - } - } - - // Install dependencies - if (this.installDependencies && verifyYarnInstallation()) { - for (Path file : packageJsonFiles.keySet()) { - Path virtualFile = virtualSourceRoot.toVirtualFile(file); - System.out.println("Installing dependencies from " + virtualFile); - ProcessBuilder pb = - new ProcessBuilder( - Arrays.asList( - "yarn", - "install", - "--non-interactive", - "--ignore-scripts", - "--ignore-platform", - "--ignore-engines", - "--ignore-optional", - "--no-default-rc", - "--no-bin-links", - "--pure-lockfile")); - pb.directory(virtualFile.getParent().toFile()); - pb.redirectOutput(Redirect.INHERIT); - pb.redirectError(Redirect.INHERIT); + List> futures = new ArrayList<>(); + packageJsonFiles.forEach((file, packageJson) -> { + Path virtualFile = virtualSourceRoot.toVirtualFile(file); + Path nodeModulesDir = virtualFile.getParent().resolve("node_modules"); + futures.add(new DependencyResolver(installationThreadPool, packagesInRepo.keySet()).installDependencies(packageJson, nodeModulesDir)); + }); + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); + } finally { + installationThreadPool.shutdown(); try { - pb.start().waitFor(this.installDependenciesTimeout, TimeUnit.MILLISECONDS); - } catch (IOException | InterruptedException ex) { - throw new ResourceError("Could not install dependencies from " + file, ex); + installationThreadPool.awaitTermination(1, TimeUnit.HOURS); + } catch (InterruptedException e) { + Exceptions.ignore(e, "Awaiting termination is not essential."); } } } @@ -917,7 +817,7 @@ protected DependencyInstallationResult preparePackagesAndDependencies(Set * given package - that is, the file you get when importing the package by name * without any path suffix. */ - private Path guessPackageMainFile(Path packageJsonFile, JsonObject packageJson, Iterable extensions) { + private Path guessPackageMainFile(Path packageJsonFile, PackageJson packageJson, Iterable extensions) { Path packageDir = packageJsonFile.getParent(); // Try /index.ts. @@ -929,7 +829,7 @@ protected DependencyInstallationResult preparePackagesAndDependencies(Set // Get the "main" property from the package.json // This usually refers to the compiled output, such as `./out/foo.js` but may hint as to // the name of main file ("foo" in this case). - String mainStr = getChildAsString(packageJson, "main"); + String mainStr = packageJson.getMain(); // Look for source files `./src` if it exists Path sourceDir = packageDir.resolve("src"); From 57a588ceb6d841e6fb7214da3a90f80a07369ddb Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 17 Sep 2020 14:42:56 +0100 Subject: [PATCH 244/411] JS: Share extraction results via symlinks --- .../semmle/js/dependencies/AsyncFetcher.java | 42 +++++++++++++++++-- .../js/dependencies/DependencyResolver.java | 11 ++--- .../com/semmle/js/dependencies/Fetcher.java | 13 ++++-- .../com/semmle/js/extractor/AutoBuild.java | 7 ++-- 4 files changed, 55 insertions(+), 18 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java b/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java index 2dbac252eb2..9ea24be6754 100644 --- a/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java +++ b/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java @@ -1,8 +1,10 @@ package com.semmle.js.dependencies; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; @@ -68,17 +70,51 @@ public class AsyncFetcher { }); } + /** Result of a tarball extraction */ + class ExtractionResult { + /** The directory into which the tarball was extracted. */ + Path destDir; + + /** Files created by the extraction, relative to destDir. */ + List relativePaths; + + ExtractionResult(Path destDir, List relativePaths) { + this.destDir = destDir; + this.relativePaths = relativePaths; + } + } + + private CachedOperation tarballExtractions = new CachedOperation<>(); + /** * Extracts the relevant contents of the given tarball URL in the given folder; * the returned future completes when done. */ public CompletableFuture installFromTarballUrl(String tarballUrl, Path destDir) { - return CompletableFuture.runAsync(() -> { + return tarballExtractions.get(tarballUrl, () -> { try { - fetcher.extractFromTarballUrl(tarballUrl, destDir); + List relativePaths = fetcher.extractFromTarballUrl(tarballUrl, destDir); + return new ExtractionResult(destDir, relativePaths); } catch (IOException e) { throw makeError("Could not install package from " + tarballUrl, e); } - }, executor); + }).thenAccept(extractionResult -> { + if (!extractionResult.destDir.equals(destDir)) { + // We've been asked to extract the same tarball into multiple directories (due to multiple package.json files). + // Symlink files from the original directory instead of extracting again. + // In principle we could symlink the whole directory, but directory symlinks are hard to create in a portable way. + System.out.println("Creating symlink farm from " + destDir + " to " + extractionResult.destDir); + for (Path relativePath : extractionResult.relativePaths) { + Path originalFile = extractionResult.destDir.resolve(relativePath); + Path newFile = destDir.resolve(relativePath); + try { + fetcher.mkdirp(newFile.getParent()); + Files.createSymbolicLink(newFile, originalFile); + } catch (IOException e) { + throw makeError("Failed to create symlink " + newFile + " -> " + originalFile, e); + } + } + } + }); } } diff --git a/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java b/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java index 318725fd75b..88f83237ec2 100644 --- a/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java +++ b/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java @@ -12,7 +12,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -45,15 +44,11 @@ public class DependencyResolver { } } - public DependencyResolver(ExecutorService threadPool, Set packagesInRepo) { - this.fetcher = new AsyncFetcher(threadPool, this::reportError); + public DependencyResolver(AsyncFetcher fetcher, Set packagesInRepo) { + this.fetcher = fetcher; this.packagesInRepo = packagesInRepo; } - private void reportError(CompletionException ex) { - System.err.println(ex); - } - private void addConstraint(Constraint constraint) { synchronized(constraints) { constraints.add(constraint); @@ -207,7 +202,7 @@ public class DependencyResolver { public static void main(String[] args) throws IOException { ExecutorService executors = Executors.newFixedThreadPool(50); try { - DependencyResolver resolver = new DependencyResolver(executors, Collections.emptySet()); + DependencyResolver resolver = new DependencyResolver(new AsyncFetcher(executors, err -> { System.err.println(err); }), Collections.emptySet()); for (String packageJsonPath : args) { Path path = Paths.get(packageJsonPath).toAbsolutePath(); PackageJson packageJson = new Gson().fromJson(Files.newBufferedReader(path), PackageJson.class); diff --git a/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java b/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java index 019eedee370..d8aa623a141 100644 --- a/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java +++ b/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java @@ -14,6 +14,8 @@ import java.net.URLConnection; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; import java.util.regex.Pattern; import com.google.gson.Gson; @@ -35,7 +37,7 @@ public class Fetcher { private Object mkdirpLock = new Object(); /** Creates the given directory and its parent directories. Only one thread is allowed to create directories at once. */ - private void mkdirp(Path dir) throws IOException { + public void mkdirp(Path dir) throws IOException { synchronized (mkdirpLock) { Files.createDirectories(dir); } @@ -88,14 +90,17 @@ public class Fetcher { /** * Extracts the package at the given tarball URL into the given directory. - * + *

    * Only `package.json` and `.d.ts` files are extracted. + * + * @return paths of the files created by this call, relative to destDir */ - public void extractFromTarballUrl(String tarballUrl, Path destDir) throws IOException { + public List extractFromTarballUrl(String tarballUrl, Path destDir) throws IOException { if (!tarballUrl.startsWith("https://registry.npmjs.org/") || !tarballUrl.endsWith(".tgz")) { // Paranoid check throw new IOException("Tarball URL has unexpected format: " + tarballUrl); } System.out.println("Unpacking " + tarballUrl + " to " + destDir); + List relativePaths = new ArrayList<>(); try (InputStream rawStream = new URL(tarballUrl).openStream()) { // Despite having the .tgz extension, the file is not always gzipped, sometimes it's just a raw tar archive, // regardless of what Accept-Encoding header we send. @@ -129,6 +134,7 @@ public class Fetcher { if (!filename.endsWith(".d.ts") && !filename.equals("package.json")) { continue; // Only extract .d.ts files and package.json } + relativePaths.add(entryPath); Path outputFile = destDir.resolve(entryPath); mkdirp(outputFile.getParent()); try (OutputStream output = new BufferedOutputStream(Files.newOutputStream(outputFile))) { @@ -136,5 +142,6 @@ public class Fetcher { } } } + return relativePaths; } } diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index 04b6e07bece..f698200b40e 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -32,10 +32,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; +import com.semmle.js.dependencies.AsyncFetcher; import com.semmle.js.dependencies.DependencyResolver; import com.semmle.js.dependencies.packument.PackageJson; import com.semmle.js.extractor.ExtractorConfig.SourceType; @@ -791,12 +789,13 @@ protected DependencyInstallationResult preparePackagesAndDependencies(Set // Use more threads for dependency installation than for extraction, as this is mainly I/O bound and we want // many concurrent HTTP requests. ExecutorService installationThreadPool = Executors.newFixedThreadPool(50); + AsyncFetcher fetcher = new AsyncFetcher(installationThreadPool, err -> { System.err.println(err); }); try { List> futures = new ArrayList<>(); packageJsonFiles.forEach((file, packageJson) -> { Path virtualFile = virtualSourceRoot.toVirtualFile(file); Path nodeModulesDir = virtualFile.getParent().resolve("node_modules"); - futures.add(new DependencyResolver(installationThreadPool, packagesInRepo.keySet()).installDependencies(packageJson, nodeModulesDir)); + futures.add(new DependencyResolver(fetcher, packagesInRepo.keySet()).installDependencies(packageJson, nodeModulesDir)); }); CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); } finally { From 85224aad34ea1a5d870f0ba897ccecc86ddf0e22 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Fri, 18 Sep 2020 11:52:53 +0100 Subject: [PATCH 245/411] JS: Address some review comments --- javascript/extractor/lib/typescript/src/main.ts | 2 +- .../src/com/semmle/js/dependencies/VersionConstraint.java | 6 +----- .../src/com/semmle/js/dependencies/packument/Packument.java | 6 ++++++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/javascript/extractor/lib/typescript/src/main.ts b/javascript/extractor/lib/typescript/src/main.ts index 0d43a011761..8224fec0b73 100644 --- a/javascript/extractor/lib/typescript/src/main.ts +++ b/javascript/extractor/lib/typescript/src/main.ts @@ -139,7 +139,7 @@ function getPackageTypings(file: string): string | undefined { function getPackageTypingsRaw(packageJsonFile: string): string | undefined { let json = getPackageJson(packageJsonFile); if (json == null) return undefined; - let typings = json.types || json.typings; + let typings = json.types || json.typings; // "types" and "typings" are aliases if (typeof typings !== 'string') return undefined; let absolutePath = pathlib.join(pathlib.dirname(packageJsonFile), typings); if (ts.sys.directoryExists(absolutePath)) { diff --git a/javascript/extractor/src/com/semmle/js/dependencies/VersionConstraint.java b/javascript/extractor/src/com/semmle/js/dependencies/VersionConstraint.java index da66bd32eac..b0cadaa1a2b 100644 --- a/javascript/extractor/src/com/semmle/js/dependencies/VersionConstraint.java +++ b/javascript/extractor/src/com/semmle/js/dependencies/VersionConstraint.java @@ -14,10 +14,6 @@ public class VersionConstraint { this.version = version; } - public static VersionConstraint exact(String version) { - return new VersionConstraint("", SemVer.tryParse(version)); - } - public String getOperator() { return operator; } @@ -42,7 +38,7 @@ public class VersionConstraint { String operator = matcher.group(1); String versionStr = matcher.group(2); if (operator.isEmpty() && versionStr.contains("x")) { - // Normalize "1.x" to ">= 1.0" + // Treat "1.x" as ">= 1.0" operator = ">="; versionStr = versionStr.replaceAll("x", "0"); } diff --git a/javascript/extractor/src/com/semmle/js/dependencies/packument/Packument.java b/javascript/extractor/src/com/semmle/js/dependencies/packument/Packument.java index 74c7882e0b4..b551089d02b 100644 --- a/javascript/extractor/src/com/semmle/js/dependencies/packument/Packument.java +++ b/javascript/extractor/src/com/semmle/js/dependencies/packument/Packument.java @@ -2,6 +2,12 @@ package com.semmle.js.dependencies.packument; import java.util.Map; +/** + * A package metadata object, informally known as a "packument". + * + * @see https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md#getpackage + * @see https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md + */ public class Packument { private String name; private Map versions; From 26b7d57a94bec66ebcf7ab3d0b6279ce2f5d7ec3 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Mon, 21 Sep 2020 12:45:37 +0100 Subject: [PATCH 246/411] JS: Parse preferred version directly --- .../js/dependencies/DependencyResolver.java | 33 +++++++++--- .../js/dependencies/VersionConstraint.java | 53 ------------------- 2 files changed, 26 insertions(+), 60 deletions(-) delete mode 100644 javascript/extractor/src/com/semmle/js/dependencies/VersionConstraint.java diff --git a/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java b/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java index 88f83237ec2..3049c78e260 100644 --- a/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java +++ b/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java @@ -14,6 +14,8 @@ import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import com.google.gson.Gson; import com.semmle.js.dependencies.packument.PackageJson; @@ -55,6 +57,8 @@ public class DependencyResolver { } } + private static final Pattern semVerToken = Pattern.compile("[~^<>=|&-]+|\\d+(?:\\.[\\dx]+)+(?:-[\\w.-]*)?"); + /** * Returns the first version number mentioned in the given constraints, excluding upper bounds such as `< 2.0.0`, * or `null` if no such version number was found. @@ -62,10 +66,25 @@ public class DependencyResolver { * To help ensure deterministic version resolution, we prefer the version mentioned in the constraint, rather than * the latest version satisfying the constraint (as the latter can change in time). */ - private SemVer getPreferredVersionFromConstraints(List constraints) { - for (VersionConstraint constraint : constraints) { - if (!constraint.getOperator().equals("<") && constraint.getVersion() != null) { - return constraint.getVersion(); + public static SemVer getPreferredVersionFromVersionSpec(String versionSpec) { + versionSpec = versionSpec.trim(); + boolean isFirst = true; + Matcher m = semVerToken.matcher(versionSpec); + while (m.find()) { + if (isFirst && m.start() != 0) { + return null; // Not a version range + } + isFirst = false; + String text = m.group(); + if (text.equals("<")) { + // Skip next token to ignore upper bound constraints like `< 2.0.0`. + if (!m.find()) break; + } + if (text.charAt(0) >= '0' && text.charAt(0) <= '9') { + SemVer semVer = SemVer.tryParse(text.replace("x", "0")); + if (semVer != null) { + return semVer; + } } } return null; @@ -103,8 +122,8 @@ public class DependencyResolver { if (packagesInRepo.contains(targetName)) { return; } - List constraints = VersionConstraint.parseVersionConstraints(targetVersions); - SemVer preferredVersion = getPreferredVersionFromConstraints(constraints); + SemVer preferredVersion = getPreferredVersionFromVersionSpec(targetVersions); + System.out.println("Prefer " + preferredVersion + " from " + targetVersions); if (preferredVersion == null) return; futures.add(fetcher.getPackument(targetName).exceptionally(ex -> null).thenCompose(targetPackument -> { if (targetPackument == null) { @@ -198,7 +217,7 @@ public class DependencyResolver { }); } - /** Entry point which installs dependencies from a given `package.json`, used for testing andbenchmarking. */ + /** Entry point which installs dependencies from a given `package.json`, used for testing and benchmarking. */ public static void main(String[] args) throws IOException { ExecutorService executors = Executors.newFixedThreadPool(50); try { diff --git a/javascript/extractor/src/com/semmle/js/dependencies/VersionConstraint.java b/javascript/extractor/src/com/semmle/js/dependencies/VersionConstraint.java deleted file mode 100644 index b0cadaa1a2b..00000000000 --- a/javascript/extractor/src/com/semmle/js/dependencies/VersionConstraint.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.semmle.js.dependencies; - -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class VersionConstraint { - private String operator; - private SemVer version; - - public VersionConstraint(String operator, SemVer version) { - this.operator = operator; - this.version = version; - } - - public String getOperator() { - return operator; - } - - public SemVer getVersion() { - return version; - } - - private static final Pattern pattern = Pattern.compile("([~^<>=]*)\\s*(\\d.*)"); - - public static List parseVersionConstraints(String str) { - String[] parts = str.split(","); - List constraints = new ArrayList<>(); - for (String part : parts) { - part = part.trim(); - if (part.equals("*")) { - constraints.add(new VersionConstraint("*", null)); - continue; - } - Matcher matcher = pattern.matcher(str); - if (matcher.matches()) { - String operator = matcher.group(1); - String versionStr = matcher.group(2); - if (operator.isEmpty() && versionStr.contains("x")) { - // Treat "1.x" as ">= 1.0" - operator = ">="; - versionStr = versionStr.replaceAll("x", "0"); - } - SemVer version = SemVer.tryParse(versionStr); - if (version != null) { - constraints.add(new VersionConstraint(operator, version)); - } - } - } - return constraints; - } -} From b1bd6122326d4976a9ac777410d91f31a519605d Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 22 Sep 2020 14:04:42 +0100 Subject: [PATCH 247/411] JS: Undo unused export --- javascript/extractor/lib/typescript/src/common.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/extractor/lib/typescript/src/common.ts b/javascript/extractor/lib/typescript/src/common.ts index ba06a0195c9..c660b7bcb5e 100644 --- a/javascript/extractor/lib/typescript/src/common.ts +++ b/javascript/extractor/lib/typescript/src/common.ts @@ -9,7 +9,7 @@ import { VirtualSourceRoot } from "./virtual_source_root"; const packageNameRex = /^(?:@[\w.-]+[/\\]+)?\w[\w.-]*(?=[/\\]|$)/; const extensions = ['.ts', '.tsx', '.d.ts', '.js', '.jsx']; -export function getPackageName(importString: string) { +function getPackageName(importString: string) { let packageNameMatch = packageNameRex.exec(importString); if (packageNameMatch == null) return null; let packageName = packageNameMatch[0]; From 0ddd825ea657b6b2db7f0eba8eed8e1e9af9e715 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 22 Sep 2020 14:25:13 +0100 Subject: [PATCH 248/411] JS: Address some more review comments --- javascript/extractor/lib/typescript/src/main.ts | 2 +- .../extractor/src/com/semmle/js/dependencies/AsyncFetcher.java | 2 +- .../extractor/src/com/semmle/js/dependencies/Fetcher.java | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/javascript/extractor/lib/typescript/src/main.ts b/javascript/extractor/lib/typescript/src/main.ts index 8224fec0b73..eb3ce99a875 100644 --- a/javascript/extractor/lib/typescript/src/main.ts +++ b/javascript/extractor/lib/typescript/src/main.ts @@ -103,7 +103,7 @@ class State { public packageTypings = new Map(); /** Map from file path to the enclosing `package.json` file, if any. Will not traverse outside node_modules. */ - public enclosingPackageJson = new Map(); + public enclosingPackageJson = new Map(); } let state = new State(); diff --git a/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java b/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java index 9ea24be6754..f4f5d33b4da 100644 --- a/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java +++ b/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java @@ -71,7 +71,7 @@ public class AsyncFetcher { } /** Result of a tarball extraction */ - class ExtractionResult { + private static class ExtractionResult { /** The directory into which the tarball was extracted. */ Path destDir; diff --git a/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java b/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java index d8aa623a141..79fc7c2c65a 100644 --- a/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java +++ b/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java @@ -105,6 +105,8 @@ public class Fetcher { // Despite having the .tgz extension, the file is not always gzipped, sometimes it's just a raw tar archive, // regardless of what Accept-Encoding header we send. // Sniff the header to detect which is the case. + // Note that the compression format has nothing to do with the Accept-Encoding/Content-Encoding headers, + // so we can't reuse the code from fetch(). PushbackInputStream pushback = new PushbackInputStream(rawStream, 2); int byte1 = pushback.read(); int byte2 = pushback.read(); From 4e2b990d1471d6bf61257c4e493fd40da30dfa20 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 22 Sep 2020 14:07:21 +0100 Subject: [PATCH 249/411] Add doc string to semVerToken Co-authored-by: Erik Krogh Kristensen --- .../src/com/semmle/js/dependencies/DependencyResolver.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java b/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java index 3049c78e260..d3ea4b61392 100644 --- a/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java +++ b/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java @@ -57,7 +57,8 @@ public class DependencyResolver { } } - private static final Pattern semVerToken = Pattern.compile("[~^<>=|&-]+|\\d+(?:\\.[\\dx]+)+(?:-[\\w.-]*)?"); + // Matches either a version ("2.1.x" / "3.0", etc..), or a version constraint operator ("<", "||", "~", etc...). + private static final Pattern semVerToken = Pattern.compile("\\d+(?:\\.[\\dx]+)+(?:-[\\w.-]*)?|[~^<>=|&-]+"); /** * Returns the first version number mentioned in the given constraints, excluding upper bounds such as `< 2.0.0`, From 433e3e7e4ed08a71d1c9521fc956e4d7e6c619b5 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 22 Sep 2020 14:17:51 +0100 Subject: [PATCH 250/411] JS: Expand doc string in installFromTarballurl Co-authored-by: Erik Krogh Kristensen --- .../extractor/src/com/semmle/js/dependencies/AsyncFetcher.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java b/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java index f4f5d33b4da..7d953f4b54a 100644 --- a/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java +++ b/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java @@ -89,6 +89,8 @@ public class AsyncFetcher { /** * Extracts the relevant contents of the given tarball URL in the given folder; * the returned future completes when done. + * + * If the same tarball has already been extracted elsewhere, then symbolic links are added to `destDir` linking to the already extracted tarball. */ public CompletableFuture installFromTarballUrl(String tarballUrl, Path destDir) { return tarballExtractions.get(tarballUrl, () -> { From 5374b66029d4193e31014f29ec1438761be3d318 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 22 Sep 2020 14:27:17 +0100 Subject: [PATCH 251/411] JS: Make CachedOperation private --- .../extractor/src/com/semmle/js/dependencies/AsyncFetcher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java b/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java index 7d953f4b54a..b42123d655c 100644 --- a/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java +++ b/javascript/extractor/src/com/semmle/js/dependencies/AsyncFetcher.java @@ -40,7 +40,7 @@ public class AsyncFetcher { throw ex; } - class CachedOperation { + private class CachedOperation { private Map> cache = new LinkedHashMap<>(); public synchronized CompletableFuture get(K key, Supplier builder) { From 8e82687ab6a2d1958b74c6282037585ceea76ac5 Mon Sep 17 00:00:00 2001 From: Joe Date: Wed, 23 Sep 2020 12:19:43 +0100 Subject: [PATCH 252/411] Java: Include column numbers in Location.toString --- java/ql/src/semmle/code/Location.qll | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/java/ql/src/semmle/code/Location.qll b/java/ql/src/semmle/code/Location.qll index 5f7590c80e8..8bfd54ae79d 100755 --- a/java/ql/src/semmle/code/Location.qll +++ b/java/ql/src/semmle/code/Location.qll @@ -150,12 +150,18 @@ class Location extends @location { /** Gets a string representation containing the file and range for this location. */ string toString() { - exists(File f, int startLine, int endLine | - locations_default(this, f, startLine, _, endLine, _) + exists(File f, int startLine, int startCol, int endLine, int endCol | + locations_default(this, f, startLine, startCol, endLine, endCol) | if endLine = startLine - then result = f.toString() + ":" + startLine.toString() - else result = f.toString() + ":" + startLine.toString() + "-" + endLine.toString() + then + result = + f.toString() + ":" + startLine.toString() + "[" + startCol.toString() + "-" + + endCol.toString() + "]" + else + result = + f.toString() + ":" + startLine.toString() + "[" + startCol.toString() + "]-" + + endLine.toString() + "[" + endCol.toString() + "]" ) } From 99213b94f577dd0b0a2830f4081c6d96a66fb1e0 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 6 Oct 2020 12:23:15 +0200 Subject: [PATCH 253/411] detect uses of jsxFactory and jsxFragmentFactory in js/unused-local-variable --- javascript/ql/src/Declarations/UnusedVariable.ql | 10 ++++++++++ .../Declarations/UnusedVariable/ts/tsconfig.json | 6 ++++++ .../Declarations/UnusedVariable/ts/usesreact.tsx | 5 +++++ 3 files changed, 21 insertions(+) create mode 100644 javascript/ql/test/query-tests/Declarations/UnusedVariable/ts/tsconfig.json create mode 100644 javascript/ql/test/query-tests/Declarations/UnusedVariable/ts/usesreact.tsx diff --git a/javascript/ql/src/Declarations/UnusedVariable.ql b/javascript/ql/src/Declarations/UnusedVariable.ql index b480cb956bd..90c3948b634 100644 --- a/javascript/ql/src/Declarations/UnusedVariable.ql +++ b/javascript/ql/src/Declarations/UnusedVariable.ql @@ -58,6 +58,16 @@ predicate isReactForJSX(UnusedLocal v) { plugin.getJsxFactoryVariableName() = v.getName() ) ) + or + exists(JSONObject tsconfig | + tsconfig.isTopLevel() and tsconfig.getFile().getBaseName() = "tsconfig.json" + | + v.getName() = + tsconfig + .getPropValue("compilerOptions") + .(JSONObject) + .getPropStringValue(["jsxFactory", "jsxFragmentFactory"]) + ) ) } diff --git a/javascript/ql/test/query-tests/Declarations/UnusedVariable/ts/tsconfig.json b/javascript/ql/test/query-tests/Declarations/UnusedVariable/ts/tsconfig.json new file mode 100644 index 00000000000..ff8c14be810 --- /dev/null +++ b/javascript/ql/test/query-tests/Declarations/UnusedVariable/ts/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "jsx": "react", + "jsxFactory": "m" + } +} diff --git a/javascript/ql/test/query-tests/Declarations/UnusedVariable/ts/usesreact.tsx b/javascript/ql/test/query-tests/Declarations/UnusedVariable/ts/usesreact.tsx new file mode 100644 index 00000000000..37800165414 --- /dev/null +++ b/javascript/ql/test/query-tests/Declarations/UnusedVariable/ts/usesreact.tsx @@ -0,0 +1,5 @@ +import {m} from 'some-react-library'; + +export default function doAThing() { + return foo; +} From f9c5b864bbd3474c864d34996f7167e11cf0f1f6 Mon Sep 17 00:00:00 2001 From: Rasmus Lerchedahl Petersen Date: Tue, 6 Oct 2020 13:12:12 +0200 Subject: [PATCH 254/411] Python: Fix test of parenthesized form --- .../test/experimental/dataflow/coverage/dataflow.expected | 8 ++++---- python/ql/test/experimental/dataflow/coverage/test.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index 4e558bd1247..e49bed3919a 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -30,7 +30,7 @@ edges | datamodel.py:159:6:159:15 | ControlFlowNode for customized [Attribute b] | datamodel.py:159:6:159:17 | ControlFlowNode for Attribute | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:36:21:36:26 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:49:9:49:14 | ControlFlowNode for SOURCE | -| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:81:9:81:14 | ControlFlowNode for SOURCE | +| test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:81:10:81:15 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:87:10:87:15 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:97:10:97:15 | ControlFlowNode for SOURCE | | test.py:0:0:0:0 | ModuleVariableNode for Global Variable SOURCE in Module test | test.py:102:22:102:27 | ControlFlowNode for SOURCE | @@ -64,7 +64,7 @@ edges | test.py:60:9:60:17 | ControlFlowNode for Str | test.py:61:10:61:10 | ControlFlowNode for x | | test.py:65:9:65:10 | ControlFlowNode for IntegerLiteral | test.py:66:10:66:10 | ControlFlowNode for x | | test.py:70:9:70:12 | ControlFlowNode for FloatLiteral | test.py:71:10:71:10 | ControlFlowNode for x | -| test.py:81:9:81:14 | ControlFlowNode for SOURCE | test.py:82:10:82:10 | ControlFlowNode for x | +| test.py:81:10:81:15 | ControlFlowNode for SOURCE | test.py:82:10:82:10 | ControlFlowNode for x | | test.py:87:9:87:16 | ControlFlowNode for List [List element] | test.py:88:10:88:10 | ControlFlowNode for x [List element] | | test.py:87:10:87:15 | ControlFlowNode for SOURCE | test.py:87:9:87:16 | ControlFlowNode for List [List element] | | test.py:88:10:88:10 | ControlFlowNode for x [List element] | test.py:88:10:88:13 | ControlFlowNode for Subscript | @@ -193,7 +193,7 @@ nodes | test.py:66:10:66:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | | test.py:70:9:70:12 | ControlFlowNode for FloatLiteral | semmle.label | ControlFlowNode for FloatLiteral | | test.py:71:10:71:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:81:9:81:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:81:10:81:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | | test.py:82:10:82:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | | test.py:87:9:87:16 | ControlFlowNode for List [List element] | semmle.label | ControlFlowNode for List [List element] | | test.py:87:10:87:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | @@ -341,7 +341,7 @@ nodes | test.py:66:10:66:10 | ControlFlowNode for x | test.py:65:9:65:10 | ControlFlowNode for IntegerLiteral | test.py:66:10:66:10 | ControlFlowNode for x | Flow found | | test.py:71:10:71:10 | ControlFlowNode for x | test.py:70:9:70:12 | ControlFlowNode for FloatLiteral | test.py:71:10:71:10 | ControlFlowNode for x | Flow found | | test.py:82:10:82:10 | ControlFlowNode for x | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:82:10:82:10 | ControlFlowNode for x | Flow found | -| test.py:82:10:82:10 | ControlFlowNode for x | test.py:81:9:81:14 | ControlFlowNode for SOURCE | test.py:82:10:82:10 | ControlFlowNode for x | Flow found | +| test.py:82:10:82:10 | ControlFlowNode for x | test.py:81:10:81:15 | ControlFlowNode for SOURCE | test.py:82:10:82:10 | ControlFlowNode for x | Flow found | | test.py:88:10:88:13 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:88:10:88:13 | ControlFlowNode for Subscript | Flow found | | test.py:88:10:88:13 | ControlFlowNode for Subscript | test.py:87:10:87:15 | ControlFlowNode for SOURCE | test.py:88:10:88:13 | ControlFlowNode for Subscript | Flow found | | test.py:98:10:98:13 | ControlFlowNode for Subscript | test.py:14:10:14:17 | ControlFlowNode for Str | test.py:98:10:98:13 | ControlFlowNode for Subscript | Flow found | diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 744082b84e2..c59b01e306b 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -78,7 +78,7 @@ def test_imagnumber_literal(): # 6.2.3. Parenthesized forms def test_parenthesized_form(): - x = SOURCE + x = (SOURCE) SINK(x) From 396f353397277432cb3b5309939e531c460184bc Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 6 Oct 2020 14:06:10 +0100 Subject: [PATCH 255/411] JS: Reapply fixed to javadoc --- .../src/com/semmle/js/dependencies/DependencyResolver.java | 2 +- .../src/com/semmle/js/dependencies/packument/Packument.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java b/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java index d3ea4b61392..cd0ff098419 100644 --- a/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java +++ b/javascript/extractor/src/com/semmle/js/dependencies/DependencyResolver.java @@ -61,7 +61,7 @@ public class DependencyResolver { private static final Pattern semVerToken = Pattern.compile("\\d+(?:\\.[\\dx]+)+(?:-[\\w.-]*)?|[~^<>=|&-]+"); /** - * Returns the first version number mentioned in the given constraints, excluding upper bounds such as `< 2.0.0`, + * Returns the first version number mentioned in the given constraints, excluding upper bounds such as `< 2.0.0`, * or `null` if no such version number was found. *

    * To help ensure deterministic version resolution, we prefer the version mentioned in the constraint, rather than diff --git a/javascript/extractor/src/com/semmle/js/dependencies/packument/Packument.java b/javascript/extractor/src/com/semmle/js/dependencies/packument/Packument.java index b551089d02b..cfc9c318cec 100644 --- a/javascript/extractor/src/com/semmle/js/dependencies/packument/Packument.java +++ b/javascript/extractor/src/com/semmle/js/dependencies/packument/Packument.java @@ -5,8 +5,8 @@ import java.util.Map; /** * A package metadata object, informally known as a "packument". * - * @see https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md#getpackage - * @see https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md + * see https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md#getpackage + * see https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md */ public class Packument { private String name; From 95b6b16b579be889555f0d45328d7ab2fb67c72d Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 29 Sep 2020 19:43:24 +0100 Subject: [PATCH 256/411] JavaScript: Add another API-graph test with re-exports. --- .../ql/test/ApiGraphs/reexport/VerifyAssertions.expected | 1 + javascript/ql/test/ApiGraphs/reexport/index.js | 3 ++- javascript/ql/test/ApiGraphs/reexport/lib/stuff.js | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 javascript/ql/test/ApiGraphs/reexport/lib/stuff.js diff --git a/javascript/ql/test/ApiGraphs/reexport/VerifyAssertions.expected b/javascript/ql/test/ApiGraphs/reexport/VerifyAssertions.expected index 9815f2e44c8..53c5f78647b 100644 --- a/javascript/ql/test/ApiGraphs/reexport/VerifyAssertions.expected +++ b/javascript/ql/test/ApiGraphs/reexport/VerifyAssertions.expected @@ -1 +1,2 @@ +| lib/stuff.js:1:19:1:103 | /* use ... )))) */ | def (member other (member exports (module reexport))) has no outgoing edge labelled member bar; it has no outgoing edges at all. | | lib/utils.js:1:38:1:120 | /* use ... )))) */ | def (member util (member exports (module reexport))) has no outgoing edge labelled member id; it has no outgoing edges at all. | diff --git a/javascript/ql/test/ApiGraphs/reexport/index.js b/javascript/ql/test/ApiGraphs/reexport/index.js index b88845d7175..6d985f19570 100644 --- a/javascript/ql/test/ApiGraphs/reexport/index.js +++ b/javascript/ql/test/ApiGraphs/reexport/index.js @@ -2,5 +2,6 @@ const impl = require("./lib/impl.js"); module.exports = { impl, - util: require("./lib/utils") + util: require("./lib/utils"), + other: require("./lib/stuff") }; \ No newline at end of file diff --git a/javascript/ql/test/ApiGraphs/reexport/lib/stuff.js b/javascript/ql/test/ApiGraphs/reexport/lib/stuff.js new file mode 100644 index 00000000000..f2a9bd7f56d --- /dev/null +++ b/javascript/ql/test/ApiGraphs/reexport/lib/stuff.js @@ -0,0 +1,5 @@ +function foo(x) { /* use (parameter 0 (member bar (member other (member exports (module reexport)))) */ + return x + 1; +} + +export const bar = foo; \ No newline at end of file From 96bf82e1ca8459d49f4908561d41d715afe07e5d Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 29 Sep 2020 19:44:32 +0100 Subject: [PATCH 257/411] JavaScript: Make new source-node classes in API graphs more general and more useful. --- .../ql/src/semmle/javascript/ApiGraphs.qll | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index da78e3a543d..45237b596a8 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -561,15 +561,11 @@ module API { cached predicate use(TApiNode nd, DataFlow::Node ref) { exists(string m, Module mod | nd = MkModuleDef(m) and mod = importableModule(m) | - ref = DataFlow::ssaDefinitionNode(SSA::implicitInit(mod.(NodeModule).getModuleVariable())) - or - ref = DataFlow::parameterNode(mod.(AmdModule).getDefine().getModuleParameter()) + ref.(ModuleAsSourceNode).getModule() = mod ) or exists(string m, Module mod | nd = MkModuleExport(m) and mod = importableModule(m) | - ref = DataFlow::ssaDefinitionNode(SSA::implicitInit(mod.(NodeModule).getExportsVariable())) - or - ref = DataFlow::parameterNode(mod.(AmdModule).getDefine().getExportsParameter()) + ref.(ExportsAsSourceNode).getModule() = mod or exists(DataFlow::Node base | use(MkModuleDef(m), base) | ref = trackUseNode(base).getAPropertyRead("exports") @@ -796,13 +792,31 @@ private module Label { } /** - * A CommonJS `module` or `exports` variable, considered as a source node. + * A CommonJS/AMD `module` variable, considered as a source node. */ -private class AdditionalSourceNode extends DataFlow::SourceNode::Range { - AdditionalSourceNode() { - exists(NodeModule m, Variable v | - v in [m.getModuleVariable(), m.getExportsVariable()] and - this = DataFlow::ssaDefinitionNode(SSA::implicitInit(v)) - ) +private class ModuleAsSourceNode extends DataFlow::SourceNode::Range { + Module m; + + ModuleAsSourceNode() { + this = DataFlow::ssaDefinitionNode(SSA::implicitInit(m.(NodeModule).getModuleVariable())) + or + this = DataFlow::parameterNode(m.(AmdModule).getDefine().getModuleParameter()) } + + Module getModule() { result = m } +} + +/** + * A CommonJS/AMD `exports` variable, considered as a source node. + */ +private class ExportsAsSourceNode extends DataFlow::SourceNode::Range { + Module m; + + ExportsAsSourceNode() { + this = DataFlow::ssaDefinitionNode(SSA::implicitInit(m.(NodeModule).getExportsVariable())) + or + this = DataFlow::parameterNode(m.(AmdModule).getDefine().getExportsParameter()) + } + + Module getModule() { result = m } } From d054206004f2a4787931cbd06772e0147e410388 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 29 Sep 2020 19:45:11 +0100 Subject: [PATCH 258/411] JavaScript: Improve handling of re-exports in API graphs. --- javascript/ql/src/semmle/javascript/ApiGraphs.qll | 9 +++++++++ .../ql/test/ApiGraphs/reexport/VerifyAssertions.expected | 1 - 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 45237b596a8..60d2c3c5c2a 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -419,11 +419,20 @@ module API { exists(DataFlow::Node def, DataFlow::SourceNode pred | rhs(base, def) and pred = trackDefNode(def) | + // from `x` to a definition of `x.prop` exists(DataFlow::PropWrite pw | pw = pred.getAPropertyWrite() | lbl = Label::memberFromRef(pw) and rhs = pw.getRhs() ) or + // special case: from `require('m')` to an export of `prop` in `m` + exists(Import imp, Module m, string prop | + pred = imp.getImportedModuleNode() and + m = imp.getImportedModule() and + lbl = Label::member(prop) and + rhs = m.getAnExportedValue(prop) + ) + or exists(DataFlow::FunctionNode fn | fn = pred | not fn.getFunction().isAsync() and lbl = Label::return() and diff --git a/javascript/ql/test/ApiGraphs/reexport/VerifyAssertions.expected b/javascript/ql/test/ApiGraphs/reexport/VerifyAssertions.expected index 53c5f78647b..9815f2e44c8 100644 --- a/javascript/ql/test/ApiGraphs/reexport/VerifyAssertions.expected +++ b/javascript/ql/test/ApiGraphs/reexport/VerifyAssertions.expected @@ -1,2 +1 @@ -| lib/stuff.js:1:19:1:103 | /* use ... )))) */ | def (member other (member exports (module reexport))) has no outgoing edge labelled member bar; it has no outgoing edges at all. | | lib/utils.js:1:38:1:120 | /* use ... )))) */ | def (member util (member exports (module reexport))) has no outgoing edge labelled member id; it has no outgoing edges at all. | From 1d8051eee05dc910fa20795b1da4d8cbaa221560 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 29 Sep 2020 19:47:56 +0100 Subject: [PATCH 259/411] JavaScript: Further improve handling of re-exports in API graphs. --- javascript/ql/src/semmle/javascript/ApiGraphs.qll | 10 ++++++++++ .../test/ApiGraphs/reexport/VerifyAssertions.expected | 1 - 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 60d2c3c5c2a..3f7152d4438 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -645,6 +645,16 @@ module API { rhs(_, nd) and result = nd.getALocalSource() or + // additional backwards step from `require('m')` to `exports` or `module.exports` in m + exists(Import imp | imp.getImportedModuleNode() = trackDefNode(nd, t.continue()) | + result.(ExportsAsSourceNode).getModule() = imp.getImportedModule() + or + exists(ModuleAsSourceNode mod | + mod.getModule() = imp.getImportedModule() and + result = mod.(DataFlow::SourceNode).getAPropertyRead("exports") + ) + ) + or exists(DataFlow::TypeBackTracker t2 | result = trackDefNode(nd, t2).backtrack(t2, t)) } diff --git a/javascript/ql/test/ApiGraphs/reexport/VerifyAssertions.expected b/javascript/ql/test/ApiGraphs/reexport/VerifyAssertions.expected index 9815f2e44c8..e69de29bb2d 100644 --- a/javascript/ql/test/ApiGraphs/reexport/VerifyAssertions.expected +++ b/javascript/ql/test/ApiGraphs/reexport/VerifyAssertions.expected @@ -1 +0,0 @@ -| lib/utils.js:1:38:1:120 | /* use ... )))) */ | def (member util (member exports (module reexport))) has no outgoing edge labelled member id; it has no outgoing edges at all. | From 1d9acbfca9391e14d771e0fcbd35ac122a4e3df6 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 6 Oct 2020 14:51:11 +0200 Subject: [PATCH 260/411] C++: Demonstrate overflowing guard bounds --- .../SimpleRangeAnalysis/lowerBound.expected | 4 ++++ .../rangeanalysis/SimpleRangeAnalysis/test.c | 14 +++++++++++++- .../SimpleRangeAnalysis/upperBound.expected | 4 ++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected index 620cf26619e..8477847b92c 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected @@ -582,6 +582,10 @@ | test.c:635:9:635:10 | ss | -32768 | | test.c:638:7:638:8 | ss | -32768 | | test.c:639:9:639:10 | ss | -1 | +| test.c:645:7:645:7 | i | 0 | +| test.c:646:9:646:9 | i | -2147483648 | +| test.c:650:7:650:7 | u | 0 | +| test.c:651:9:651:9 | u | 0 | | test.cpp:10:7:10:7 | b | -2147483648 | | test.cpp:11:5:11:5 | x | -2147483648 | | test.cpp:13:10:13:10 | x | -2147483648 | diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c index fa66212db86..15d836dfc5e 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c @@ -638,4 +638,16 @@ void two_bounds_from_one_test(short ss, unsigned short us) { if (ss + 1 < sizeof(int)) { out(ss); // -1 .. 2 } -} \ No newline at end of file +} + +void guard_bound_out_of_range(void) { + int i = 0; + if (i < 0) { + out(i); // 0 .. 0 [BUG: is -max .. +max] + } + + unsigned int u = 0; + if (u < 0) { + out(u); // 0 .. 0 [BUG: is 0 .. +max] + } +} diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected index 7f4dfc3dd94..29c24f3206d 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected @@ -582,6 +582,10 @@ | test.c:635:9:635:10 | ss | 32767 | | test.c:638:7:638:8 | ss | 32767 | | test.c:639:9:639:10 | ss | 2 | +| test.c:645:7:645:7 | i | 0 | +| test.c:646:9:646:9 | i | 2147483647 | +| test.c:650:7:650:7 | u | 0 | +| test.c:651:9:651:9 | u | 4294967295 | | test.cpp:10:7:10:7 | b | 2147483647 | | test.cpp:11:5:11:5 | x | 2147483647 | | test.cpp:13:10:13:10 | x | 2147483647 | From 56604e005aa3b788bb8a64cd48bbb5e3c2ddb9c9 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 23 Sep 2020 14:47:10 +0200 Subject: [PATCH 261/411] C#: Upgrade to .net core app 3.1 --- .../Semmle.Autobuild.Cpp.Tests.csproj | 2 +- .../Semmle.Autobuild.Cpp/Semmle.Autobuild.Cpp.csproj | 2 +- .../Semmle.Autobuild.CSharp.Tests.csproj | 2 +- .../Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj | 2 +- .../Semmle.Autobuild.Shared/Semmle.Autobuild.Shared.csproj | 2 +- .../Semmle.Extraction.CIL.Driver.csproj | 2 +- .../Semmle.Extraction.CIL/Semmle.Extraction.CIL.csproj | 2 +- .../Semmle.Extraction.CSharp.Driver.csproj | 2 +- .../Semmle.Extraction.CSharp.Standalone.csproj | 2 +- .../Semmle.Extraction.CSharp/Semmle.Extraction.CSharp.csproj | 2 +- .../Semmle.Extraction.Tests/Semmle.Extraction.Tests.csproj | 2 +- csharp/extractor/Semmle.Extraction/Semmle.Extraction.csproj | 2 +- csharp/extractor/Semmle.Util.Tests/Semmle.Util.Tests.csproj | 2 +- csharp/extractor/Semmle.Util/Semmle.Util.csproj | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/Semmle.Autobuild.Cpp.Tests.csproj b/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/Semmle.Autobuild.Cpp.Tests.csproj index 204b6418299..7de677b5610 100644 --- a/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/Semmle.Autobuild.Cpp.Tests.csproj +++ b/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/Semmle.Autobuild.Cpp.Tests.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.0 + netcoreapp3.1 false win-x64;linux-x64;osx-x64 enable diff --git a/cpp/autobuilder/Semmle.Autobuild.Cpp/Semmle.Autobuild.Cpp.csproj b/cpp/autobuilder/Semmle.Autobuild.Cpp/Semmle.Autobuild.Cpp.csproj index 43e958183ea..aadcc07568d 100644 --- a/cpp/autobuilder/Semmle.Autobuild.Cpp/Semmle.Autobuild.Cpp.csproj +++ b/cpp/autobuilder/Semmle.Autobuild.Cpp/Semmle.Autobuild.Cpp.csproj @@ -1,7 +1,7 @@ - netcoreapp3.0 + netcoreapp3.1 Semmle.Autobuild.Cpp Semmle.Autobuild.Cpp diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/Semmle.Autobuild.CSharp.Tests.csproj b/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/Semmle.Autobuild.CSharp.Tests.csproj index be45ad8f961..ee3324eb639 100644 --- a/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/Semmle.Autobuild.CSharp.Tests.csproj +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/Semmle.Autobuild.CSharp.Tests.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.0 + netcoreapp3.1 false win-x64;linux-x64;osx-x64 enable diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj b/csharp/autobuilder/Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj index 091f0704ef0..82ca05504bc 100644 --- a/csharp/autobuilder/Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp/Semmle.Autobuild.CSharp.csproj @@ -1,7 +1,7 @@ - netcoreapp3.0 + netcoreapp3.1 Semmle.Autobuild.CSharp Semmle.Autobuild.CSharp diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/Semmle.Autobuild.Shared.csproj b/csharp/autobuilder/Semmle.Autobuild.Shared/Semmle.Autobuild.Shared.csproj index 66a5b26098c..6663c428b03 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/Semmle.Autobuild.Shared.csproj +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/Semmle.Autobuild.Shared.csproj @@ -1,7 +1,7 @@ - netcoreapp3.0 + netcoreapp3.1 Semmle.Autobuild.Shared Semmle.Autobuild.Shared false diff --git a/csharp/extractor/Semmle.Extraction.CIL.Driver/Semmle.Extraction.CIL.Driver.csproj b/csharp/extractor/Semmle.Extraction.CIL.Driver/Semmle.Extraction.CIL.Driver.csproj index 49f183fd9b0..67e40dae2d8 100644 --- a/csharp/extractor/Semmle.Extraction.CIL.Driver/Semmle.Extraction.CIL.Driver.csproj +++ b/csharp/extractor/Semmle.Extraction.CIL.Driver/Semmle.Extraction.CIL.Driver.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.0 + netcoreapp3.1 Semmle.Extraction.CIL.Driver Semmle.Extraction.CIL.Driver false diff --git a/csharp/extractor/Semmle.Extraction.CIL/Semmle.Extraction.CIL.csproj b/csharp/extractor/Semmle.Extraction.CIL/Semmle.Extraction.CIL.csproj index 6626eda5474..eb90b909b81 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Semmle.Extraction.CIL.csproj +++ b/csharp/extractor/Semmle.Extraction.CIL/Semmle.Extraction.CIL.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0 + netcoreapp3.1 Semmle.Extraction.CIL Semmle.Extraction.CIL false diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Driver/Semmle.Extraction.CSharp.Driver.csproj b/csharp/extractor/Semmle.Extraction.CSharp.Driver/Semmle.Extraction.CSharp.Driver.csproj index 7475350f993..3ec25c498fe 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Driver/Semmle.Extraction.CSharp.Driver.csproj +++ b/csharp/extractor/Semmle.Extraction.CSharp.Driver/Semmle.Extraction.CSharp.Driver.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.0 + netcoreapp3.1 Semmle.Extraction.CSharp.Driver Semmle.Extraction.CSharp.Driver false diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj index fc72c824f99..277310cc341 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.0 + netcoreapp3.1 Semmle.Extraction.CSharp.Standalone Semmle.Extraction.CSharp.Standalone false diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Semmle.Extraction.CSharp.csproj b/csharp/extractor/Semmle.Extraction.CSharp/Semmle.Extraction.CSharp.csproj index 7ac3c7728b9..905af7f616a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Semmle.Extraction.CSharp.csproj +++ b/csharp/extractor/Semmle.Extraction.CSharp/Semmle.Extraction.CSharp.csproj @@ -1,7 +1,7 @@ - netcoreapp3.0 + netcoreapp3.1 Semmle.Extraction.CSharp Semmle.Extraction.CSharp false diff --git a/csharp/extractor/Semmle.Extraction.Tests/Semmle.Extraction.Tests.csproj b/csharp/extractor/Semmle.Extraction.Tests/Semmle.Extraction.Tests.csproj index 64980e797cd..830529d3710 100644 --- a/csharp/extractor/Semmle.Extraction.Tests/Semmle.Extraction.Tests.csproj +++ b/csharp/extractor/Semmle.Extraction.Tests/Semmle.Extraction.Tests.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.0 + netcoreapp3.1 false win-x64;linux-x64;osx-x64 enable diff --git a/csharp/extractor/Semmle.Extraction/Semmle.Extraction.csproj b/csharp/extractor/Semmle.Extraction/Semmle.Extraction.csproj index 567dede9407..cc32fc33b38 100644 --- a/csharp/extractor/Semmle.Extraction/Semmle.Extraction.csproj +++ b/csharp/extractor/Semmle.Extraction/Semmle.Extraction.csproj @@ -1,7 +1,7 @@  - netcoreapp3.0 + netcoreapp3.1 Semmle.Extraction Semmle.Extraction false diff --git a/csharp/extractor/Semmle.Util.Tests/Semmle.Util.Tests.csproj b/csharp/extractor/Semmle.Util.Tests/Semmle.Util.Tests.csproj index a82997aea63..3acf1a1fa42 100644 --- a/csharp/extractor/Semmle.Util.Tests/Semmle.Util.Tests.csproj +++ b/csharp/extractor/Semmle.Util.Tests/Semmle.Util.Tests.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.0 + netcoreapp3.1 false win-x64;linux-x64;osx-x64 enable diff --git a/csharp/extractor/Semmle.Util/Semmle.Util.csproj b/csharp/extractor/Semmle.Util/Semmle.Util.csproj index 39f0c7cdedb..fdcd0672395 100644 --- a/csharp/extractor/Semmle.Util/Semmle.Util.csproj +++ b/csharp/extractor/Semmle.Util/Semmle.Util.csproj @@ -1,7 +1,7 @@ - netcoreapp3.0 + netcoreapp3.1 Semmle.Util Semmle.Util false From 4f56a97244f225638e7acabe3fc7a9cd9b1a6a68 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 29 Sep 2020 09:33:55 +0200 Subject: [PATCH 262/411] C#: Adjust expected files for .net 3.1 upgrade --- .../ExternalDependencies/ExternalDependencies.expected | 10 +++++----- .../ExternalDependenciesSourceLinks.expected | 10 +++++----- .../query-tests/Stubs/MinimalStubsFromSource.expected | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/csharp/ql/test/query-tests/Metrics/Dependencies/ExternalDependencies/ExternalDependencies.expected b/csharp/ql/test/query-tests/Metrics/Dependencies/ExternalDependencies/ExternalDependencies.expected index 096443a411d..ca75d5f716a 100644 --- a/csharp/ql/test/query-tests/Metrics/Dependencies/ExternalDependencies/ExternalDependencies.expected +++ b/csharp/ql/test/query-tests/Metrics/Dependencies/ExternalDependencies/ExternalDependencies.expected @@ -1,5 +1,5 @@ -| /query-tests/Metrics/Dependencies/ExternalDependencies/File1.cs<\|>System.Net.Http<\|>4.2.1.0 | 11 | -| /query-tests/Metrics/Dependencies/ExternalDependencies/File1.cs<\|>System.Private.DataContractSerialization<\|>4.1.4.0 | 2 | -| /query-tests/Metrics/Dependencies/ExternalDependencies/File1.cs<\|>System.Private.Xml<\|>4.0.1.0 | 2 | -| /query-tests/Metrics/Dependencies/ExternalDependencies/File1.cs<\|>System.Data.Common<\|>4.2.1.0 | 1 | -| /query-tests/Metrics/Dependencies/ExternalDependencies/File2.cs<\|>System.Net.Http<\|>4.2.1.0 | 1 | +| /query-tests/Metrics/Dependencies/ExternalDependencies/File1.cs<\|>System.Net.Http<\|>4.2.2.0 | 11 | +| /query-tests/Metrics/Dependencies/ExternalDependencies/File1.cs<\|>System.Private.DataContractSerialization<\|>4.1.5.0 | 2 | +| /query-tests/Metrics/Dependencies/ExternalDependencies/File1.cs<\|>System.Private.Xml<\|>4.0.2.0 | 2 | +| /query-tests/Metrics/Dependencies/ExternalDependencies/File1.cs<\|>System.Data.Common<\|>4.2.2.0 | 1 | +| /query-tests/Metrics/Dependencies/ExternalDependencies/File2.cs<\|>System.Net.Http<\|>4.2.2.0 | 1 | diff --git a/csharp/ql/test/query-tests/Metrics/Dependencies/ExternalDependencies/ExternalDependenciesSourceLinks.expected b/csharp/ql/test/query-tests/Metrics/Dependencies/ExternalDependencies/ExternalDependenciesSourceLinks.expected index 656ec843114..e1fe8dd8d03 100644 --- a/csharp/ql/test/query-tests/Metrics/Dependencies/ExternalDependencies/ExternalDependenciesSourceLinks.expected +++ b/csharp/ql/test/query-tests/Metrics/Dependencies/ExternalDependencies/ExternalDependenciesSourceLinks.expected @@ -1,5 +1,5 @@ -| /query-tests/Metrics/Dependencies/ExternalDependencies/File1.cs<\|>System.Data.Common<\|>4.2.1.0 | File1.cs:0:0:0:0 | File1.cs | -| /query-tests/Metrics/Dependencies/ExternalDependencies/File1.cs<\|>System.Net.Http<\|>4.2.1.0 | File1.cs:0:0:0:0 | File1.cs | -| /query-tests/Metrics/Dependencies/ExternalDependencies/File1.cs<\|>System.Private.DataContractSerialization<\|>4.1.4.0 | File1.cs:0:0:0:0 | File1.cs | -| /query-tests/Metrics/Dependencies/ExternalDependencies/File1.cs<\|>System.Private.Xml<\|>4.0.1.0 | File1.cs:0:0:0:0 | File1.cs | -| /query-tests/Metrics/Dependencies/ExternalDependencies/File2.cs<\|>System.Net.Http<\|>4.2.1.0 | File2.cs:0:0:0:0 | File2.cs | +| /query-tests/Metrics/Dependencies/ExternalDependencies/File1.cs<\|>System.Data.Common<\|>4.2.2.0 | File1.cs:0:0:0:0 | File1.cs | +| /query-tests/Metrics/Dependencies/ExternalDependencies/File1.cs<\|>System.Net.Http<\|>4.2.2.0 | File1.cs:0:0:0:0 | File1.cs | +| /query-tests/Metrics/Dependencies/ExternalDependencies/File1.cs<\|>System.Private.DataContractSerialization<\|>4.1.5.0 | File1.cs:0:0:0:0 | File1.cs | +| /query-tests/Metrics/Dependencies/ExternalDependencies/File1.cs<\|>System.Private.Xml<\|>4.0.2.0 | File1.cs:0:0:0:0 | File1.cs | +| /query-tests/Metrics/Dependencies/ExternalDependencies/File2.cs<\|>System.Net.Http<\|>4.2.2.0 | File2.cs:0:0:0:0 | File2.cs | diff --git a/csharp/ql/test/query-tests/Stubs/MinimalStubsFromSource.expected b/csharp/ql/test/query-tests/Stubs/MinimalStubsFromSource.expected index 5c7911617f3..967642a861f 100644 --- a/csharp/ql/test/query-tests/Stubs/MinimalStubsFromSource.expected +++ b/csharp/ql/test/query-tests/Stubs/MinimalStubsFromSource.expected @@ -1 +1 @@ -| // This file contains auto-generated code.\n// original-extractor-options: /r:System.Text.RegularExpressions.dll /r:System.Collections.Specialized.dll /r:System.Net.dll /r:System.Web.dll /r:System.Net.HttpListener.dll /r:System.Collections.Specialized.dll /r:System.Private.Uri.dll /r:System.Runtime.Extensions.dll /r:System.Linq.Parallel.dll /r:System.Collections.Concurrent.dll /r:System.Linq.Expressions.dll /r:System.Collections.dll /r:System.Linq.Queryable.dll /r:System.Linq.dll /r:System.Collections.NonGeneric.dll /r:System.ObjectModel.dll /r:System.ComponentModel.TypeConverter.dll /r:System.IO.Compression.dll /r:System.IO.Pipes.dll /r:System.Net.Primitives.dll /r:System.Net.Security.dll /r:System.Security.Cryptography.Primitives.dll /r:System.Text.RegularExpressions.dll ${testdir}/../../resources/stubs/System.Web.cs /r:System.Runtime.Serialization.Primitives.dll\n\nnamespace System\n{\n// Generated from `System.Uri` in `System.Private.Uri, Version=4.0.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Uri : System.Runtime.Serialization.ISerializable\n{\n public override bool Equals(object comparand) => throw null;\n public override int GetHashCode() => throw null;\n public override string ToString() => throw null;\n void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null;\n}\n\nnamespace Collections\n{\n// Generated from `System.Collections.SortedList` in `System.Collections.NonGeneric, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class SortedList : System.ICloneable, System.Collections.IEnumerable, System.Collections.IDictionary, System.Collections.ICollection\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public virtual System.Collections.ICollection Keys { get => throw null; }\n public virtual System.Collections.ICollection Values { get => throw null; }\n public virtual System.Collections.IDictionaryEnumerator GetEnumerator() => throw null;\n public virtual bool Contains(object key) => throw null;\n public virtual bool IsFixedSize { get => throw null; }\n public virtual bool IsReadOnly { get => throw null; }\n public virtual bool IsSynchronized { get => throw null; }\n public virtual int Count { get => throw null; }\n public virtual object Clone() => throw null;\n public virtual object GetByIndex(int index) => throw null;\n public virtual object SyncRoot { get => throw null; }\n public virtual object this[object key] { get => throw null; set => throw null; }\n public virtual void Add(object key, object value) => throw null;\n public virtual void Clear() => throw null;\n public virtual void CopyTo(System.Array array, int arrayIndex) => throw null;\n public virtual void Remove(object key) => throw null;\n}\n\nnamespace Generic\n{\n// Generated from `System.Collections.Generic.Stack<>` in `System.Collections, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Stack : System.Collections.IEnumerable, System.Collections.ICollection, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IEnumerable\n{\n System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n public T Peek() => throw null;\n public int Count { get => throw null; }\n void System.Collections.ICollection.CopyTo(System.Array array, int arrayIndex) => throw null;\n}\n\n}\nnamespace Specialized\n{\n// Generated from `System.Collections.Specialized.NameObjectCollectionBase` in `System.Collections.Specialized, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract public class NameObjectCollectionBase : System.Runtime.Serialization.ISerializable, System.Runtime.Serialization.IDeserializationCallback, System.Collections.IEnumerable, System.Collections.ICollection\n{\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n public virtual System.Collections.IEnumerator GetEnumerator() => throw null;\n public virtual int Count { get => throw null; }\n public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null;\n public virtual void OnDeserialization(object sender) => throw null;\n void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null;\n}\n\n// Generated from `System.Collections.Specialized.NameValueCollection` in `System.Collections.Specialized, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class NameValueCollection : System.Collections.Specialized.NameObjectCollectionBase\n{\n public string this[string name] { get => throw null; set => throw null; }\n}\n\n}\n}\nnamespace IO\n{\n// Generated from `System.IO.StringReader` in `System.Runtime.Extensions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class StringReader : System.IO.TextReader\n{\n protected override void Dispose(bool disposing) => throw null;\n public StringReader(string s) => throw null;\n public override System.Threading.Tasks.Task ReadAsync(System.Char[] buffer, int index, int count) => throw null;\n public override System.Threading.Tasks.Task ReadBlockAsync(System.Char[] buffer, int index, int count) => throw null;\n public override System.Threading.Tasks.Task ReadLineAsync() => throw null;\n public override System.Threading.Tasks.Task ReadToEndAsync() => throw null;\n public override System.Threading.Tasks.ValueTask ReadAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.ValueTask ReadBlockAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override int Peek() => throw null;\n public override int Read() => throw null;\n public override int Read(System.Char[] buffer, int index, int count) => throw null;\n public override int Read(System.Span buffer) => throw null;\n public override int ReadBlock(System.Span buffer) => throw null;\n public override string ReadLine() => throw null;\n public override string ReadToEnd() => throw null;\n public override void Close() => throw null;\n}\n\n}\nnamespace Linq\n{\n// Generated from `System.Linq.Enumerable` in `System.Linq, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nstatic public class Enumerable\n{\n public static System.Collections.Generic.IEnumerable Select(this System.Collections.Generic.IEnumerable source, System.Func selector) => throw null;\n}\n\n// Generated from `System.Linq.IQueryable` in `System.Linq.Expressions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface IQueryable : System.Collections.IEnumerable\n{\n}\n\n// Generated from `System.Linq.ParallelEnumerable` in `System.Linq.Parallel, Version=4.0.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nstatic public class ParallelEnumerable\n{\n public static System.Linq.ParallelQuery AsParallel(this System.Collections.IEnumerable source) => throw null;\n}\n\n// Generated from `System.Linq.ParallelQuery` in `System.Linq.Parallel, Version=4.0.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ParallelQuery : System.Collections.IEnumerable\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n}\n\n// Generated from `System.Linq.Queryable` in `System.Linq.Queryable, Version=4.0.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nstatic public class Queryable\n{\n public static System.Linq.IQueryable AsQueryable(this System.Collections.IEnumerable source) => throw null;\n}\n\n}\nnamespace Runtime\n{\nnamespace Serialization\n{\n// Generated from `System.Runtime.Serialization.DataContractAttribute` in `System.Runtime.Serialization.Primitives, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DataContractAttribute : System.Attribute\n{\n public DataContractAttribute() => throw null;\n}\n\n// Generated from `System.Runtime.Serialization.DataMemberAttribute` in `System.Runtime.Serialization.Primitives, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DataMemberAttribute : System.Attribute\n{\n public DataMemberAttribute() => throw null;\n}\n\n}\n}\nnamespace Text\n{\nnamespace RegularExpressions\n{\n// Generated from `System.Text.RegularExpressions.Capture` in `System.Text.RegularExpressions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Capture\n{\n public override string ToString() => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.Group` in `System.Text.RegularExpressions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Group : System.Text.RegularExpressions.Capture\n{\n}\n\n// Generated from `System.Text.RegularExpressions.Match` in `System.Text.RegularExpressions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Match : System.Text.RegularExpressions.Group\n{\n}\n\n// Generated from `System.Text.RegularExpressions.RegexOptions` in `System.Text.RegularExpressions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic enum RegexOptions\n{\n IgnoreCase,\n}\n\n// Generated from `System.Text.RegularExpressions.Regex` in `System.Text.RegularExpressions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Regex : System.Runtime.Serialization.ISerializable\n{\n public Regex(string pattern) => throw null;\n public Regex(string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null;\n public System.Text.RegularExpressions.Match Match(string input) => throw null;\n public override string ToString() => throw null;\n public static System.Text.RegularExpressions.Match Match(string input, string pattern) => throw null;\n public static System.Text.RegularExpressions.Match Match(string input, string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null;\n public string Replace(string input, string replacement) => throw null;\n void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo si, System.Runtime.Serialization.StreamingContext context) => throw null;\n}\n\n}\n}\n}\n | +| // This file contains auto-generated code.\n// original-extractor-options: /r:System.Text.RegularExpressions.dll /r:System.Collections.Specialized.dll /r:System.Net.dll /r:System.Web.dll /r:System.Net.HttpListener.dll /r:System.Collections.Specialized.dll /r:System.Private.Uri.dll /r:System.Runtime.Extensions.dll /r:System.Linq.Parallel.dll /r:System.Collections.Concurrent.dll /r:System.Linq.Expressions.dll /r:System.Collections.dll /r:System.Linq.Queryable.dll /r:System.Linq.dll /r:System.Collections.NonGeneric.dll /r:System.ObjectModel.dll /r:System.ComponentModel.TypeConverter.dll /r:System.IO.Compression.dll /r:System.IO.Pipes.dll /r:System.Net.Primitives.dll /r:System.Net.Security.dll /r:System.Security.Cryptography.Primitives.dll /r:System.Text.RegularExpressions.dll ${testdir}/../../resources/stubs/System.Web.cs /r:System.Runtime.Serialization.Primitives.dll\n\nnamespace System\n{\n// Generated from `System.Uri` in `System.Private.Uri, Version=4.0.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Uri : System.Runtime.Serialization.ISerializable\n{\n public override bool Equals(object comparand) => throw null;\n public override int GetHashCode() => throw null;\n public override string ToString() => throw null;\n void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null;\n}\n\nnamespace Collections\n{\n// Generated from `System.Collections.SortedList` in `System.Collections.NonGeneric, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class SortedList : System.ICloneable, System.Collections.IEnumerable, System.Collections.IDictionary, System.Collections.ICollection\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public virtual System.Collections.ICollection Keys { get => throw null; }\n public virtual System.Collections.ICollection Values { get => throw null; }\n public virtual System.Collections.IDictionaryEnumerator GetEnumerator() => throw null;\n public virtual bool Contains(object key) => throw null;\n public virtual bool IsFixedSize { get => throw null; }\n public virtual bool IsReadOnly { get => throw null; }\n public virtual bool IsSynchronized { get => throw null; }\n public virtual int Count { get => throw null; }\n public virtual object Clone() => throw null;\n public virtual object GetByIndex(int index) => throw null;\n public virtual object SyncRoot { get => throw null; }\n public virtual object this[object key] { get => throw null; set => throw null; }\n public virtual void Add(object key, object value) => throw null;\n public virtual void Clear() => throw null;\n public virtual void CopyTo(System.Array array, int arrayIndex) => throw null;\n public virtual void Remove(object key) => throw null;\n}\n\nnamespace Generic\n{\n// Generated from `System.Collections.Generic.Stack<>` in `System.Collections, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Stack : System.Collections.IEnumerable, System.Collections.ICollection, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IEnumerable\n{\n System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n public T Peek() => throw null;\n public int Count { get => throw null; }\n void System.Collections.ICollection.CopyTo(System.Array array, int arrayIndex) => throw null;\n}\n\n}\nnamespace Specialized\n{\n// Generated from `System.Collections.Specialized.NameObjectCollectionBase` in `System.Collections.Specialized, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nabstract public class NameObjectCollectionBase : System.Runtime.Serialization.ISerializable, System.Runtime.Serialization.IDeserializationCallback, System.Collections.IEnumerable, System.Collections.ICollection\n{\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n public virtual System.Collections.IEnumerator GetEnumerator() => throw null;\n public virtual int Count { get => throw null; }\n public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null;\n public virtual void OnDeserialization(object sender) => throw null;\n void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null;\n}\n\n// Generated from `System.Collections.Specialized.NameValueCollection` in `System.Collections.Specialized, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class NameValueCollection : System.Collections.Specialized.NameObjectCollectionBase\n{\n public string this[string name] { get => throw null; set => throw null; }\n}\n\n}\n}\nnamespace IO\n{\n// Generated from `System.IO.StringReader` in `System.Runtime.Extensions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class StringReader : System.IO.TextReader\n{\n protected override void Dispose(bool disposing) => throw null;\n public StringReader(string s) => throw null;\n public override System.Threading.Tasks.Task ReadAsync(System.Char[] buffer, int index, int count) => throw null;\n public override System.Threading.Tasks.Task ReadBlockAsync(System.Char[] buffer, int index, int count) => throw null;\n public override System.Threading.Tasks.Task ReadLineAsync() => throw null;\n public override System.Threading.Tasks.Task ReadToEndAsync() => throw null;\n public override System.Threading.Tasks.ValueTask ReadAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override System.Threading.Tasks.ValueTask ReadBlockAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken) => throw null;\n public override int Peek() => throw null;\n public override int Read() => throw null;\n public override int Read(System.Char[] buffer, int index, int count) => throw null;\n public override int Read(System.Span buffer) => throw null;\n public override int ReadBlock(System.Span buffer) => throw null;\n public override string ReadLine() => throw null;\n public override string ReadToEnd() => throw null;\n public override void Close() => throw null;\n}\n\n}\nnamespace Linq\n{\n// Generated from `System.Linq.Enumerable` in `System.Linq, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nstatic public class Enumerable\n{\n public static System.Collections.Generic.IEnumerable Select(this System.Collections.Generic.IEnumerable source, System.Func selector) => throw null;\n}\n\n// Generated from `System.Linq.IQueryable` in `System.Linq.Expressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface IQueryable : System.Collections.IEnumerable\n{\n}\n\n// Generated from `System.Linq.ParallelEnumerable` in `System.Linq.Parallel, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nstatic public class ParallelEnumerable\n{\n public static System.Linq.ParallelQuery AsParallel(this System.Collections.IEnumerable source) => throw null;\n}\n\n// Generated from `System.Linq.ParallelQuery` in `System.Linq.Parallel, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ParallelQuery : System.Collections.IEnumerable\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n}\n\n// Generated from `System.Linq.Queryable` in `System.Linq.Queryable, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\nstatic public class Queryable\n{\n public static System.Linq.IQueryable AsQueryable(this System.Collections.IEnumerable source) => throw null;\n}\n\n}\nnamespace Runtime\n{\nnamespace Serialization\n{\n// Generated from `System.Runtime.Serialization.DataContractAttribute` in `System.Runtime.Serialization.Primitives, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DataContractAttribute : System.Attribute\n{\n public DataContractAttribute() => throw null;\n}\n\n// Generated from `System.Runtime.Serialization.DataMemberAttribute` in `System.Runtime.Serialization.Primitives, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DataMemberAttribute : System.Attribute\n{\n public DataMemberAttribute() => throw null;\n}\n\n}\n}\nnamespace Text\n{\nnamespace RegularExpressions\n{\n// Generated from `System.Text.RegularExpressions.Capture` in `System.Text.RegularExpressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Capture\n{\n public override string ToString() => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.Group` in `System.Text.RegularExpressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Group : System.Text.RegularExpressions.Capture\n{\n}\n\n// Generated from `System.Text.RegularExpressions.Match` in `System.Text.RegularExpressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Match : System.Text.RegularExpressions.Group\n{\n}\n\n// Generated from `System.Text.RegularExpressions.RegexOptions` in `System.Text.RegularExpressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic enum RegexOptions\n{\n IgnoreCase,\n}\n\n// Generated from `System.Text.RegularExpressions.Regex` in `System.Text.RegularExpressions, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Regex : System.Runtime.Serialization.ISerializable\n{\n public Regex(string pattern) => throw null;\n public Regex(string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null;\n public System.Text.RegularExpressions.Match Match(string input) => throw null;\n public override string ToString() => throw null;\n public static System.Text.RegularExpressions.Match Match(string input, string pattern) => throw null;\n public static System.Text.RegularExpressions.Match Match(string input, string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null;\n public string Replace(string input, string replacement) => throw null;\n void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo si, System.Runtime.Serialization.StreamingContext context) => throw null;\n}\n\n}\n}\n}\n | From 98ab38a630f51486a2fcc04337bbb36eb2b2cf7a Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 6 Oct 2020 15:32:21 +0100 Subject: [PATCH 263/411] JavaScript: Add yet another API-graph test with re-exports. --- javascript/ql/test/ApiGraphs/reexport/index.js | 5 +++-- javascript/ql/test/ApiGraphs/reexport/lib/utils2.js | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 javascript/ql/test/ApiGraphs/reexport/lib/utils2.js diff --git a/javascript/ql/test/ApiGraphs/reexport/index.js b/javascript/ql/test/ApiGraphs/reexport/index.js index 6d985f19570..2562008211b 100644 --- a/javascript/ql/test/ApiGraphs/reexport/index.js +++ b/javascript/ql/test/ApiGraphs/reexport/index.js @@ -3,5 +3,6 @@ const impl = require("./lib/impl.js"); module.exports = { impl, util: require("./lib/utils"), - other: require("./lib/stuff") -}; \ No newline at end of file + other: require("./lib/stuff"), + util2: require("./lib/utils2") +}; diff --git a/javascript/ql/test/ApiGraphs/reexport/lib/utils2.js b/javascript/ql/test/ApiGraphs/reexport/lib/utils2.js new file mode 100644 index 00000000000..65b729666be --- /dev/null +++ b/javascript/ql/test/ApiGraphs/reexport/lib/utils2.js @@ -0,0 +1,5 @@ +module.exports = { + id: function id(x) { /* use (parameter 0 (member id (member util2 (member exports (module reexport)))) */ + return x; + } +}; From b905a3d5e3daeb906553db6f141c20db23e52ce4 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Tue, 6 Oct 2020 16:36:29 +0200 Subject: [PATCH 264/411] Python: Attribute access API --- .../src/experimental/dataflow/TypeTracker.qll | 17 +- .../dataflow/internal/Attributes.qll | 208 ++++++++++++++++++ .../dataflow/internal/DataFlowPublic.qll | 1 + .../dataflow/typetracking/attribute_tests.py | 70 ++++++ 4 files changed, 289 insertions(+), 7 deletions(-) create mode 100644 python/ql/src/experimental/dataflow/internal/Attributes.qll diff --git a/python/ql/src/experimental/dataflow/TypeTracker.qll b/python/ql/src/experimental/dataflow/TypeTracker.qll index 4491279a971..fc14251211f 100644 --- a/python/ql/src/experimental/dataflow/TypeTracker.qll +++ b/python/ql/src/experimental/dataflow/TypeTracker.qll @@ -6,7 +6,7 @@ private import internal.DataFlowPrivate /** Any string that may appear as the name of an attribute or access path. */ class AttributeName extends string { - AttributeName() { this = any(Attribute a).getName() } + AttributeName() { this = any(AttrRef a).getAttributeName() } } /** Either an attribute name, or the empty string (representing no attribute). */ @@ -115,11 +115,10 @@ predicate returnStep(ReturnNode nodeFrom, Node nodeTo) { * assignment to `z` inside `bar`, even though this attribute write happens _after_ `bar` is called. */ predicate basicStoreStep(Node nodeFrom, Node nodeTo, string attr) { - exists(AttributeAssignment a, Node var | - a.getName() = attr and - simpleLocalFlowStep*(nodeTo, var) and - var.asVar() = a.getInput() and - nodeFrom.asCfgNode() = a.getValue() + exists(AttrWrite a | + a.getAttributeName() = attr and + nodeFrom = a.getValue() and + simpleLocalFlowStep*(nodeTo, a.getObject()) ) } @@ -127,7 +126,11 @@ predicate basicStoreStep(Node nodeFrom, Node nodeTo, string attr) { * Holds if `nodeTo` is the result of accessing the `attr` attribute of `nodeFrom`. */ predicate basicLoadStep(Node nodeFrom, Node nodeTo, string attr) { - exists(AttrNode s | nodeTo.asCfgNode() = s and s.getObject(attr) = nodeFrom.asCfgNode()) + exists(AttrRead a | + attr = a.getAttributeName() and + nodeFrom = a.getObject() and + nodeTo = a + ) } /** diff --git a/python/ql/src/experimental/dataflow/internal/Attributes.qll b/python/ql/src/experimental/dataflow/internal/Attributes.qll new file mode 100644 index 00000000000..ec8725f8c2a --- /dev/null +++ b/python/ql/src/experimental/dataflow/internal/Attributes.qll @@ -0,0 +1,208 @@ +/** This module provides an API for attribute reads and writes. */ + +import DataFlowPublic +private import DataFlowPrivate + +/** + * A data flow node that reads or writes an attribute of an object. + * + * This abstract base class only knows about the base object on which the attribute is being + * accessed, and the attribute itself, if it is statically inferrable. + */ +abstract class AttrRef extends Node { + /** + * Gets the data flow node corresponding to the object whose attribute is being read or written. + */ + abstract Node getObject(); + + /** + * Gets the expression control flow node that defines the attribute being accessed. This is + * usually an identifier or literal. + */ + abstract ExprNode getAttributeNameExpr(); + + /** Holds if this attribute reference may access an attribute named `attrName`. */ + predicate mayHaveAttributeName(string attrName) { none() } + + /** Gets the name of the attribute being read or written, if it can be determined statically. */ + abstract string getAttributeName(); +} + +/** + * A data flow node that writes an attribute of an object. This includes + * - Simple attribute writes: `object.attr = value` + * - Dynamic attribute writes: `setattr(object, attr, value)` + * - Fields written during class initialization: `class MyClass: attr = value` + */ +abstract class AttrWrite extends AttrRef { + /** Gets the data flow node corresponding to the value that is written to the attribute. */ + abstract Node getValue(); +} + +/** A simple attribute assignment: `object.attr = value`. */ +private class AttributeAssignmentAsAttrWrite extends AttrWrite, CfgNode { + DefinitionNode attr_node; + + AttributeAssignmentAsAttrWrite() { this = TCfgNode(attr_node) and attr_node instanceof AttrNode } + + override Node getValue() { result = TCfgNode(attr_node.(DefinitionNode).getValue()) } + + override Node getObject() { result = TCfgNode(attr_node.(AttrNode).getObject()) } + + override ExprNode getAttributeNameExpr() { + // Attribute names don't exist as `Node`s in the control flow graph, as they can only ever be + // identifiers, and are therefore represented directly as strings. + // Use `getAttributeName` to access the name of the attribute. + none() + } + + override string getAttributeName() { result = attr_node.(AttrNode).getName() } +} + +import semmle.python.types.Builtins + +/** Represents `CallNode`s that may refer to calls to built-in functions or classes. */ +private class BuiltInCallNode extends CallNode { + string name; + + BuiltInCallNode() { + // TODO disallow instances where `setattr` may refer to an in-scope variable of that name. + exists(NameNode id | this.getFunction() = id and id.getId() = name and id.isGlobal()) and + name = any(Builtin b).getName() + } + + /** Gets the name of the built-in function that is called at this `CallNode` */ + string getBuiltinName() { result = name } +} + +/** + * Represents a call to the built-ins that handle dynamic inspection and modification of + * attributes: `getattr`, `setattr`, and `hasattr`. + */ +private class BuiltinAttrCallNode extends BuiltInCallNode { + BuiltinAttrCallNode() { + name = "setattr" or + name = "getattr" or + name = "hasattr" + } + + /** Gets the control flow node for object on which the attribute is accessed. */ + ControlFlowNode getObject() { result in [this.getArg(0), this.getArgByName("object")] } + + /** + * Gets the control flow node for the value that is being written to the attribute. + * Only relevant for `setattr` calls. + */ + ControlFlowNode getValue() { + // only valid for `setattr` + name = "setattr" and + result in [this.getArg(2), this.getArgByName("value")] + } + + /** Gets the control flow node that defines the name of the attribute being accessed. */ + ControlFlowNode getName() { result in [this.getArg(1), this.getArgByName("name")] } +} + +/** Represents calls to the built-in `setattr`. */ +private class SetAttrCallNode extends BuiltinAttrCallNode { + SetAttrCallNode() { name = "setattr" } +} + +/** Represents calls to the built-in `getattr`. */ +private class GetAttrCallNode extends BuiltinAttrCallNode { + GetAttrCallNode() { name = "getattr" } +} + +/** An attribute assignment using `setattr`, e.g. `setattr(object, attr, value)` */ +private class SetAttrCallAsAttrWrite extends AttrWrite, CfgNode { + SetAttrCallNode setattr_call; + + SetAttrCallAsAttrWrite() { this = TCfgNode(setattr_call) } + + override Node getValue() { result = TCfgNode(setattr_call.getValue()) } + + override Node getObject() { result = TCfgNode(setattr_call.getObject()) } + + override ExprNode getAttributeNameExpr() { result = TCfgNode(setattr_call.getName()) } + + override string getAttributeName() { + // TODO track this back using local flow + exists(StrConst s, Node nodeFrom | + s = nodeFrom.asExpr() and + simpleLocalFlowStep*(nodeFrom, this.getAttributeNameExpr()) and + result = s.getText() + ) + } +} + +/** + * An attribute assignment via a class field, e.g. + * ```python + * class MyClass: + * attr = value + * ``` + * is treated as equivalent to `MyClass.attr = value`. + */ +private class ClassDefinitionAsAttrWrite extends AttrWrite, Node { + ClassExpr cls; + DefinitionNode attr_node; + + ClassDefinitionAsAttrWrite() { + attr_node instanceof NameNode and + this.asCfgNode() = attr_node and + attr_node.getScope() = cls.getInnerScope() + } + + override Node getValue() { result = TCfgNode(attr_node.getValue()) } + + override Node getObject() { result = TCfgNode(cls.getAFlowNode()) } + + override ExprNode getAttributeNameExpr() { none() } + + override string getAttributeName() { result = attr_node.(NameNode).getId() } +} + +/** + * A read of an attribute on an object. This includes + * - Simple attribute reads: `object.attr` + * - Dynamic attribute reads using `getattr`: `getattr(object, attr)` + * - Qualified imports: `from module import attr as name` + */ +abstract class AttrRead extends AttrRef, Node { } + +/** A simple attribute read, e.g. `object.attr` */ +private class AttributeReadAsAttrRead extends AttrRead, CfgNode { + AttrNode attr_node; + + AttributeReadAsAttrRead() { this = TCfgNode(attr_node) } + + override Node getObject() { result = TCfgNode(attr_node.getObject()) } + + override ExprNode getAttributeNameExpr() { + // Attribute names don't exist as `Node`s in the control flow graph, as they can only ever be + // identifiers, and are therefore represented directly as strings. + // Use `getAttributeName` to access the name of the attribute. + none() + } + + override string getAttributeName() { result = attr_node.getName() } +} + +/** An attribute read using `getattr`: `getattr(object, attr)` */ +private class GetAttrCallAsAttrRead extends AttrRead, CfgNode { + GetAttrCallNode getattr_call; + + GetAttrCallAsAttrRead() { this.asCfgNode() = getattr_call } + + override Node getObject() { result = TCfgNode(getattr_call.getObject()) } + + override ExprNode getAttributeNameExpr() { result = TCfgNode(getattr_call.getName()) } + + override string getAttributeName() { + exists(StrConst s, Node nodeFrom | + s = nodeFrom.asExpr() and + simpleLocalFlowStep*(nodeFrom, this.getAttributeNameExpr()) and + result = s.getText() + ) + } +} diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll b/python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll index fb68fe3b1f1..9cb9d115b22 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll @@ -5,6 +5,7 @@ private import python private import DataFlowPrivate import experimental.dataflow.TypeTracker +import Attributes private import semmle.python.essa.SsaCompute /** diff --git a/python/ql/test/experimental/dataflow/typetracking/attribute_tests.py b/python/ql/test/experimental/dataflow/typetracking/attribute_tests.py index 7d88489842f..5e8e87f8ae3 100644 --- a/python/ql/test/experimental/dataflow/typetracking/attribute_tests.py +++ b/python/ql/test/experimental/dataflow/typetracking/attribute_tests.py @@ -29,3 +29,73 @@ def test_incompatible_types(): expects_int(x) # $int=field $f+:str=field x.field = str("Hello") # $f+:int=field $str=field $f+:int $str expects_string(x) # $f+:int=field $str=field + + +# Attributes assigned statically to a class + +class MyClass: # $tracked=field + field = tracked # $tracked + +lookup = MyClass.field # $tracked $tracked=field +instance = MyClass() # $tracked=field +lookup2 = instance.field # $f-:tracked + +## Dynamic attribute access + +# Via `getattr`/`setattr` + +def setattr_immediate_write(): + x = SomeClass() # $tracked=foo + setattr(x,"foo", tracked) # $tracked $tracked=foo + y = x.foo # $tracked $tracked=foo + do_stuff(y) # $tracked + +def getattr_immediate_read(): + x = SomeClass() # $tracked=foo + x.foo = tracked # $tracked $tracked=foo + y = getattr(x,"foo") # $tracked $tracked=foo + do_stuff(y) # $tracked + +def setattr_indirect_write(): + attr = "foo" + x = SomeClass() # $tracked=foo + setattr(x, attr, tracked) # $tracked $tracked=foo + y = x.foo # $tracked $tracked=foo + do_stuff(y) # $tracked + +def getattr_indirect_read(): + attr = "foo" + x = SomeClass() # $tracked=foo + x.foo = tracked # $tracked $tracked=foo + y = getattr(x, attr) #$tracked $tracked=foo + do_stuff(y) # $tracked + +# Via `__dict__` -- not currently implemented. + +def dunder_dict_immediate_write(): + x = SomeClass() # $f-:tracked=foo + x.__dict__["foo"] = tracked # $tracked $f-:tracked=foo + y = x.foo # $f-:tracked $f-:tracked=foo + do_stuff(y) # $f-:tracked + +def dunder_dict_immediate_read(): + x = SomeClass() # $tracked=foo + x.foo = tracked # $tracked $tracked=foo + y = x.__dict__["foo"] # $f-:tracked $tracked=foo + do_stuff(y) # $f-:tracked + +def dunder_dict_indirect_write(): + attr = "foo" + x = SomeClass() # $f-:tracked=foo + x.__dict__[attr] = tracked # $tracked $f-:tracked=foo + y = x.foo # $f-:tracked $f-:tracked=foo + do_stuff(y) # $f-:tracked + +def dunder_dict_indirect_read(): + attr = "foo" + x = SomeClass() # $tracked=foo + x.foo = tracked # $tracked $tracked=foo + y = x.__dict__[attr] # $f-:tracked $tracked=foo + do_stuff(y) # $f-:tracked + + From 050ed97d9c0cab94ae4062a1466cf2daecbafcdb Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 23 Sep 2020 13:49:43 +0200 Subject: [PATCH 265/411] add node-serialize as a js/code-injection sink --- .../security/dataflow/CodeInjectionCustomizations.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll index 265650703e5..24807aa0299 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll @@ -86,6 +86,8 @@ module CodeInjection { | this = c.getArgument(index) ) + or + this = DataFlow::moduleMember("node-serialize", "unserialize").getACall().getArgument(0) } } From 1ed026fcce16f3e8fe4059971b0a9bf987db1a73 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 23 Sep 2020 13:55:21 +0200 Subject: [PATCH 266/411] add a RemoteFlowSource for serverless handlers --- javascript/ql/src/javascript.qll | 1 + .../javascript/frameworks/ServerLess.qll | 91 +++++++++++++++++++ .../frameworks/ServerLess/test.expected | 5 + .../frameworks/ServerLess/test.ql | 3 + .../ServerLess/tst1/backend/src/mylibrary.js | 3 + .../frameworks/ServerLess/tst1/template.yml | 19 ++++ .../ServerLess/tst2/nodejs/index.js | 3 + .../frameworks/ServerLess/tst2/template.yml | 18 ++++ .../ServerLess/tst3/function/index.js | 3 + .../frameworks/ServerLess/tst3/template.yml | 10 ++ .../frameworks/ServerLess/tst4/app.js | 3 + .../frameworks/ServerLess/tst4/template.yml | 12 +++ .../frameworks/ServerLess/tst5/app.js | 3 + .../frameworks/ServerLess/tst5/template.yml | 11 +++ 14 files changed, 185 insertions(+) create mode 100644 javascript/ql/src/semmle/javascript/frameworks/ServerLess.qll create mode 100644 javascript/ql/test/library-tests/frameworks/ServerLess/test.expected create mode 100644 javascript/ql/test/library-tests/frameworks/ServerLess/test.ql create mode 100644 javascript/ql/test/library-tests/frameworks/ServerLess/tst1/backend/src/mylibrary.js create mode 100644 javascript/ql/test/library-tests/frameworks/ServerLess/tst1/template.yml create mode 100644 javascript/ql/test/library-tests/frameworks/ServerLess/tst2/nodejs/index.js create mode 100644 javascript/ql/test/library-tests/frameworks/ServerLess/tst2/template.yml create mode 100644 javascript/ql/test/library-tests/frameworks/ServerLess/tst3/function/index.js create mode 100644 javascript/ql/test/library-tests/frameworks/ServerLess/tst3/template.yml create mode 100644 javascript/ql/test/library-tests/frameworks/ServerLess/tst4/app.js create mode 100644 javascript/ql/test/library-tests/frameworks/ServerLess/tst4/template.yml create mode 100644 javascript/ql/test/library-tests/frameworks/ServerLess/tst5/app.js create mode 100644 javascript/ql/test/library-tests/frameworks/ServerLess/tst5/template.yml diff --git a/javascript/ql/src/javascript.qll b/javascript/ql/src/javascript.qll index 1fbf61615eb..ac1fe785029 100644 --- a/javascript/ql/src/javascript.qll +++ b/javascript/ql/src/javascript.qll @@ -94,6 +94,7 @@ import semmle.javascript.frameworks.PropertyProjection import semmle.javascript.frameworks.React import semmle.javascript.frameworks.ReactNative import semmle.javascript.frameworks.Request +import semmle.javascript.frameworks.ServerLess import semmle.javascript.frameworks.ShellJS import semmle.javascript.frameworks.SystemCommandExecutors import semmle.javascript.frameworks.SQL diff --git a/javascript/ql/src/semmle/javascript/frameworks/ServerLess.qll b/javascript/ql/src/semmle/javascript/frameworks/ServerLess.qll new file mode 100644 index 00000000000..a5a7006cb0f --- /dev/null +++ b/javascript/ql/src/semmle/javascript/frameworks/ServerLess.qll @@ -0,0 +1,91 @@ +/** + * Provides classes and predicates for working with serverless handlers. + * E.g. AWS: https://docs.aws.amazon.com/lambda/latest/dg/nodejs-handler.html + */ + +import javascript +private import semmle.javascript.PackageExports as Exports + +/** + * Provides classes and predicates for working with serverless handlers. + */ +private module ServerLess { + /** + * Holds if the `.yml` file `ymlFile` contains a serverless configuration with `handler` and `codeURI` properties. + * `codeURI` defaults to the empty string if no explicit value is set in the configuration. + */ + private predicate hasServerlessHandler(File ymlFile, string handler, string codeURI) { + exists(YAMLMapping resource | ymlFile = resource.getFile() | + // There exists at least "AWS::Serverless::Function" and "Aliyun::Serverless::Function" + resource.lookup("Type").(YAMLScalar).getValue().regexpMatch(".*::Serverless::Function") and + exists(YAMLMapping properties | properties = resource.lookup("Properties") | + handler = properties.lookup("Handler").(YAMLScalar).getValue() and + if exists(properties.lookup("CodeUri")) + then codeURI = properties.lookup("CodeUri").(YAMLScalar).getValue() + else codeURI = "" + ) + ) + } + + /** + * Gets a string where an ending "/." is simplified to "/" (if it exists). + */ + bindingset[base] + private string removeTrailingDot(string base) { + if base.regexpMatch(".*/\\.") + then result = base.substring(0, base.length() - 1) + else result = base + } + + /** + * Gets a string where a leading "./" is simplified to "" (if it exists). + */ + bindingset[base] + private string removeLeadingDotSlash(string base) { + if base.regexpMatch("\\./.*") then result = base.substring(2, base.length()) else result = base + } + + /** + * Gets a path to a file from a `codeURI` property and a file name from a serverless configuration. + */ + bindingset[codeURI, file] + private string getPathFromHandlerProperties(string codeURI, string file) { + exists(string folder | folder = removeLeadingDotSlash(removeTrailingDot(codeURI)) | + if folder.regexpMatch(".*\\..+") then result = folder else result = folder + file + ".js" + ) + } + + /** + * Holds if `file` has a serverless handler function with name `func`. + */ + private predicate hasServerlessHandler(File file, string func) { + exists(File ymlFile, string handler, string codeURI, string fileName | + hasServerlessHandler(ymlFile, handler, codeURI) and + func = handler.regexpCapture(".*\\.(.*)", 1) and + fileName = handler.regexpCapture("([^.]+).*", 1) + | + file.getAbsolutePath() = + ymlFile.getParentContainer().getAbsolutePath() + "/" + + getPathFromHandlerProperties(codeURI, fileName) + ) + } + + /** + * Gets a function that is a serverless request handler. + */ + private DataFlow::FunctionNode getAServerlessHandler() { + exists(File file, string handler, Module mod | hasServerlessHandler(file, handler) | + mod.getFile() = file and + result = mod.getAnExportedValue(handler).getAFunctionValue() + ) + } + + /** + * A serverless request handler event, seen as a RemoteFlowSource. + */ + private class ServerlessHandlerEventAsRemoteFlow extends RemoteFlowSource { + ServerlessHandlerEventAsRemoteFlow() { this = getAServerlessHandler().getParameter(0) } + + override string getSourceType() { result = "Serverless event" } + } +} diff --git a/javascript/ql/test/library-tests/frameworks/ServerLess/test.expected b/javascript/ql/test/library-tests/frameworks/ServerLess/test.expected new file mode 100644 index 00000000000..96ef06a352b --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/ServerLess/test.expected @@ -0,0 +1,5 @@ +| tst1/backend/src/mylibrary.js:1:36:1:40 | event | +| tst2/nodejs/index.js:1:36:1:40 | event | +| tst3/function/index.js:1:36:1:40 | event | +| tst4/app.js:1:36:1:40 | event | +| tst5/app.js:1:36:1:40 | event | diff --git a/javascript/ql/test/library-tests/frameworks/ServerLess/test.ql b/javascript/ql/test/library-tests/frameworks/ServerLess/test.ql new file mode 100644 index 00000000000..06f5e5fffe4 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/ServerLess/test.ql @@ -0,0 +1,3 @@ +import javascript + +query RemoteFlowSource remoteFlow() { any() } diff --git a/javascript/ql/test/library-tests/frameworks/ServerLess/tst1/backend/src/mylibrary.js b/javascript/ql/test/library-tests/frameworks/ServerLess/tst1/backend/src/mylibrary.js new file mode 100644 index 00000000000..76b27566d69 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/ServerLess/tst1/backend/src/mylibrary.js @@ -0,0 +1,3 @@ +module.exports.handler = function (event) { + console.log(event); +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/ServerLess/tst1/template.yml b/javascript/ql/test/library-tests/frameworks/ServerLess/tst1/template.yml new file mode 100644 index 00000000000..8aeef52c3ff --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/ServerLess/tst1/template.yml @@ -0,0 +1,19 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: 'AWS::Serverless-2016-10-31' +Description: 'Serverless thing' + +Globals: + Api: + Cors: + AllowMethods: "'*'" + AllowHeaders: "'*'" + AllowOrigin: "'*'" + +Resources: + OrderManagerJsFunction: + Type: 'AWS::Serverless::Function' + Properties: + FunctionName: MY-SERVERLESS-THING + Handler: mylibrary.handler + Runtime: nodejs12.x + CodeUri: backend/src/ \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/ServerLess/tst2/nodejs/index.js b/javascript/ql/test/library-tests/frameworks/ServerLess/tst2/nodejs/index.js new file mode 100644 index 00000000000..76b27566d69 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/ServerLess/tst2/nodejs/index.js @@ -0,0 +1,3 @@ +module.exports.handler = function (event) { + console.log(event); +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/ServerLess/tst2/template.yml b/javascript/ql/test/library-tests/frameworks/ServerLess/tst2/template.yml new file mode 100644 index 00000000000..ac6a26278e6 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/ServerLess/tst2/template.yml @@ -0,0 +1,18 @@ +Transform: 'Aliyun::Serverless-2018-04-03' +Resources: + fc-mongo: + Type: 'Aliyun::Serverless::Service' + Properties: + Description: MyServiceThing + nodejs: + Type: 'Aliyun::Serverless::Function' + Properties: + Handler: index.handler + Runtime: nodejs10 + CodeUri: nodejs/ + python: + Type: 'Aliyun::Serverless::Function' + Properties: + Handler: 'index.handler' + Runtime: python3 + CodeUri: python/ \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/ServerLess/tst3/function/index.js b/javascript/ql/test/library-tests/frameworks/ServerLess/tst3/function/index.js new file mode 100644 index 00000000000..76b27566d69 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/ServerLess/tst3/function/index.js @@ -0,0 +1,3 @@ +module.exports.handler = function (event) { + console.log(event); +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/ServerLess/tst3/template.yml b/javascript/ql/test/library-tests/frameworks/ServerLess/tst3/template.yml new file mode 100644 index 00000000000..23f3575a15b --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/ServerLess/tst3/template.yml @@ -0,0 +1,10 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: 'AWS::Serverless-2016-10-31' +Description: An AWS Lambda application. +Resources: + function: + Type: AWS::Serverless::Function + Properties: + Handler: index.handler + Runtime: nodejs12.x + CodeUri: function/. \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/ServerLess/tst4/app.js b/javascript/ql/test/library-tests/frameworks/ServerLess/tst4/app.js new file mode 100644 index 00000000000..76b27566d69 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/ServerLess/tst4/app.js @@ -0,0 +1,3 @@ +module.exports.handler = function (event) { + console.log(event); +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/ServerLess/tst4/template.yml b/javascript/ql/test/library-tests/frameworks/ServerLess/tst4/template.yml new file mode 100644 index 00000000000..9f5c2ba992a --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/ServerLess/tst4/template.yml @@ -0,0 +1,12 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: 'AWS::Serverless-2016-10-31' +Description: A AWS Lambda function. + +Resources: + helloworld: + Type: 'AWS::Serverless::Function' + Properties: + Handler: app.handler + Runtime: nodejs6.10 + CodeUri: ./ + Description: A AWS Lambda function. \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/ServerLess/tst5/app.js b/javascript/ql/test/library-tests/frameworks/ServerLess/tst5/app.js new file mode 100644 index 00000000000..76b27566d69 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/ServerLess/tst5/app.js @@ -0,0 +1,3 @@ +module.exports.handler = function (event) { + console.log(event); +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/ServerLess/tst5/template.yml b/javascript/ql/test/library-tests/frameworks/ServerLess/tst5/template.yml new file mode 100644 index 00000000000..9fc4d4d2bb3 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/ServerLess/tst5/template.yml @@ -0,0 +1,11 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: 'AWS::Serverless-2016-10-31' +Description: A AWS Lambda function. + +Resources: + helloworld: + Type: 'AWS::Serverless::Function' + Properties: + Handler: app.handler + Runtime: nodejs6.10 + Description: A AWS Lambda function. \ No newline at end of file From 7233ffa50f249db18aae7b8fc8fc2ebd251a094e Mon Sep 17 00:00:00 2001 From: Gulshan Singh Date: Tue, 6 Oct 2020 23:57:05 -0700 Subject: [PATCH 267/411] Address review comments --- .../rangeanalysis/BinaryOrAssignOperation.qll | 31 ----- .../ConstantBitwiseAndExprRange.qll | 130 ++++++++---------- 2 files changed, 55 insertions(+), 106 deletions(-) delete mode 100644 cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/BinaryOrAssignOperation.qll diff --git a/cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/BinaryOrAssignOperation.qll b/cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/BinaryOrAssignOperation.qll deleted file mode 100644 index 1670f4ebcd0..00000000000 --- a/cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/BinaryOrAssignOperation.qll +++ /dev/null @@ -1,31 +0,0 @@ -private import cpp - -Expr getLOp(Operation o) { - result = o.(BinaryOperation).getLeftOperand() or - result = o.(Assignment).getLValue() -} - -Expr getROp(Operation o) { - result = o.(BinaryOperation).getRightOperand() or - result = o.(Assignment).getRValue() -} - -private newtype TBinaryOrAssignOperation = - BinaryOp(BinaryOperation op) or - AssignOp(AssignOperation op) - -class BinaryOrAssignOperation extends TBinaryOrAssignOperation { - BinaryOperation asBinaryOp() { this = BinaryOp(result) } - - AssignOperation asAssignOp() { this = AssignOp(result) } - - Expr getLeftOperand() { result = getLOp(asBinaryOp()) or result = getLOp(asAssignOp()) } - - Expr getRightOperand() { result = getROp(asBinaryOp()) or result = getROp(asAssignOp()) } - - Expr getAnOperand() { result = getLeftOperand() or result = getRightOperand() } - - Operation getOperation() { result = asBinaryOp() or result = asAssignOp() } - - string toString() { result = asBinaryOp().toString() or result = asAssignOp().toString() } -} diff --git a/cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/extensions/ConstantBitwiseAndExprRange.qll b/cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/extensions/ConstantBitwiseAndExprRange.qll index 27f9733b557..e4c76e16120 100644 --- a/cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/extensions/ConstantBitwiseAndExprRange.qll +++ b/cpp/ql/src/experimental/semmle/code/cpp/rangeanalysis/extensions/ConstantBitwiseAndExprRange.qll @@ -1,50 +1,6 @@ private import cpp private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils -private import experimental.semmle.code.cpp.rangeanalysis.BinaryOrAssignOperation - -/** - * The current implementation for `BitwiseAndExpr` only handles cases where both operands are - * either unsigned or non-negative constants. This class not only covers these cases, but also - * adds support for `&` expressions between a signed integer with a non-negative range and a - * non-negative constant. It also adds support for `&=` for the same set of cases as `&`. - */ -private class ConstantBitwiseAndExprRange extends SimpleRangeAnalysisExpr { - BinaryOrAssignConstantBitwiseAndExpr e; - - ConstantBitwiseAndExprRange() { this = e.getOperation() } - - BinaryOrAssignConstantBitwiseAndExpr getExpr() { result = e } - - Expr getLeftOperand() { result = e.getLeftOperand() } - - Expr getRightOperand() { result = e.getRightOperand() } - - override float getLowerBounds() { result = e.getLowerBounds() } - - override float getUpperBounds() { result = e.getUpperBounds() } - - override predicate dependsOnChild(Expr child) { child = e.getAnOperand() } -} - -private class ConstantBitwiseAndExprOp extends Expr { - BinaryOrAssignConstantBitwiseAndExpr b; - float lowerBound; - float upperBound; - - ConstantBitwiseAndExprOp() { - this = b.getAnOperand() and - lowerBound = getFullyConvertedLowerBounds(this) and - upperBound = getFullyConvertedUpperBounds(this) and - lowerBound <= upperBound - } - - float getLowerBound() { result = lowerBound } - - float getUpperBound() { result = upperBound } - - predicate hasNegativeRange() { getLowerBound() < 0 or getUpperBound() < 0 } -} /** * Holds if `e` is a constant or if it is a variable with a constant value @@ -58,32 +14,49 @@ float evaluateConstantExpr(Expr e) { ) } -private class BinaryOrAssignConstantBitwiseAndExpr extends BinaryOrAssignOperation { - BinaryOrAssignConstantBitwiseAndExpr() { - ( - getOperation() instanceof BitwiseAndExpr +/** + * The current implementation for `BitwiseAndExpr` only handles cases where both operands are + * either unsigned or non-negative constants. This class not only covers these cases, but also + * adds support for `&` expressions between a signed integer with a non-negative range and a + * non-negative constant. It also adds support for `&=` for the same set of cases as `&`. + */ +private class ConstantBitwiseAndExprRange extends SimpleRangeAnalysisExpr { + ConstantBitwiseAndExprRange() { + exists(Expr l, Expr r | + l = this.(BitwiseAndExpr).getLeftOperand() and + r = this.(BitwiseAndExpr).getRightOperand() or - getOperation() instanceof AssignAndExpr - ) and - // Make sure all operands and the result type are integral - getOperation().getUnspecifiedType() instanceof IntegralType and - getLeftOperand().getUnspecifiedType() instanceof IntegralType and - getRightOperand().getUnspecifiedType() instanceof IntegralType and - // No operands can be negative constants - not (evaluateConstantExpr(getLeftOperand()) < 0 or evaluateConstantExpr(getRightOperand()) < 0) and - // At least one operand must be a non-negative constant - (evaluateConstantExpr(getLeftOperand()) >= 0 or evaluateConstantExpr(getRightOperand()) >= 0) + l = this.(AssignAndExpr).getLValue() and + r = this.(AssignAndExpr).getRValue() + | + // No operands can be negative constants + not (evaluateConstantExpr(getLOp(this)) < 0 or evaluateConstantExpr(getROp(this)) < 0) and + // At least one operand must be a non-negative constant + (evaluateConstantExpr(getLOp(this)) >= 0 or evaluateConstantExpr(getROp(this)) >= 0) + ) } - float getLowerBounds() { - // If both operands have non-negative ranges, the lower bound is zero. If an operand can have - // negative values, the lower bound is unconstrained. - exists(ConstantBitwiseAndExprOp l, ConstantBitwiseAndExprOp r | - l = getLeftOperand() and - r = getRightOperand() and + Expr getLeftOperand() { + result = this.(BitwiseAndExpr).getLeftOperand() or + result = this.(AssignAndExpr).getLValue() + } + + Expr getRightOperand() { + result = this.(BitwiseAndExpr).getRightOperand() or + result = this.(AssignAndExpr).getRValue() + } + + override float getLowerBounds() { + // If an operand can have negative values, the lower bound is unconstrained. + // Otherwise, the lower bound is zero. + exists(float lLower, float lUpper, float rLower, float rUpper | + lLower = getFullyConvertedLowerBounds(getLeftOperand()) and + lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and + rLower = getFullyConvertedLowerBounds(getRightOperand()) and + rUpper = getFullyConvertedUpperBounds(getRightOperand()) and ( - (l.hasNegativeRange() or r.hasNegativeRange()) and - result = exprMinVal(getOperation()) + (lLower < 0 or rLower < 0) and + result = exprMinVal(this) or // This technically results in two lowerBounds when an operand range is negative, but // that's fine since `exprMinVal(x) <= 0`. We can't use an if statement here without @@ -93,20 +66,27 @@ private class BinaryOrAssignConstantBitwiseAndExpr extends BinaryOrAssignOperati ) } - float getUpperBounds() { + override float getUpperBounds() { // If an operand can have negative values, the upper bound is unconstrained. - // Otherwise, the upper bound is the maximum of the upper bounds of the operands - exists(ConstantBitwiseAndExprOp l, ConstantBitwiseAndExprOp r | - l = getLeftOperand() and - r = getRightOperand() and + // Otherwise, the upper bound is the minimum of the upper bounds of the operands + exists(float lLower, float lUpper, float rLower, float rUpper | + lLower = getFullyConvertedLowerBounds(getLeftOperand()) and + lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and + rLower = getFullyConvertedLowerBounds(getRightOperand()) and + rUpper = getFullyConvertedUpperBounds(getRightOperand()) and ( - (l.hasNegativeRange() or r.hasNegativeRange()) and - result = exprMaxVal(getOperation()) + (lLower < 0 or rLower < 0) and + result = exprMaxVal(this) or // This technically results in two upperBounds when an operand range is negative, but - // that's fine since `exprMaxVal(b) >= result` - result = r.getUpperBound().minimum(l.getUpperBound()) + // that's fine since `exprMaxVal(b) >= result`. We can't use an if statement here without + // non-monotonic recursion issues + result = rUpper.minimum(lUpper) ) ) } + + override predicate dependsOnChild(Expr child) { + child = getLeftOperand() or child = getRightOperand() + } } From 94dc11c45a6cf01240628ed74d0c491431059388 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 7 Oct 2020 10:56:01 +0200 Subject: [PATCH 268/411] Revert getNonIntegerValue unification --- .../internal/rangeanalysis/SignAnalysisCommon.qll | 12 ------------ .../internal/rangeanalysis/SignAnalysisSpecific.qll | 11 +++++++++-- .../internal/rangeanalysis/SignAnalysisCommon.qll | 12 ------------ .../internal/rangeanalysis/SignAnalysisSpecific.qll | 9 +++++++-- 4 files changed, 16 insertions(+), 28 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index 19412a0ba39..d00a38bac73 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -41,18 +41,6 @@ private Sign certainExprSign(Expr e) { ) } -/** - * Gets the value of the expression if it can't be converted to integer, but - * can be converted to float. - */ -private float getNonIntegerValue(ExprWithPossibleValue e) { - exists(string s | - s = e.getValue() and - result = s.toFloat() and - not exists(s.toInt()) - ) -} - /** Holds if the sign of `e` is too complicated to determine. */ private predicate unknownSign(Expr e) { not exists(certainExprSign(e)) and diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index 40e07eacbb9..c6acf0efc56 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -35,8 +35,6 @@ module Private { class VariableUpdate = CS::AssignableDefinition; - class ExprWithPossibleValue = CS::Expr; - class Field = CS::Field; class RealLiteral = CS::RealLiteral; @@ -130,6 +128,15 @@ private module Impl { /** Gets the character value of expression `e`. */ string getCharValue(Expr e) { result = e.getValue() and e.getType() instanceof CharType } + /** Gets the constant `float` value of non-`ConstantIntegerExpr` expressions. */ + float getNonIntegerValue(Expr e) { + exists(string s | + s = e.getValue() and + result = s.toFloat() and + not exists(s.toInt()) + ) + } + /** * Holds if `e` is an access to the size of a container (`string`, `Array`, * `IEnumerable`, or `ICollection`). diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index 19412a0ba39..d00a38bac73 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -41,18 +41,6 @@ private Sign certainExprSign(Expr e) { ) } -/** - * Gets the value of the expression if it can't be converted to integer, but - * can be converted to float. - */ -private float getNonIntegerValue(ExprWithPossibleValue e) { - exists(string s | - s = e.getValue() and - result = s.toFloat() and - not exists(s.toInt()) - ) -} - /** Holds if the sign of `e` is too complicated to determine. */ private predicate unknownSign(Expr e) { not exists(certainExprSign(e)) and diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index 84fbe10a91d..4c3c42b76fe 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -39,8 +39,6 @@ module Private { class VariableUpdate = J::VariableUpdate; - class ExprWithPossibleValue = J::Literal; - class Field = J::Field; class DivExpr = J::DivExpr; @@ -187,6 +185,13 @@ private module Impl { /** Gets the character value of expression `e`. */ string getCharValue(Expr e) { result = e.(CharacterLiteral).getValue() } + /** Gets the constant `float` value of non-`ConstantIntegerExpr` expressions. */ + float getNonIntegerValue(Expr e) { + result = e.(LongLiteral).getValue().toFloat() or + result = e.(FloatingPointLiteral).getValue().toFloat() or + result = e.(DoubleLiteral).getValue().toFloat() + } + /** * Holds if `e` is an access to the size of a container (`string`, `Map`, or * `Collection`). From 56882102494382ed43d7468110cfc4ed578cb432 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 28 Sep 2020 10:00:49 +0200 Subject: [PATCH 269/411] Java: add test for modulus analysis --- .../modulus-analysis/ModulusAnalysis.expected | 106 ++++++++++++++++++ .../modulus-analysis/ModulusAnalysis.java | 55 +++++++++ .../modulus-analysis/ModulusAnalysis.ql | 7 ++ 3 files changed, 168 insertions(+) create mode 100644 java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.expected create mode 100644 java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.java create mode 100644 java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.ql diff --git a/java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.expected b/java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.expected new file mode 100644 index 00000000000..ee4b5e1cf52 --- /dev/null +++ b/java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.expected @@ -0,0 +1,106 @@ +| ModulusAnalysis.java:3:5:3:22 | ...=... | 0 | 42 | 0 | +| ModulusAnalysis.java:3:5:3:22 | c1 | 0 | 42 | 0 | +| ModulusAnalysis.java:3:20:3:21 | 42 | 0 | 42 | 0 | +| ModulusAnalysis.java:4:5:4:22 | ...=... | 0 | 43 | 0 | +| ModulusAnalysis.java:4:5:4:22 | c2 | 0 | 43 | 0 | +| ModulusAnalysis.java:4:20:4:21 | 43 | 0 | 43 | 0 | +| ModulusAnalysis.java:7:18:7:18 | i | SSA init(i) | 0 | 0 | +| ModulusAnalysis.java:7:18:7:22 | ... + ... | SSA init(i) | 3 | 0 | +| ModulusAnalysis.java:7:22:7:22 | 3 | 0 | 3 | 0 | +| ModulusAnalysis.java:9:19:9:20 | eq | SSA def(eq) | 0 | 0 | +| ModulusAnalysis.java:9:19:9:20 | eq | SSA init(i) | 3 | 0 | +| ModulusAnalysis.java:9:19:9:25 | ... * ... | 0 | 0 | 42 | +| ModulusAnalysis.java:9:19:9:29 | ... + ... | 0 | 3 | 42 | +| ModulusAnalysis.java:9:24:9:25 | c1 | 0 | 42 | 0 | +| ModulusAnalysis.java:9:24:9:25 | c1 | SSA init(this.c1) | 0 | 0 | +| ModulusAnalysis.java:9:29:9:29 | 3 | 0 | 3 | 0 | +| ModulusAnalysis.java:11:21:11:21 | 7 | 0 | 7 | 0 | +| ModulusAnalysis.java:12:13:12:15 | mul | 0 | 3 | 42 | +| ModulusAnalysis.java:12:13:12:15 | mul | SSA def(mul) | 0 | 0 | +| ModulusAnalysis.java:12:19:12:20 | c2 | 0 | 43 | 0 | +| ModulusAnalysis.java:12:19:12:20 | c2 | SSA impl upd[untracked](this.c2) | 0 | 0 | +| ModulusAnalysis.java:12:25:12:29 | seven | 0 | 7 | 0 | +| ModulusAnalysis.java:12:25:12:29 | seven | SSA def(seven) | 0 | 0 | +| ModulusAnalysis.java:13:32:13:34 | mul | 0 | 3 | 42 | +| ModulusAnalysis.java:13:32:13:34 | mul | SSA def(mul) | 0 | 0 | +| ModulusAnalysis.java:16:17:18:23 | ...?...:... | 0 | 3 | 4 | +| ModulusAnalysis.java:17:15:17:15 | i | SSA init(i) | 0 | 0 | +| ModulusAnalysis.java:17:15:17:19 | ... * ... | 0 | 0 | 4 | +| ModulusAnalysis.java:17:15:17:23 | ... + ... | 0 | 3 | 4 | +| ModulusAnalysis.java:17:19:17:19 | 4 | 0 | 4 | 0 | +| ModulusAnalysis.java:17:23:17:23 | 3 | 0 | 3 | 0 | +| ModulusAnalysis.java:18:15:18:15 | i | SSA init(i) | 0 | 0 | +| ModulusAnalysis.java:18:15:18:19 | ... * ... | 0 | 0 | 8 | +| ModulusAnalysis.java:18:15:18:23 | ... + ... | 0 | 7 | 8 | +| ModulusAnalysis.java:18:19:18:19 | 8 | 0 | 8 | 0 | +| ModulusAnalysis.java:18:23:18:23 | 7 | 0 | 7 | 0 | +| ModulusAnalysis.java:19:28:19:28 | j | 0 | 3 | 4 | +| ModulusAnalysis.java:19:28:19:28 | j | SSA def(j) | 0 | 0 | +| ModulusAnalysis.java:21:13:21:13 | x | SSA init(x) | 0 | 0 | +| ModulusAnalysis.java:21:17:21:18 | c1 | 0 | 42 | 0 | +| ModulusAnalysis.java:21:17:21:18 | c1 | SSA init(this.c1) | 0 | 0 | +| ModulusAnalysis.java:21:23:21:23 | 3 | 0 | 3 | 0 | +| ModulusAnalysis.java:21:28:21:28 | y | SSA init(y) | 0 | 0 | +| ModulusAnalysis.java:21:32:21:33 | c1 | 0 | 42 | 0 | +| ModulusAnalysis.java:21:32:21:33 | c1 | SSA init(this.c1) | 0 | 0 | +| ModulusAnalysis.java:21:38:21:38 | 7 | 0 | 7 | 0 | +| ModulusAnalysis.java:22:32:22:32 | x | 0 | 3 | 42 | +| ModulusAnalysis.java:22:32:22:32 | x | SSA init(x) | 0 | 0 | +| ModulusAnalysis.java:22:32:22:36 | ... + ... | 0 | 10 | 42 | +| ModulusAnalysis.java:22:32:22:36 | ... + ... | SSA init(x) | 7 | 42 | +| ModulusAnalysis.java:22:32:22:36 | ... + ... | SSA init(y) | 3 | 42 | +| ModulusAnalysis.java:22:36:22:36 | y | 0 | 7 | 42 | +| ModulusAnalysis.java:22:36:22:36 | y | SSA init(y) | 0 | 0 | +| ModulusAnalysis.java:25:13:25:13 | x | SSA init(x) | 0 | 0 | +| ModulusAnalysis.java:25:17:25:18 | c1 | 0 | 42 | 0 | +| ModulusAnalysis.java:25:17:25:18 | c1 | SSA init(this.c1) | 0 | 0 | +| ModulusAnalysis.java:25:23:25:23 | 3 | 0 | 3 | 0 | +| ModulusAnalysis.java:25:28:25:28 | y | SSA init(y) | 0 | 0 | +| ModulusAnalysis.java:25:32:25:33 | c1 | 0 | 42 | 0 | +| ModulusAnalysis.java:25:32:25:33 | c1 | SSA init(this.c1) | 0 | 0 | +| ModulusAnalysis.java:25:38:25:38 | 7 | 0 | 7 | 0 | +| ModulusAnalysis.java:26:32:26:32 | x | 0 | 3 | 42 | +| ModulusAnalysis.java:26:32:26:32 | x | SSA init(x) | 0 | 0 | +| ModulusAnalysis.java:26:32:26:36 | ... - ... | 0 | 38 | 42 | +| ModulusAnalysis.java:26:32:26:36 | ... - ... | SSA init(x) | 35 | 42 | +| ModulusAnalysis.java:26:36:26:36 | y | 0 | 7 | 42 | +| ModulusAnalysis.java:26:36:26:36 | y | SSA init(y) | 0 | 0 | +| ModulusAnalysis.java:29:17:29:26 | arr.length | SSA impl upd[untracked](arr.length) | 0 | 0 | +| ModulusAnalysis.java:29:17:29:30 | ... * ... | 0 | 0 | 4 | +| ModulusAnalysis.java:29:17:29:35 | ... - ... | 0 | 1 | 4 | +| ModulusAnalysis.java:29:30:29:30 | 4 | 0 | 4 | 0 | +| ModulusAnalysis.java:29:34:29:35 | 11 | 0 | 11 | 0 | +| ModulusAnalysis.java:30:28:30:28 | l | 0 | 1 | 4 | +| ModulusAnalysis.java:30:28:30:28 | l | SSA def(l) | 0 | 0 | +| ModulusAnalysis.java:32:9:32:38 | ...=... | 0 | 1 | 4 | +| ModulusAnalysis.java:32:13:32:29 | getArray(...).length | getArray(...).length | 0 | 0 | +| ModulusAnalysis.java:32:13:32:33 | ... * ... | 0 | 0 | 4 | +| ModulusAnalysis.java:32:13:32:38 | ... - ... | 0 | 1 | 4 | +| ModulusAnalysis.java:32:33:32:33 | 4 | 0 | 4 | 0 | +| ModulusAnalysis.java:32:37:32:38 | 11 | 0 | 11 | 0 | +| ModulusAnalysis.java:33:28:33:28 | l | 0 | 1 | 4 | +| ModulusAnalysis.java:33:28:33:28 | l | SSA def(l) | 0 | 0 | +| ModulusAnalysis.java:36:13:36:25 | ...=... | 0 | 3 | 4 | +| ModulusAnalysis.java:36:17:36:17 | i | SSA init(i) | 0 | 0 | +| ModulusAnalysis.java:36:17:36:21 | ... * ... | 0 | 0 | 4 | +| ModulusAnalysis.java:36:17:36:25 | ... + ... | 0 | 3 | 4 | +| ModulusAnalysis.java:36:21:36:21 | 4 | 0 | 4 | 0 | +| ModulusAnalysis.java:36:25:36:25 | 3 | 0 | 3 | 0 | +| ModulusAnalysis.java:39:13:39:25 | ...=... | 0 | 7 | 8 | +| ModulusAnalysis.java:39:17:39:17 | i | SSA init(i) | 0 | 0 | +| ModulusAnalysis.java:39:17:39:21 | ... * ... | 0 | 0 | 8 | +| ModulusAnalysis.java:39:17:39:25 | ... + ... | 0 | 7 | 8 | +| ModulusAnalysis.java:39:21:39:21 | 8 | 0 | 8 | 0 | +| ModulusAnalysis.java:39:25:39:25 | 7 | 0 | 7 | 0 | +| ModulusAnalysis.java:41:28:41:28 | j | 0 | 3 | 4 | +| ModulusAnalysis.java:41:28:41:28 | j | SSA phi(j) | 0 | 0 | +| ModulusAnalysis.java:44:32:44:32 | j | 0 | 3 | 4 | +| ModulusAnalysis.java:44:32:44:32 | j | SSA phi(j) | 0 | 0 | +| ModulusAnalysis.java:46:32:46:32 | j | 0 | 3 | 4 | +| ModulusAnalysis.java:46:32:46:32 | j | SSA phi(j) | 0 | 0 | +| ModulusAnalysis.java:49:14:49:14 | x | SSA init(x) | 0 | 0 | +| ModulusAnalysis.java:49:18:49:19 | 15 | 0 | 15 | 0 | +| ModulusAnalysis.java:49:25:49:25 | 3 | 0 | 3 | 0 | +| ModulusAnalysis.java:50:32:50:32 | x | 0 | 3 | 16 | +| ModulusAnalysis.java:50:32:50:32 | x | SSA init(x) | 0 | 0 | +| ModulusAnalysis.java:54:38:54:39 | 42 | 0 | 42 | 0 | diff --git a/java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.java b/java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.java new file mode 100644 index 00000000000..bc6b2b73117 --- /dev/null +++ b/java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.java @@ -0,0 +1,55 @@ +class ModulusAnalysis +{ + final int c1 = 42; + final int c2 = 43; + + void m(int i, boolean cond, int x, int y, int[] arr) { + int eq = i + 3; + + int mul = eq * c1 + 3; // congruent 3 mod 42 + + int seven = 7; + if (mul % c2 == seven) { + System.out.println(mul); // congruent 3 mod 42 + } + + int j = cond + ? i * 4 + 3 + : i * 8 + 7; + System.out.println(j); // congruent 3 mod 4 + + if (x % c1 == 3 && y % c1 == 7) { + System.out.println(x + y); // congruent 10 mod 42 + } + + if (x % c1 == 3 && y % c1 == 7) { + System.out.println(x - y); // congruent 38 mod 42 + } + + int l = arr.length * 4 - 11; + System.out.println(l); // congruent 1 mod 4 + + l = getArray().length * 4 - 11; + System.out.println(l); // congruent 1 mod 4 + + if (cond) { + j = i * 4 + 3; + } + else { + j = i * 8 + 7; + } + System.out.println(j); // congruent 3 mod 4 + + if (cond) { + System.out.println(j); // congruent 3 mod 4 + } else { + System.out.println(j); // congruent 3 mod 4 + } + + if ((x & 15) == 3) { + System.out.println(x); // congruent 3 mod 16 + } + } + + int[] getArray(){ return new int[42]; } +} \ No newline at end of file diff --git a/java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.ql b/java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.ql new file mode 100644 index 00000000000..b9a71b74412 --- /dev/null +++ b/java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.ql @@ -0,0 +1,7 @@ +import java +import semmle.code.java.dataflow.ModulusAnalysis +import semmle.code.java.dataflow.Bound + +from Expr e, Bound b, int delta, int mod +where exprModulus(e, b, delta, mod) +select e, b.toString(), delta, mod From 40a7f5aa1fd7acd2c5fd7118aef9aaad20aee14a Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 25 Sep 2020 17:15:47 +0200 Subject: [PATCH 270/411] Java: Minor fix to modulus analysis to handle constant expressions and not only compile time constants --- java/ql/src/semmle/code/java/dataflow/ModulusAnalysis.qll | 6 +++--- .../dataflow/modulus-analysis/ModulusAnalysis.expected | 1 + .../dataflow/modulus-analysis/ModulusAnalysis.java | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/ModulusAnalysis.qll b/java/ql/src/semmle/code/java/dataflow/ModulusAnalysis.qll index b153e9fbd04..012a1ccf5de 100644 --- a/java/ql/src/semmle/code/java/dataflow/ModulusAnalysis.qll +++ b/java/ql/src/semmle/code/java/dataflow/ModulusAnalysis.qll @@ -68,11 +68,11 @@ private Expr modExpr(Expr arg, int mod) { exists(RemExpr rem | result = rem and arg = rem.getLeftOperand() and - rem.getRightOperand().(CompileTimeConstantExpr).getIntValue() = mod and + rem.getRightOperand().(ConstantIntegerExpr).getIntValue() = mod and mod >= 2 ) or - exists(CompileTimeConstantExpr c | + exists(ConstantIntegerExpr c | mod = 2.pow([1 .. 30]) and c.getIntValue() = mod - 1 and result.(AndBitwiseExpr).hasOperands(arg, c) @@ -84,7 +84,7 @@ private Expr modExpr(Expr arg, int mod) { * its `testIsTrue` branch. */ private Guard moduloCheck(SsaVariable v, int val, int mod, boolean testIsTrue) { - exists(Expr rem, CompileTimeConstantExpr c, int r, boolean polarity | + exists(Expr rem, ConstantIntegerExpr c, int r, boolean polarity | result.isEquality(rem, c, polarity) and c.getIntValue() = r and rem = modExpr(v.getAUse(), mod) and diff --git a/java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.expected b/java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.expected index ee4b5e1cf52..597b4795fcb 100644 --- a/java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.expected +++ b/java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.expected @@ -22,6 +22,7 @@ | ModulusAnalysis.java:12:25:12:29 | seven | 0 | 7 | 0 | | ModulusAnalysis.java:12:25:12:29 | seven | SSA def(seven) | 0 | 0 | | ModulusAnalysis.java:13:32:13:34 | mul | 0 | 3 | 42 | +| ModulusAnalysis.java:13:32:13:34 | mul | 0 | 7 | 43 | | ModulusAnalysis.java:13:32:13:34 | mul | SSA def(mul) | 0 | 0 | | ModulusAnalysis.java:16:17:18:23 | ...?...:... | 0 | 3 | 4 | | ModulusAnalysis.java:17:15:17:15 | i | SSA init(i) | 0 | 0 | diff --git a/java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.java b/java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.java index bc6b2b73117..5b251894166 100644 --- a/java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.java +++ b/java/ql/test/library-tests/dataflow/modulus-analysis/ModulusAnalysis.java @@ -10,7 +10,7 @@ class ModulusAnalysis int seven = 7; if (mul % c2 == seven) { - System.out.println(mul); // congruent 3 mod 42 + System.out.println(mul); // congruent 3 mod 42, 7 mod 43 } int j = cond From d2d8d009eb7dd1e298136a0a20bd903d8b7db181 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 24 Sep 2020 13:02:10 +0200 Subject: [PATCH 271/411] Sync Bound between C# and Java --- config/identical-files.json | 4 + .../src/semmle/code/csharp/dataflow/Bound.qll | 78 +++++++++++++++++++ .../internal/rangeanalysis/BoundSpecific.qll | 21 +++++ .../internal/rangeanalysis/ConstantUtils.qll | 9 ++- .../src/semmle/code/java/dataflow/Bound.qll | 8 +- .../internal/rangeanalysis/BoundSpecific.qll | 20 +++++ 6 files changed, 134 insertions(+), 6 deletions(-) create mode 100644 csharp/ql/src/semmle/code/csharp/dataflow/Bound.qll create mode 100644 csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/BoundSpecific.qll create mode 100644 java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/BoundSpecific.qll diff --git a/config/identical-files.json b/config/identical-files.json index e0a4e8dabf4..fa9087dc9d8 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -62,6 +62,10 @@ "java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll", "csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll" ], + "Bound Java/C#": [ + "java/ql/src/semmle/code/java/dataflow/Bound.qll", + "csharp/ql/src/semmle/code/csharp/dataflow/Bound.qll" + ], "C++ SubBasicBlocks": [ "cpp/ql/src/semmle/code/cpp/controlflow/SubBasicBlocks.qll", "cpp/ql/src/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll" diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/Bound.qll b/csharp/ql/src/semmle/code/csharp/dataflow/Bound.qll new file mode 100644 index 00000000000..b129203db70 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/dataflow/Bound.qll @@ -0,0 +1,78 @@ +/** + * Provides classes for representing abstract bounds for use in, for example, range analysis. + */ + +private import internal.rangeanalysis.BoundSpecific + +private newtype TBound = + TBoundZero() or + TBoundSsa(SsaVariable v) { v.getSourceVariable().getType() instanceof IntegralType } or + TBoundExpr(Expr e) { + interestingExprBound(e) and + not exists(SsaVariable v | e = v.getAUse()) + } + +/** + * A bound that may be inferred for an expression plus/minus an integer delta. + */ +abstract class Bound extends TBound { + /** Gets a textual representation of this bound. */ + abstract string toString(); + + /** Gets an expression that equals this bound plus `delta`. */ + abstract Expr getExpr(int delta); + + /** Gets an expression that equals this bound. */ + Expr getExpr() { result = getExpr(0) } + + /** + * Holds if this element is at the specified location. + * The location spans column `sc` of line `sl` to + * column `ec` of line `el` in file `path`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ + predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { + path = "" and sl = 0 and sc = 0 and el = 0 and ec = 0 + } +} + +/** + * The bound that corresponds to the integer 0. This is used to represent all + * integer bounds as bounds are always accompanied by an added integer delta. + */ +class ZeroBound extends Bound, TBoundZero { + override string toString() { result = "0" } + + override Expr getExpr(int delta) { result.(ConstantIntegerExpr).getIntValue() = delta } +} + +/** + * A bound corresponding to the value of an SSA variable. + */ +class SsaBound extends Bound, TBoundSsa { + /** Gets the SSA variable that equals this bound. */ + SsaVariable getSsa() { this = TBoundSsa(result) } + + override string toString() { result = getSsa().toString() } + + override Expr getExpr(int delta) { result = getSsa().getAUse() and delta = 0 } + + override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { + getSsa().getLocation().hasLocationInfo(path, sl, sc, el, ec) + } +} + +/** + * A bound that corresponds to the value of a specific expression that might be + * interesting, but isn't otherwise represented by the value of an SSA variable. + */ +class ExprBound extends Bound, TBoundExpr { + override string toString() { result = getExpr().toString() } + + override Expr getExpr(int delta) { this = TBoundExpr(result) and delta = 0 } + + override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { + getExpr().getLocation().hasLocationInfo(path, sl, sc, el, ec) + } +} diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/BoundSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/BoundSpecific.qll new file mode 100644 index 00000000000..edf437e919c --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/BoundSpecific.qll @@ -0,0 +1,21 @@ +/** + * Provides C#-specific definitions for bounds. + */ + +private import csharp as CS +private import semmle.code.csharp.dataflow.SSA::Ssa as Ssa +private import semmle.code.csharp.dataflow.internal.rangeanalysis.ConstantUtils as CU + +class SsaVariable extends Ssa::Definition { + /** Gets a read of the source variable underlying this SSA definition. */ + Expr getAUse() { result = getARead() } +} + +class Expr = CS::Expr; + +class IntegralType = CS::IntegralType; + +class ConstantIntegerExpr = CU::ConstantIntegerExpr; + +/** Holds if `e` is a bound expression and it is not an SSA variable read. */ +predicate interestingExprBound(Expr e) { CU::systemArrayLengthAccess(e.(CS::PropertyRead)) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ConstantUtils.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ConstantUtils.qll index e283909155c..08b64321a38 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ConstantUtils.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ConstantUtils.qll @@ -17,6 +17,13 @@ predicate propertyOverrides(Property p, string baseClass, string property) { ) } +/** + * Holds if `pa` is an access to the `Length` property of an array. + */ +predicate systemArrayLengthAccess(PropertyAccess pa) { + propertyOverrides(pa.getTarget(), "System.Array", "Length") +} + /** * Holds if expression `e` is either * - a compile time constant with integer value `val`, or @@ -47,7 +54,7 @@ private int getArrayLengthRec(ArrayCreation arrCreation, int index) { } private predicate isArrayLengthAccess(PropertyAccess pa, int length) { - propertyOverrides(pa.getTarget(), "System.Array", "Length") and + systemArrayLengthAccess(pa) and exists(ExplicitDefinition arr, ArrayCreation arrCreation | getArrayLengthRec(arrCreation, arrCreation.getNumberOfLengthArguments() - 1) = length and arrCreation = arr.getADefinition().getSource() and diff --git a/java/ql/src/semmle/code/java/dataflow/Bound.qll b/java/ql/src/semmle/code/java/dataflow/Bound.qll index 4a89f8cfeba..b129203db70 100644 --- a/java/ql/src/semmle/code/java/dataflow/Bound.qll +++ b/java/ql/src/semmle/code/java/dataflow/Bound.qll @@ -2,15 +2,13 @@ * Provides classes for representing abstract bounds for use in, for example, range analysis. */ -import java -private import SSA -private import RangeUtils +private import internal.rangeanalysis.BoundSpecific private newtype TBound = TBoundZero() or TBoundSsa(SsaVariable v) { v.getSourceVariable().getType() instanceof IntegralType } or TBoundExpr(Expr e) { - e.(FieldRead).getField() instanceof ArrayLengthField and + interestingExprBound(e) and not exists(SsaVariable v | e = v.getAUse()) } @@ -75,6 +73,6 @@ class ExprBound extends Bound, TBoundExpr { override Expr getExpr(int delta) { this = TBoundExpr(result) and delta = 0 } override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { - getExpr().hasLocationInfo(path, sl, sc, el, ec) + getExpr().getLocation().hasLocationInfo(path, sl, sc, el, ec) } } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/BoundSpecific.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/BoundSpecific.qll new file mode 100644 index 00000000000..f7fca3a184f --- /dev/null +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/BoundSpecific.qll @@ -0,0 +1,20 @@ +/** + * Provides Java-specific definitions for bounds. + */ + +private import java as J +private import semmle.code.java.dataflow.SSA as Ssa +private import semmle.code.java.dataflow.RangeUtils as RU + +class SsaVariable = Ssa::SsaVariable; + +class Expr = J::Expr; + +class IntegralType = J::IntegralType; + +class ConstantIntegerExpr = RU::ConstantIntegerExpr; + +/** Holds if `e` is a bound expression and it is not an SSA variable read. */ +predicate interestingExprBound(Expr e) { + e.(J::FieldRead).getField() instanceof J::ArrayLengthField +} From 300a8cdf7db14308b32e5a67b90f0e57430616bb Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 7 Oct 2020 11:23:03 +0200 Subject: [PATCH 272/411] Python: Add tests for the 'invoke' package --- .../frameworks/invoke/ConceptsTest.expected | 9 +++++ .../frameworks/invoke/ConceptsTest.ql | 2 + .../frameworks/invoke/invoke_test.py | 39 +++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.expected create mode 100644 python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.ql create mode 100644 python/ql/test/experimental/library-tests/frameworks/invoke/invoke_test.py diff --git a/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.expected b/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.expected new file mode 100644 index 00000000000..6ced96216b9 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.expected @@ -0,0 +1,9 @@ +| invoke_test.py:8:27:8:52 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | +| invoke_test.py:9:35:9:60 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | +| invoke_test.py:13:32:13:57 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | +| invoke_test.py:14:40:14:65 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | +| invoke_test.py:19:26:19:51 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | +| invoke_test.py:20:27:20:52 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | +| invoke_test.py:24:27:24:52 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | +| invoke_test.py:31:26:31:51 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | +| invoke_test.py:38:26:38:51 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | diff --git a/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.ql b/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.ql new file mode 100644 index 00000000000..b557a0bccb6 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.ql @@ -0,0 +1,2 @@ +import python +import experimental.meta.ConceptsTest diff --git a/python/ql/test/experimental/library-tests/frameworks/invoke/invoke_test.py b/python/ql/test/experimental/library-tests/frameworks/invoke/invoke_test.py new file mode 100644 index 00000000000..e926a79f9f7 --- /dev/null +++ b/python/ql/test/experimental/library-tests/frameworks/invoke/invoke_test.py @@ -0,0 +1,39 @@ +"""tests for the 'invoke' package + +see https://www.pyinvoke.org/ +""" + +import invoke + +invoke.run("cmd1; cmd2") # $getCommand="cmd1; cmd2" +invoke.run(command="cmd1; cmd2") # $getCommand="cmd1; cmd2" + + +def with_sudo(): + invoke.sudo("cmd1; cmd2") # $getCommand="cmd1; cmd2" + invoke.sudo(command="cmd1; cmd2") # $getCommand="cmd1; cmd2" + + +def manual_context(): + c = invoke.Context() + c.run("cmd1; cmd2") # $getCommand="cmd1; cmd2" + c.sudo("cmd1; cmd2") # $getCommand="cmd1; cmd2" + + # invoke.Context is just an alias for invoke.context.Context + c2 = invoke.context.Context() + c2.run("cmd1; cmd2") # $getCommand="cmd1; cmd2" + + +manual_context() + + +def foo_helper(c): + c.run("cmd1; cmd2") # $getCommand="cmd1; cmd2" + + +# for use with the 'invoke' command-line tool +@invoke.task +def foo(c): + # 'c' is a invoke.context.Context + c.run("cmd1; cmd2") # $getCommand="cmd1; cmd2" + foo_helper(c) From 4ef5202382490d107f149b97ca1906fa10e98db3 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 7 Oct 2020 11:47:38 +0200 Subject: [PATCH 273/411] Python: Add simple model for invoke.run and invoke.sudo and I sorted the list in Frameworks.qll, that kinda makes sense :) --- .../experimental/semmle/python/Frameworks.qll | 3 +- .../semmle/python/frameworks/Invoke.qll | 89 +++++++++++++++++++ .../frameworks/invoke/ConceptsTest.expected | 4 - 3 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 python/ql/src/experimental/semmle/python/frameworks/Invoke.qll diff --git a/python/ql/src/experimental/semmle/python/Frameworks.qll b/python/ql/src/experimental/semmle/python/Frameworks.qll index 13a8ca5f2da..44a26ddbd82 100644 --- a/python/ql/src/experimental/semmle/python/Frameworks.qll +++ b/python/ql/src/experimental/semmle/python/Frameworks.qll @@ -2,6 +2,7 @@ * Helper file that imports all framework modeling. */ -private import experimental.semmle.python.frameworks.Flask private import experimental.semmle.python.frameworks.Django +private import experimental.semmle.python.frameworks.Flask +private import experimental.semmle.python.frameworks.Invoke private import experimental.semmle.python.frameworks.Stdlib diff --git a/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll b/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll new file mode 100644 index 00000000000..0b2c9c4d144 --- /dev/null +++ b/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll @@ -0,0 +1,89 @@ +/** + * Provides classes modeling security-relevant aspects of the `invoke` PyPI package. + * See https://www.pyinvoke.org/. + */ + +private import python +private import experimental.dataflow.DataFlow +private import experimental.dataflow.RemoteFlowSources +private import experimental.dataflow.TaintTracking +private import experimental.semmle.python.Concepts +private import experimental.semmle.python.frameworks.Werkzeug + +/** + * Provides models for the `invoke` PyPI package. + * See https://www.pyinvoke.org/. + */ +private module Invoke { + // --------------------------------------------------------------------------- + // invoke + // --------------------------------------------------------------------------- + /** Gets a reference to the `invoke` module. */ + private DataFlow::Node invoke(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importModule("invoke") + or + exists(DataFlow::TypeTracker t2 | result = invoke(t2).track(t2, t)) + } + + /** Gets a reference to the `invoke` module. */ + DataFlow::Node invoke() { result = invoke(DataFlow::TypeTracker::end()) } + + /** + * Gets a reference to the attribute `attr_name` of the `invoke` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node invoke_attr(DataFlow::TypeTracker t, string attr_name) { + attr_name in ["run", "sudo"] and + ( + t.start() and + result = DataFlow::importMember("invoke", attr_name) + or + t.startInAttr(attr_name) and + result = DataFlow::importModule("invoke") + ) + or + // Due to bad performance when using normal setup with `invoke_attr(t2, attr_name).track(t2, t)` + // we have inlined that code and forced a join + exists(DataFlow::TypeTracker t2 | + exists(DataFlow::StepSummary summary | + invoke_attr_first_join(t2, attr_name, result, summary) and + t = t2.append(summary) + ) + ) + } + + pragma[nomagic] + private predicate invoke_attr_first_join( + DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, DataFlow::StepSummary summary + ) { + DataFlow::StepSummary::step(invoke_attr(t2, attr_name), res, summary) + } + + /** + * Gets a reference to the attribute `attr_name` of the `invoke` module. + * WARNING: Only holds for a few predefined attributes. + */ + private DataFlow::Node invoke_attr(string attr_name) { + result = invoke_attr(DataFlow::TypeTracker::end(), attr_name) + } + + /** Provides models for the `invoke` module. */ + module invoke { } + + /** + * A call to either of the `invoke.run` or `invoke.sudo` functions + * See http://docs.pyinvoke.org/en/stable/api/__init__.html + */ + private class InvokeRunCommandCall extends SystemCommandExecution::Range { + InvokeRunCommandCall() { + this.asCfgNode().(CallNode).getFunction() = invoke_attr(["run", "sudo"]).asCfgNode() + } + + override DataFlow::Node getCommand() { + result.asCfgNode() = this.asCfgNode().(CallNode).getArg(0) + or + result.asCfgNode() = this.asCfgNode().(CallNode).getArgByName("command") + } + } +} diff --git a/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.expected b/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.expected index 6ced96216b9..3c1cefe0a40 100644 --- a/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.expected +++ b/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.expected @@ -1,7 +1,3 @@ -| invoke_test.py:8:27:8:52 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | -| invoke_test.py:9:35:9:60 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | -| invoke_test.py:13:32:13:57 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | -| invoke_test.py:14:40:14:65 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | | invoke_test.py:19:26:19:51 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | | invoke_test.py:20:27:20:52 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | | invoke_test.py:24:27:24:52 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | From ebff1794fc511dbca2274e9e9bcc872b86b9e298 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 7 Oct 2020 12:16:53 +0200 Subject: [PATCH 274/411] Python: Model invoke.context.Context --- .../semmle/python/frameworks/Invoke.qll | 68 +++++++++++++++++-- .../frameworks/invoke/ConceptsTest.expected | 3 - 2 files changed, 63 insertions(+), 8 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll b/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll index 0b2c9c4d144..d96e9fff3a7 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll @@ -34,7 +34,7 @@ private module Invoke { * WARNING: Only holds for a few predefined attributes. */ private DataFlow::Node invoke_attr(DataFlow::TypeTracker t, string attr_name) { - attr_name in ["run", "sudo"] and + attr_name in ["run", "sudo", "context", "Context"] and ( t.start() and result = DataFlow::importMember("invoke", attr_name) @@ -69,15 +69,73 @@ private module Invoke { } /** Provides models for the `invoke` module. */ - module invoke { } + module invoke { + /** Gets a reference to the `invoke.context` module. */ + DataFlow::Node context() { result = invoke_attr("context") } + + /** Provides models for the `invoke.context` module */ + module context { + /** Provides models for the `invoke.context.Context` class */ + module Context { + /** Gets a reference to the `invoke.context.Context` class. */ + private DataFlow::Node class_(DataFlow::TypeTracker t) { + t.start() and + result = DataFlow::importMember("invoke.context", "Context") + or + t.startInAttr("Context") and + result = invoke::context() + or + t.start() and + result = invoke_attr("Context") + or + exists(DataFlow::TypeTracker t2 | result = class_(t2).track(t2, t)) + } + + /** Gets a reference to the `invoke.context.Context` class. */ + DataFlow::Node class_() { result = class_(DataFlow::TypeTracker::end()) } + + /** Gets a reference to an instance of `invoke.context.Context`. */ + private DataFlow::Node instance(DataFlow::TypeTracker t) { + t.start() and + result.asCfgNode().(CallNode).getFunction() = + invoke::context::Context::class_().asCfgNode() + or + exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t)) + } + + /** Gets a reference to an instance of `invoke.context.Context`. */ + DataFlow::Node instance() { result = instance(DataFlow::TypeTracker::end()) } + + /** Gets a reference to the `run` or `sudo` methods on a `invoke.context.Context` instance. */ + private DataFlow::Node instanceRunMethods(DataFlow::TypeTracker t) { + t.startInAttr(["run", "sudo"]) and + result = invoke::context::Context::instance() + or + exists(DataFlow::TypeTracker t2 | result = instanceRunMethods(t2).track(t2, t)) + } + + /** Gets a reference to the `run` or `sudo` methods on a `invoke.context.Context` instance. */ + DataFlow::Node instanceRunMethods() { + result = instanceRunMethods(DataFlow::TypeTracker::end()) + } + } + } + } /** - * A call to either of the `invoke.run` or `invoke.sudo` functions - * See http://docs.pyinvoke.org/en/stable/api/__init__.html + * A call to either + * - `invoke.run` or `invoke.sudo` functions (http://docs.pyinvoke.org/en/stable/api/__init__.html) + * - `run` or `sudo` methods on a `invoke.context.Context` instance (http://docs.pyinvoke.org/en/stable/api/context.html#invoke.context.Context.run) */ private class InvokeRunCommandCall extends SystemCommandExecution::Range { InvokeRunCommandCall() { - this.asCfgNode().(CallNode).getFunction() = invoke_attr(["run", "sudo"]).asCfgNode() + exists(DataFlow::Node callFunction | + this.asCfgNode().(CallNode).getFunction() = callFunction.asCfgNode() + | + callFunction = invoke_attr(["run", "sudo"]) + or + callFunction = invoke::context::Context::instanceRunMethods() + ) } override DataFlow::Node getCommand() { diff --git a/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.expected b/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.expected index 3c1cefe0a40..b02dab20015 100644 --- a/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.expected +++ b/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.expected @@ -1,5 +1,2 @@ -| invoke_test.py:19:26:19:51 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | -| invoke_test.py:20:27:20:52 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | -| invoke_test.py:24:27:24:52 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | | invoke_test.py:31:26:31:51 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | | invoke_test.py:38:26:38:51 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | From c9219b37441eeef6284ae09438570c1f3e27b0b3 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 7 Oct 2020 12:21:30 +0200 Subject: [PATCH 275/411] Clean module imports --- python/ql/src/experimental/semmle/python/frameworks/Invoke.qll | 3 --- 1 file changed, 3 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll b/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll index d96e9fff3a7..319d31d866b 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll @@ -5,10 +5,7 @@ private import python private import experimental.dataflow.DataFlow -private import experimental.dataflow.RemoteFlowSources -private import experimental.dataflow.TaintTracking private import experimental.semmle.python.Concepts -private import experimental.semmle.python.frameworks.Werkzeug /** * Provides models for the `invoke` PyPI package. From 6d7f4a048bac4daaa71fcee1a95adb1e8ec59296 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 7 Oct 2020 12:26:49 +0200 Subject: [PATCH 276/411] Python: Attempt to model invoke.task decorator --- .../src/experimental/semmle/python/frameworks/Invoke.qll | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll b/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll index 319d31d866b..b8fd71c73b9 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll @@ -31,7 +31,7 @@ private module Invoke { * WARNING: Only holds for a few predefined attributes. */ private DataFlow::Node invoke_attr(DataFlow::TypeTracker t, string attr_name) { - attr_name in ["run", "sudo", "context", "Context"] and + attr_name in ["run", "sudo", "context", "Context", "task"] and ( t.start() and result = DataFlow::importMember("invoke", attr_name) @@ -97,6 +97,12 @@ private module Invoke { result.asCfgNode().(CallNode).getFunction() = invoke::context::Context::class_().asCfgNode() or + t.start() and + exists(Function func | + func.getADecorator() = invoke_attr("task").asExpr() and + result.asExpr() = func.getArg(0) + ) + or exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t)) } From 67c5c590d2c7c98e68489b64c11751438c6b651a Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 2 Oct 2020 18:52:14 +0200 Subject: [PATCH 277/411] Python: Expose getParameter on ParameterNode --- .../ql/src/experimental/dataflow/internal/DataFlowPublic.qll | 3 +++ python/ql/src/semmle/python/essa/Essa.qll | 1 + 2 files changed, 4 insertions(+) diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll b/python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll index fb68fe3b1f1..bec7ca747fa 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowPublic.qll @@ -151,6 +151,9 @@ class ParameterNode extends EssaNode { } override DataFlowCallable getEnclosingCallable() { this.isParameterOf(result, _) } + + /** Gets the `Parameter` this `ParameterNode` represents. */ + Parameter getParameter() { result = var.(ParameterDefinition).getParameter() } } /** diff --git a/python/ql/src/semmle/python/essa/Essa.qll b/python/ql/src/semmle/python/essa/Essa.qll index b44b784b48d..b8cf058c114 100644 --- a/python/ql/src/semmle/python/essa/Essa.qll +++ b/python/ql/src/semmle/python/essa/Essa.qll @@ -567,6 +567,7 @@ class ParameterDefinition extends EssaNodeDefinition { exists(Function func | func.getKwarg() = this.getDefiningNode().getNode()) } + /** Gets the `Parameter` this `ParameterDefinition` represents. */ Parameter getParameter() { result = this.getDefiningNode().getNode() } } From c09695af7d3c307f68f52debbcf5d986d81f21a1 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 7 Oct 2020 12:29:19 +0200 Subject: [PATCH 278/411] Python: Properly handle invoke.task decorator --- python/ql/src/experimental/semmle/python/frameworks/Invoke.qll | 2 +- .../library-tests/frameworks/invoke/ConceptsTest.expected | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll b/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll index b8fd71c73b9..671a2fd4d13 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Invoke.qll @@ -100,7 +100,7 @@ private module Invoke { t.start() and exists(Function func | func.getADecorator() = invoke_attr("task").asExpr() and - result.asExpr() = func.getArg(0) + result.(DataFlow::ParameterNode).getParameter() = func.getArg(0) ) or exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t)) diff --git a/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.expected b/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.expected index b02dab20015..e69de29bb2d 100644 --- a/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.expected +++ b/python/ql/test/experimental/library-tests/frameworks/invoke/ConceptsTest.expected @@ -1,2 +0,0 @@ -| invoke_test.py:31:26:31:51 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | -| invoke_test.py:38:26:38:51 | Comment # $getCommand="cmd1; cmd2" | Missing result:getCommand="cmd1; cmd2" | From a4ce9417bc0b86c9fb072b249e717016d55d0f37 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 6 Oct 2020 10:34:57 +0200 Subject: [PATCH 279/411] C#: Add test for missing accessors --- csharp/ql/test/library-tests/indexers/Indexers12.expected | 0 csharp/ql/test/library-tests/indexers/Indexers12.ql | 8 ++++++++ 2 files changed, 8 insertions(+) create mode 100644 csharp/ql/test/library-tests/indexers/Indexers12.expected create mode 100644 csharp/ql/test/library-tests/indexers/Indexers12.ql diff --git a/csharp/ql/test/library-tests/indexers/Indexers12.expected b/csharp/ql/test/library-tests/indexers/Indexers12.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/csharp/ql/test/library-tests/indexers/Indexers12.ql b/csharp/ql/test/library-tests/indexers/Indexers12.ql new file mode 100644 index 00000000000..189c239edb1 --- /dev/null +++ b/csharp/ql/test/library-tests/indexers/Indexers12.ql @@ -0,0 +1,8 @@ +import csharp + +from Indexer i, Accessor a, string s +where + i.getDeclaringType().hasQualifiedName("System", s) and + s.regexpMatch("Tuple<,*>") and + a = i.getAnAccessor() +select i.toStringWithTypes(), a.toStringWithTypes() From bec33b745e1415f927b8f3e111b0a721ce1c5790 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 7 Oct 2020 14:54:51 +0200 Subject: [PATCH 280/411] Python: Use `range` instead of `self` for ::Range pattern Following the suggestions from https://github.com/github/codeql/pull/4357 --- python/ql/src/experimental/semmle/python/Concepts.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index e1cd0fa580e..f20be525ead 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -16,12 +16,12 @@ private import experimental.semmle.python.Frameworks * extend `SystemCommandExecution::Range` instead. */ class SystemCommandExecution extends DataFlow::Node { - SystemCommandExecution::Range self; + SystemCommandExecution::Range range; - SystemCommandExecution() { this = self } + SystemCommandExecution() { this = range } /** Gets the argument that specifies the command to be executed. */ - DataFlow::Node getCommand() { result = self.getCommand() } + DataFlow::Node getCommand() { result = range.getCommand() } } /** Provides a class for modeling new system-command execution APIs. */ From 68014fd3bf662453f1cd9a44a8b05008e79474e2 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 6 Oct 2020 10:35:09 +0200 Subject: [PATCH 281/411] C#: Fix extraction of library indexers with explicit interface implementations --- .../Entities/Accessor.cs | 35 ++++++++++--------- .../Entities/Method.cs | 2 +- .../indexers/Indexers12.expected | 1 + 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs index cc713b5ad2f..c343c0678c3 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs @@ -9,25 +9,28 @@ namespace Semmle.Extraction.CSharp.Entities protected Accessor(Context cx, IMethodSymbol init) : base(cx, init) { } + ///

    + /// Gets the property symbol associated accessor `symbol`, or `null` + /// if there is no associated symbol. + /// + public static IPropertySymbol GetPropertySymbol(IMethodSymbol symbol) + { + // Usually, the property/indexer can be fetched from the associated symbol + var prop = symbol.AssociatedSymbol as IPropertySymbol; + if (prop != null) + return prop; + + // But for properties/indexers that implement explicit interfaces, Roslyn + // does not properly populate `AssociatedSymbol` + var props = symbol.ContainingType.GetMembers().OfType(); + props = props.Where(p => SymbolEqualityComparer.Default.Equals(symbol, p.GetMethod) || SymbolEqualityComparer.Default.Equals(symbol, p.SetMethod)); + return props.SingleOrDefault(); + } + /// /// Gets the property symbol associated with this accessor. /// - IPropertySymbol PropertySymbol - { - get - { - // Usually, the property/indexer can be fetched from the associated symbol - var prop = symbol.AssociatedSymbol as IPropertySymbol; - if (prop != null) - return prop; - - // But for properties/indexers that implement explicit interfaces, Roslyn - // does not properly populate `AssociatedSymbol` - var props = symbol.ContainingType.GetMembers().OfType(); - props = props.Where(p => SymbolEqualityComparer.Default.Equals(symbol, p.GetMethod) || SymbolEqualityComparer.Default.Equals(symbol, p.SetMethod)); - return props.SingleOrDefault(); - } - } + IPropertySymbol PropertySymbol => GetPropertySymbol(symbol); public new Accessor OriginalDefinition => Create(Context, symbol.OriginalDefinition); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs index 2527920ca3a..5c7c5481ebe 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs @@ -240,7 +240,7 @@ namespace Semmle.Extraction.CSharp.Entities return Destructor.Create(cx, methodDecl); case MethodKind.PropertyGet: case MethodKind.PropertySet: - return methodDecl.AssociatedSymbol is null ? OrdinaryMethod.Create(cx, methodDecl) : (Method)Accessor.Create(cx, methodDecl); + return Accessor.GetPropertySymbol(methodDecl) is null ? OrdinaryMethod.Create(cx, methodDecl) : (Method)Accessor.Create(cx, methodDecl); case MethodKind.EventAdd: case MethodKind.EventRemove: return EventAccessor.Create(cx, methodDecl); diff --git a/csharp/ql/test/library-tests/indexers/Indexers12.expected b/csharp/ql/test/library-tests/indexers/Indexers12.expected index e69de29bb2d..a97b8216ef3 100644 --- a/csharp/ql/test/library-tests/indexers/Indexers12.expected +++ b/csharp/ql/test/library-tests/indexers/Indexers12.expected @@ -0,0 +1 @@ +| Item[int] | get_Item(int) | From af36718dc63edabe37d48ee445ee46dd2f454aff Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 7 Oct 2020 15:15:18 +0200 Subject: [PATCH 282/411] C#: QL doc adjustments --- .../src/semmle/code/csharp/controlflow/ControlFlowElement.qll | 3 +++ .../src/semmle/code/csharp/controlflow/internal/Splitting.qll | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowElement.qll b/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowElement.qll index 84d218e78d7..7f0a3666b29 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowElement.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowElement.qll @@ -126,6 +126,9 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element { * ``` * * does not work. + * + * `cb` records all of the possible condition blocks for this control flow element + * that a path from the callable entry point to `succ` may go through. */ pragma[nomagic] private predicate immediatelyControlsBlockSplit( diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll index 1fedd716806..c56f3db362a 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll @@ -409,7 +409,7 @@ module AssertionSplitting { * ``` * * we record whether `i >= 0` evaluates to `true` or `false`, and restrict the - * edges out out of the assertion accordingly. + * edges out of the assertion accordingly. */ class AssertionSplitImpl extends SplitImpl, TAssertionSplit { Assertion a; From 239ea809755233284493bd6df6f5cd3ed08cdff1 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 7 Oct 2020 14:37:35 +0100 Subject: [PATCH 283/411] add new css styles --- .../global-sphinx-files/_static/custom.css_t | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/docs/language/global-sphinx-files/_static/custom.css_t b/docs/language/global-sphinx-files/_static/custom.css_t index 7d2b1a02b90..09d8e87f64c 100644 --- a/docs/language/global-sphinx-files/_static/custom.css_t +++ b/docs/language/global-sphinx-files/_static/custom.css_t @@ -76,6 +76,9 @@ div.linkbar { text-decoration: underline; } +div.footer { + width: 100%; +} /* CODEQL DOCUMENTATION AND SEARCHBOX BANNER ---------------------------------------------------------- */ @@ -156,6 +159,10 @@ div.body li { /* -- SIDEBAR ------------------------------------------------------------------------------- */ +.SideNav { + height: 100vh; +} + div.navBox { width:29%; padding-left: 25px; @@ -190,6 +197,20 @@ div.navBox { text-decoration: underline; } +/* -- BREADCRUMBS --------------------------------------------------------------------------------*/ + +div.related ul { + padding: 0; +} + +a.reference { + border-bottom: none; +} + +a.reference:hover { + text-decoration: none; +} + /* -- SIDEBAR TOC ----------------------------------------------------------------------------------*/ #toc h1 { @@ -201,12 +222,13 @@ div.navBox { /* -- SMALL SCREEN ------------------------------------------------------------------------------- */ @media screen and (max-width: 875px){ - + /* Override strange behaviour caused by default styles */ body { - margin: 0; padding: 0; - overflow: inherit; - width: 100%; + } + + div.footer { + display: block; } #siteBanner { @@ -266,9 +288,6 @@ div.navBox { padding-left:0; } - div.body { - min-width: unset; - } ul { margin: 10px 20px 10px 20px; @@ -489,4 +508,4 @@ blockquote.pull-quote > :last-child { .toggle .name.open:after { content: " â–¼"; -} +} \ No newline at end of file From 4df6a4161666c080c3e2bbfb704a4d950d08c7e1 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 6 Oct 2020 09:36:42 +0200 Subject: [PATCH 284/411] ModulusAnalysis shared between C# and Java --- config/identical-files.json | 4 + .../code/csharp/dataflow/ModulusAnalysis.qll | 302 ++++++++++++++++++ .../rangeanalysis/ModulusAnalysisSpecific.qll | 110 +++++++ .../internal/rangeanalysis/RangeUtils.qll | 98 ++++++ .../rangeanalysis/SignAnalysisSpecific.qll | 14 +- .../modulusanalysis/ModulusAnalysis.cs | 84 +++++ .../modulusanalysis/ModulusAnalysis.expected | 138 ++++++++ .../modulusanalysis/ModulusAnalysis.ql | 7 + .../code/java/dataflow/ModulusAnalysis.qll | 55 +--- .../rangeanalysis/ModulusAnalysisSpecific.qll | 119 +++++++ 10 files changed, 879 insertions(+), 52 deletions(-) create mode 100644 csharp/ql/src/semmle/code/csharp/dataflow/ModulusAnalysis.qll create mode 100644 csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ModulusAnalysisSpecific.qll create mode 100644 csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll create mode 100644 csharp/ql/test/library-tests/dataflow/modulusanalysis/ModulusAnalysis.cs create mode 100644 csharp/ql/test/library-tests/dataflow/modulusanalysis/ModulusAnalysis.expected create mode 100644 csharp/ql/test/library-tests/dataflow/modulusanalysis/ModulusAnalysis.ql create mode 100644 java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/ModulusAnalysisSpecific.qll diff --git a/config/identical-files.json b/config/identical-files.json index fa9087dc9d8..9be5c0d0dd2 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -66,6 +66,10 @@ "java/ql/src/semmle/code/java/dataflow/Bound.qll", "csharp/ql/src/semmle/code/csharp/dataflow/Bound.qll" ], + "ModulusAnalysis Java/C#": [ + "java/ql/src/semmle/code/java/dataflow/ModulusAnalysis.qll", + "csharp/ql/src/semmle/code/csharp/dataflow/ModulusAnalysis.qll" + ], "C++ SubBasicBlocks": [ "cpp/ql/src/semmle/code/cpp/controlflow/SubBasicBlocks.qll", "cpp/ql/src/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll" diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/ModulusAnalysis.qll b/csharp/ql/src/semmle/code/csharp/dataflow/ModulusAnalysis.qll new file mode 100644 index 00000000000..2b3c3402415 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/dataflow/ModulusAnalysis.qll @@ -0,0 +1,302 @@ +/** + * Provides inferences of the form: `e` equals `b + v` modulo `m` where `e` is + * an expression, `b` is a `Bound` (typically zero or the value of an SSA + * variable), and `v` is an integer in the range `[0 .. m-1]`. + */ + +private import internal.rangeanalysis.ModulusAnalysisSpecific::Private +private import Bound +private import internal.rangeanalysis.SsaReadPositionCommon + +/** + * Holds if `e + delta` equals `v` at `pos`. + */ +private predicate valueFlowStepSsa(SsaVariable v, SsaReadPosition pos, Expr e, int delta) { + ssaUpdateStep(v, e, delta) and pos.hasReadOfVar(v) + or + exists(Guard guard, boolean testIsTrue | + pos.hasReadOfVar(v) and + guard = eqFlowCond(v, e, delta, true, testIsTrue) and + guardDirectlyControlsSsaRead(guard, pos, testIsTrue) + ) +} + +/** + * Holds if `add` is the addition of `larg` and `rarg`, neither of which are + * `ConstantIntegerExpr`s. + */ +private predicate nonConstAddition(Expr add, Expr larg, Expr rarg) { + exists(AddExpr a | a = add | + larg = a.getLhs() and + rarg = a.getRhs() + ) and + not larg instanceof ConstantIntegerExpr and + not rarg instanceof ConstantIntegerExpr +} + +/** + * Holds if `sub` is the subtraction of `larg` and `rarg`, where `rarg` is not + * a `ConstantIntegerExpr`. + */ +private predicate nonConstSubtraction(Expr sub, Expr larg, Expr rarg) { + exists(SubExpr s | s = sub | + larg = s.getLhs() and + rarg = s.getRhs() + ) and + not rarg instanceof ConstantIntegerExpr +} + +/** Gets an expression that is the remainder modulo `mod` of `arg`. */ +private Expr modExpr(Expr arg, int mod) { + exists(RemExpr rem | + result = rem and + arg = rem.getLeftOperand() and + rem.getRightOperand().(ConstantIntegerExpr).getIntValue() = mod and + mod >= 2 + ) + or + exists(ConstantIntegerExpr c | + mod = 2.pow([1 .. 30]) and + c.getIntValue() = mod - 1 and + result.(BitwiseAndExpr).hasOperands(arg, c) + ) +} + +/** + * Gets a guard that tests whether `v` is congruent with `val` modulo `mod` on + * its `testIsTrue` branch. + */ +private Guard moduloCheck(SsaVariable v, int val, int mod, boolean testIsTrue) { + exists(Expr rem, ConstantIntegerExpr c, int r, boolean polarity | + result.isEquality(rem, c, polarity) and + c.getIntValue() = r and + rem = modExpr(v.getAUse(), mod) and + ( + testIsTrue = polarity and val = r + or + testIsTrue = polarity.booleanNot() and + mod = 2 and + val = 1 - r and + (r = 0 or r = 1) + ) + ) +} + +/** + * Holds if a guard ensures that `v` at `pos` is congruent with `val` modulo `mod`. + */ +private predicate moduloGuardedRead(SsaVariable v, SsaReadPosition pos, int val, int mod) { + exists(Guard guard, boolean testIsTrue | + pos.hasReadOfVar(v) and + guard = moduloCheck(v, val, mod, testIsTrue) and + guardControlsSsaRead(guard, pos, testIsTrue) + ) +} + +/** Holds if `factor` is a power of 2 that divides `mask`. */ +bindingset[mask] +private predicate andmaskFactor(int mask, int factor) { + mask % factor = 0 and + factor = 2.pow([1 .. 30]) +} + +/** Holds if `e` is evenly divisible by `factor`. */ +private predicate evenlyDivisibleExpr(Expr e, int factor) { + exists(ConstantIntegerExpr c, int k | k = c.getIntValue() | + e.(MulExpr).getAnOperand() = c and factor = k.abs() and factor >= 2 + or + e.(LShiftExpr).getRhs() = c and factor = 2.pow(k) and k > 0 + or + e.(BitwiseAndExpr).getAnOperand() = c and factor = max(int f | andmaskFactor(k, f)) + ) +} + +/** + * Holds if `inp` is an input to `phi` along `edge` and this input has index `r` + * in an arbitrary 1-based numbering of the input edges to `phi`. + */ +private predicate rankedPhiInput( + SsaPhiNode phi, SsaVariable inp, SsaReadPositionPhiInputEdge edge, int r +) { + edge.phiInput(phi, inp) and + edge = + rank[r](SsaReadPositionPhiInputEdge e | e.phiInput(phi, _) | e order by getId(e.getOrigBlock())) +} + +/** + * Holds if `rix` is the number of input edges to `phi`. + */ +private predicate maxPhiInputRank(SsaPhiNode phi, int rix) { + rix = max(int r | rankedPhiInput(phi, _, _, r)) +} + +/** + * Gets the remainder of `val` modulo `mod`. + * + * For `mod = 0` the result equals `val` and for `mod > 1` the result is within + * the range `[0 .. mod-1]`. + */ +bindingset[val, mod] +private int remainder(int val, int mod) { + mod = 0 and result = val + or + mod > 1 and result = ((val % mod) + mod) % mod +} + +/** + * Holds if `inp` is an input to `phi` and equals `phi` modulo `mod` along `edge`. + */ +private predicate phiSelfModulus( + SsaPhiNode phi, SsaVariable inp, SsaReadPositionPhiInputEdge edge, int mod +) { + exists(SsaBound phibound, int v, int m | + edge.phiInput(phi, inp) and + phibound.getSsa() = phi and + ssaModulus(inp, edge, phibound, v, m) and + mod = m.gcd(v) and + mod != 1 + ) +} + +/** + * Holds if `b + val` modulo `mod` is a candidate congruence class for `phi`. + */ +private predicate phiModulusInit(SsaPhiNode phi, Bound b, int val, int mod) { + exists(SsaVariable inp, SsaReadPositionPhiInputEdge edge | + edge.phiInput(phi, inp) and + ssaModulus(inp, edge, b, val, mod) + ) +} + +/** + * Holds if all inputs to `phi` numbered `1` to `rix` are equal to `b + val` modulo `mod`. + */ +private predicate phiModulusRankStep(SsaPhiNode phi, Bound b, int val, int mod, int rix) { + rix = 0 and + phiModulusInit(phi, b, val, mod) + or + exists(SsaVariable inp, SsaReadPositionPhiInputEdge edge, int v1, int m1 | + mod != 1 and + val = remainder(v1, mod) + | + exists(int v2, int m2 | + rankedPhiInput(phi, inp, edge, rix) and + phiModulusRankStep(phi, b, v1, m1, rix - 1) and + ssaModulus(inp, edge, b, v2, m2) and + mod = m1.gcd(m2).gcd(v1 - v2) + ) + or + exists(int m2 | + rankedPhiInput(phi, inp, edge, rix) and + phiModulusRankStep(phi, b, v1, m1, rix - 1) and + phiSelfModulus(phi, inp, edge, m2) and + mod = m1.gcd(m2) + ) + ) +} + +/** + * Holds if `phi` is equal to `b + val` modulo `mod`. + */ +private predicate phiModulus(SsaPhiNode phi, Bound b, int val, int mod) { + exists(int r | + maxPhiInputRank(phi, r) and + phiModulusRankStep(phi, b, val, mod, r) + ) +} + +/** + * Holds if `v` at `pos` is equal to `b + val` modulo `mod`. + */ +private predicate ssaModulus(SsaVariable v, SsaReadPosition pos, Bound b, int val, int mod) { + phiModulus(v, b, val, mod) and pos.hasReadOfVar(v) + or + b.(SsaBound).getSsa() = v and pos.hasReadOfVar(v) and val = 0 and mod = 0 + or + exists(Expr e, int val0, int delta | + exprModulus(e, b, val0, mod) and + valueFlowStepSsa(v, pos, e, delta) and + val = remainder(val0 + delta, mod) + ) + or + moduloGuardedRead(v, pos, val, mod) and b instanceof ZeroBound +} + +/** + * Holds if `e` is equal to `b + val` modulo `mod`. + * + * There are two cases for the modulus: + * - `mod = 0`: The equality `e = b + val` is an ordinary equality. + * - `mod > 1`: `val` lies within the range `[0 .. mod-1]`. + */ +cached +predicate exprModulus(Expr e, Bound b, int val, int mod) { + e = b.getExpr(val) and mod = 0 + or + evenlyDivisibleExpr(e, mod) and val = 0 and b instanceof ZeroBound + or + exists(SsaVariable v, SsaReadPositionBlock bb | + ssaModulus(v, bb, b, val, mod) and + e = v.getAUse() and + getABasicBlockExpr(bb.getBlock()) = e + ) + or + exists(Expr mid, int val0, int delta | + exprModulus(mid, b, val0, mod) and + valueFlowStep(e, mid, delta) and + val = remainder(val0 + delta, mod) + ) + or + exists(ConditionalExpr cond, int v1, int v2, int m1, int m2 | + cond = e and + condExprBranchModulus(cond, true, b, v1, m1) and + condExprBranchModulus(cond, false, b, v2, m2) and + mod = m1.gcd(m2).gcd(v1 - v2) and + mod != 1 and + val = remainder(v1, mod) + ) + or + exists(Bound b1, Bound b2, int v1, int v2, int m1, int m2 | + addModulus(e, true, b1, v1, m1) and + addModulus(e, false, b2, v2, m2) and + mod = m1.gcd(m2) and + mod != 1 and + val = remainder(v1 + v2, mod) + | + b = b1 and b2 instanceof ZeroBound + or + b = b2 and b1 instanceof ZeroBound + ) + or + exists(int v1, int v2, int m1, int m2 | + subModulus(e, true, b, v1, m1) and + subModulus(e, false, any(ZeroBound zb), v2, m2) and + mod = m1.gcd(m2) and + mod != 1 and + val = remainder(v1 - v2, mod) + ) +} + +private predicate condExprBranchModulus( + ConditionalExpr cond, boolean branch, Bound b, int val, int mod +) { + exprModulus(cond.getTrueExpr(), b, val, mod) and branch = true + or + exprModulus(cond.getFalseExpr(), b, val, mod) and branch = false +} + +private predicate addModulus(Expr add, boolean isLeft, Bound b, int val, int mod) { + exists(Expr larg, Expr rarg | nonConstAddition(add, larg, rarg) | + exprModulus(larg, b, val, mod) and isLeft = true + or + exprModulus(rarg, b, val, mod) and isLeft = false + ) +} + +private predicate subModulus(Expr sub, boolean isLeft, Bound b, int val, int mod) { + exists(Expr larg, Expr rarg | nonConstSubtraction(sub, larg, rarg) | + exprModulus(larg, b, val, mod) and isLeft = true + or + exprModulus(rarg, b, val, mod) and isLeft = false + ) +} diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ModulusAnalysisSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ModulusAnalysisSpecific.qll new file mode 100644 index 00000000000..2cdbfbf65f4 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/ModulusAnalysisSpecific.qll @@ -0,0 +1,110 @@ +module Private { + private import csharp as CS + private import ConstantUtils as CU + private import semmle.code.csharp.controlflow.Guards as G + private import semmle.code.csharp.dataflow.internal.rangeanalysis.RangeUtils as RU + private import SsaUtils as SU + private import SignAnalysisSpecific::Private as SA + + class BasicBlock = CS::Ssa::BasicBlock; + + class SsaVariable extends CS::Ssa::Definition { + CS::AssignableRead getAUse() { result = this.getARead() } + } + + class SsaPhiNode = CS::Ssa::PhiNode; + + class Expr = CS::Expr; + + class Guard = G::Guard; + + class ConstantIntegerExpr = CU::ConstantIntegerExpr; + + class ConditionalExpr extends CS::ConditionalExpr { + /** Gets the "then" expression of this conditional expression. */ + Expr getTrueExpr() { result = this.getThen() } + + /** Gets the "else" expression of this conditional expression. */ + Expr getFalseExpr() { result = this.getElse() } + } + + /** Represent an addition expression. */ + class AddExpr extends CS::AddExpr { + /** Gets the LHS operand of this add expression. */ + Expr getLhs() { result = this.getLeftOperand() } + + /** Gets the RHS operand of this add expression. */ + Expr getRhs() { result = this.getRightOperand() } + } + + /** Represent a subtraction expression. */ + class SubExpr extends CS::SubExpr { + /** Gets the LHS operand of this subtraction expression. */ + Expr getLhs() { result = this.getLeftOperand() } + + /** Gets the RHS operand of this subtraction expression. */ + Expr getRhs() { result = this.getRightOperand() } + } + + class RemExpr = CS::RemExpr; + + /** Represent a bitwise and or an assign-and expression. */ + class BitwiseAndExpr extends CS::Expr { + BitwiseAndExpr() { this instanceof CS::BitwiseAndExpr or this instanceof CS::AssignAndExpr } + + /** Gets an operand of this bitwise and operation. */ + Expr getAnOperand() { + result = this.(CS::BitwiseAndExpr).getAnOperand() or + result = this.(CS::AssignAndExpr).getRValue() or + result = this.(CS::AssignAndExpr).getLValue() + } + + /** Holds if this expression has operands `e1` and `e2`. */ + predicate hasOperands(Expr e1, Expr e2) { + this.getAnOperand() = e1 and + this.getAnOperand() = e2 and + e1 != e2 + } + } + + /** Represent a multiplication or an assign-mul expression. */ + class MulExpr extends CS::Expr { + MulExpr() { this instanceof CS::MulExpr or this instanceof CS::AssignMulExpr } + + /** Gets an operand of this multiplication. */ + Expr getAnOperand() { + result = this.(CS::MulExpr).getAnOperand() or + result = this.(CS::AssignMulExpr).getRValue() or + result = this.(CS::AssignMulExpr).getLValue() + } + } + + /** Represent a left shift or an assign-lshift expression. */ + class LShiftExpr extends CS::Expr { + LShiftExpr() { this instanceof CS::LShiftExpr or this instanceof CS::AssignLShiftExpr } + + /** Gets the RHS operand of this shift. */ + Expr getRhs() { + result = this.(CS::LShiftExpr).getRightOperand() or + result = this.(CS::AssignLShiftExpr).getRValue() + } + } + + predicate guardDirectlyControlsSsaRead = SA::guardControlsSsaRead/3; + + predicate guardControlsSsaRead = SA::guardControlsSsaRead/3; + + predicate valueFlowStep = RU::valueFlowStep/3; + + predicate eqFlowCond = RU::eqFlowCond/5; + + predicate ssaUpdateStep = RU::ssaUpdateStep/3; + + Expr getABasicBlockExpr(BasicBlock bb) { result = bb.getANode().getElement() } + + private predicate id(CS::ControlFlowElement x, CS::ControlFlowElement y) { x = y } + + private predicate idOf(CS::ControlFlowElement x, int y) = equivalenceRelation(id/2)(x, y) + + int getId(BasicBlock bb) { idOf(bb.getFirstNode().getElement(), result) } +} diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll new file mode 100644 index 00000000000..4abfb2d1779 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll @@ -0,0 +1,98 @@ +/** + * Provides predicates for range and modulus analysis. + */ + +private import csharp +private import Ssa +private import SsaUtils +private import ConstantUtils +private import SsaReadPositionCommon +private import semmle.code.csharp.controlflow.Guards as G + +private class BooleanValue = G::AbstractValues::BooleanValue; + +/** + * Holds if `v` is an `ExplicitDefinition` that equals `e + delta`. + */ +predicate ssaUpdateStep(ExplicitDefinition v, Expr e, int delta) { + v.getADefinition().getExpr().(Assignment).getRValue() = e and delta = 0 + or + v.getADefinition().getExpr().(PostIncrExpr).getOperand() = e and delta = 1 + or + v.getADefinition().getExpr().(PreIncrExpr).getOperand() = e and delta = 1 + or + v.getADefinition().getExpr().(PostDecrExpr).getOperand() = e and delta = -1 + or + v.getADefinition().getExpr().(PreDecrExpr).getOperand() = e and delta = -1 +} + +private G::Guard eqFlowCondAbs(Definition def, Expr e, int delta, boolean isEq, G::AbstractValue v) { + exists(boolean eqpolarity | + result.isEquality(ssaRead(def, delta), e, eqpolarity) and + eqpolarity.booleanXor(v.(BooleanValue).getValue()).booleanNot() = isEq + ) + or + exists(G::AbstractValue v0 | + G::Internal::impliesSteps(result, v, eqFlowCondAbs(def, e, delta, isEq, v0), v0) + ) +} + +/** + * Gets a condition that tests whether `def` equals `e + delta`. + * + * If the condition evaluates to `testIsTrue`: + * - `isEq = true` : `def == e + delta` + * - `isEq = false` : `def != e + delta` + */ +G::Guard eqFlowCond(Definition def, Expr e, int delta, boolean isEq, boolean testIsTrue) { + exists(BooleanValue v | + result = eqFlowCondAbs(def, e, delta, isEq, v) and + testIsTrue = v.getValue() + ) +} + +/** + * Holds if `e1 + delta` equals `e2`. + */ +predicate valueFlowStep(Expr e2, Expr e1, int delta) { + valueFlowStep(e2.(AssignOperation).getExpandedAssignment(), e1, delta) + or + e2.(AssignExpr).getRValue() = e1 and delta = 0 + or + e2.(UnaryPlusExpr).getOperand() = e1 and delta = 0 + or + e2.(PostIncrExpr).getOperand() = e1 and delta = 0 + or + e2.(PostDecrExpr).getOperand() = e1 and delta = 0 + or + e2.(PreIncrExpr).getOperand() = e1 and delta = 1 + or + e2.(PreDecrExpr).getOperand() = e1 and delta = -1 + or + exists(ConstantIntegerExpr x | + e2.(AddExpr).getAnOperand() = e1 and + e2.(AddExpr).getAnOperand() = x and + not e1 = x + | + x.getIntValue() = delta + ) + or + exists(ConstantIntegerExpr x | + exists(SubExpr sub | + e2 = sub and + sub.getLeftOperand() = e1 and + sub.getRightOperand() = x + ) + | + x.getIntValue() = -delta + ) +} + +/** + * Holds if `guard` controls the position `controlled` with the value `testIsTrue`. + */ +predicate guardControlsSsaRead(G::Guard guard, SsaReadPosition controlled, boolean testIsTrue) { + exists(BooleanValue b | b.getValue() = testIsTrue | + guard.controlsBasicBlock(controlled.(SsaReadPositionBlock).getBlock(), b) + ) +} diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index 813834c3fd8..9893ebc5dad 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -2,9 +2,10 @@ * Provides C#-specific definitions for use in sign analysis. */ module Private { - private import SsaUtils as SU private import csharp as CS + private import SsaUtils as SU private import ConstantUtils as CU + private import RangeUtils as RU private import semmle.code.csharp.controlflow.Guards as G import Impl @@ -33,6 +34,8 @@ module Private { class Expr = CS::Expr; predicate ssaRead = SU::ssaRead/2; + + predicate guardControlsSsaRead = RU::guardControlsSsaRead/3; } private module Impl { @@ -254,15 +257,6 @@ private module Impl { Guard getComparisonGuard(ComparisonExpr ce) { result = ce.getExpr() } - /** - * Holds if `guard` controls the position `controlled` with the value `testIsTrue`. - */ - predicate guardControlsSsaRead(Guard guard, SsaReadPosition controlled, boolean testIsTrue) { - exists(BooleanValue b | b.getValue() = testIsTrue | - guard.controlsBasicBlock(controlled.(SsaReadPositionBlock).getBlock(), b) - ) - } - /** A relational comparison */ class ComparisonExpr extends ComparisonTest { private boolean strict; diff --git a/csharp/ql/test/library-tests/dataflow/modulusanalysis/ModulusAnalysis.cs b/csharp/ql/test/library-tests/dataflow/modulusanalysis/ModulusAnalysis.cs new file mode 100644 index 00000000000..8c55e74372b --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/modulusanalysis/ModulusAnalysis.cs @@ -0,0 +1,84 @@ +using System; +using System.Linq; + +class ModulusAnalysis +{ + const int c1 = 42; + const int c2 = 43; + + void M(int i, bool cond, int x, int y, int[] arr, int otherSeven) + { + var eq = i + 3; + + var mul = eq * c1 + 3; // congruent 3 mod 42 + + int seven = 7; + if (mul % c2 == seven) + { + System.Console.WriteLine(mul); // congruent 7 mod 43, 3 mod 42 + } + + if (otherSeven == 7) + { + if (mul % c2 == otherSeven) + { + System.Console.WriteLine(mul); // congruent 3 mod 42, 7 mod 43 missing + } + } + + var j = cond + ? i * 4 + 3 + : i * 8 + 7; + System.Console.WriteLine(j); // congruent 3 mod 4 + + if (x % c1 == 3 && y % c1 == 7) + { + System.Console.WriteLine(x + y); // congruent 10 mod 42 + } + + if (x % c1 == 3 && y % c1 == 7) + { + System.Console.WriteLine(x - y); // congruent 38 mod 42 + } + + var l = arr.Length * 4 - 11; // congruent 1 mod 4 + System.Console.WriteLine(l); + + l = GetArray().Length * 4 - 11; + System.Console.WriteLine(l); // congruent 1 mod 4 + + if (cond) + { + j = i * 4 + 3; + } + else + { + j = i * 8 + 7; + } + System.Console.WriteLine(j); // congruent 3 mod 4 or 7 mod 8 + + if (cond) + { + System.Console.WriteLine(j); // congruent 3 mod 4 + } + else + { + System.Console.WriteLine(j); // congruent 7 mod 8 + } + + var t = 64; + System.Console.WriteLine(t & 32); // congruent 0 mod 32 + System.Console.WriteLine(t & 16); // congruent 0 mod 16 + t = 1; + System.Console.WriteLine(t << 2); // congruent 0 mod 4 + + if ((x & 15) == 3) + { + System.Console.WriteLine(x); // congruent 3 mod 16 + } + } + + + + int[] GetArray(){ return new int[42]; } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/dataflow/modulusanalysis/ModulusAnalysis.expected b/csharp/ql/test/library-tests/dataflow/modulusanalysis/ModulusAnalysis.expected new file mode 100644 index 00000000000..c7bacd76943 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/modulusanalysis/ModulusAnalysis.expected @@ -0,0 +1,138 @@ +| ModulusAnalysis.cs:6:15:6:21 | ... = ... | 0 | 42 | 0 | +| ModulusAnalysis.cs:6:20:6:21 | 42 | 0 | 42 | 0 | +| ModulusAnalysis.cs:7:15:7:21 | ... = ... | 0 | 43 | 0 | +| ModulusAnalysis.cs:7:20:7:21 | 43 | 0 | 43 | 0 | +| ModulusAnalysis.cs:11:18:11:18 | access to parameter i | SSA param(i) | 0 | 0 | +| ModulusAnalysis.cs:11:18:11:22 | ... + ... | SSA param(i) | 3 | 0 | +| ModulusAnalysis.cs:11:22:11:22 | 3 | 0 | 3 | 0 | +| ModulusAnalysis.cs:13:19:13:20 | access to local variable eq | SSA def(eq) | 0 | 0 | +| ModulusAnalysis.cs:13:19:13:20 | access to local variable eq | SSA param(i) | 3 | 0 | +| ModulusAnalysis.cs:13:19:13:25 | ... * ... | 0 | 0 | 42 | +| ModulusAnalysis.cs:13:19:13:29 | ... + ... | 0 | 3 | 42 | +| ModulusAnalysis.cs:13:24:13:25 | access to constant c1 | 0 | 42 | 0 | +| ModulusAnalysis.cs:13:24:13:25 | access to constant c1 | SSA entry def(ModulusAnalysis.c1) | 0 | 0 | +| ModulusAnalysis.cs:13:29:13:29 | 3 | 0 | 3 | 0 | +| ModulusAnalysis.cs:15:21:15:21 | 7 | 0 | 7 | 0 | +| ModulusAnalysis.cs:16:13:16:15 | access to local variable mul | 0 | 3 | 42 | +| ModulusAnalysis.cs:16:13:16:15 | access to local variable mul | SSA def(mul) | 0 | 0 | +| ModulusAnalysis.cs:16:19:16:20 | access to constant c2 | 0 | 43 | 0 | +| ModulusAnalysis.cs:16:19:16:20 | access to constant c2 | SSA entry def(ModulusAnalysis.c2) | 0 | 0 | +| ModulusAnalysis.cs:16:25:16:29 | access to local variable seven | 0 | 7 | 0 | +| ModulusAnalysis.cs:16:25:16:29 | access to local variable seven | SSA def(seven) | 0 | 0 | +| ModulusAnalysis.cs:18:38:18:40 | access to local variable mul | 0 | 3 | 42 | +| ModulusAnalysis.cs:18:38:18:40 | access to local variable mul | 0 | 7 | 43 | +| ModulusAnalysis.cs:18:38:18:40 | access to local variable mul | SSA def(mul) | 0 | 0 | +| ModulusAnalysis.cs:21:13:21:22 | access to parameter otherSeven | SSA param(otherSeven) | 0 | 0 | +| ModulusAnalysis.cs:21:27:21:27 | 7 | 0 | 7 | 0 | +| ModulusAnalysis.cs:23:17:23:19 | access to local variable mul | 0 | 3 | 42 | +| ModulusAnalysis.cs:23:17:23:19 | access to local variable mul | SSA def(mul) | 0 | 0 | +| ModulusAnalysis.cs:23:23:23:24 | access to constant c2 | 0 | 43 | 0 | +| ModulusAnalysis.cs:23:23:23:24 | access to constant c2 | SSA entry def(ModulusAnalysis.c2) | 0 | 0 | +| ModulusAnalysis.cs:23:29:23:38 | access to parameter otherSeven | 0 | 7 | 0 | +| ModulusAnalysis.cs:23:29:23:38 | access to parameter otherSeven | SSA param(otherSeven) | 0 | 0 | +| ModulusAnalysis.cs:25:42:25:44 | access to local variable mul | 0 | 3 | 42 | +| ModulusAnalysis.cs:25:42:25:44 | access to local variable mul | SSA def(mul) | 0 | 0 | +| ModulusAnalysis.cs:29:17:31:23 | ... ? ... : ... | 0 | 3 | 4 | +| ModulusAnalysis.cs:30:15:30:15 | access to parameter i | SSA param(i) | 0 | 0 | +| ModulusAnalysis.cs:30:15:30:19 | ... * ... | 0 | 0 | 4 | +| ModulusAnalysis.cs:30:15:30:23 | ... + ... | 0 | 3 | 4 | +| ModulusAnalysis.cs:30:19:30:19 | 4 | 0 | 4 | 0 | +| ModulusAnalysis.cs:30:23:30:23 | 3 | 0 | 3 | 0 | +| ModulusAnalysis.cs:31:15:31:15 | access to parameter i | SSA param(i) | 0 | 0 | +| ModulusAnalysis.cs:31:15:31:19 | ... * ... | 0 | 0 | 8 | +| ModulusAnalysis.cs:31:15:31:23 | ... + ... | 0 | 7 | 8 | +| ModulusAnalysis.cs:31:19:31:19 | 8 | 0 | 8 | 0 | +| ModulusAnalysis.cs:31:23:31:23 | 7 | 0 | 7 | 0 | +| ModulusAnalysis.cs:32:34:32:34 | access to local variable j | 0 | 3 | 4 | +| ModulusAnalysis.cs:32:34:32:34 | access to local variable j | [cond (line 9): false] SSA def(j) | 0 | 0 | +| ModulusAnalysis.cs:32:34:32:34 | access to local variable j | [cond (line 9): true] SSA def(j) | 0 | 0 | +| ModulusAnalysis.cs:34:13:34:13 | access to parameter x | SSA param(x) | 0 | 0 | +| ModulusAnalysis.cs:34:17:34:18 | access to constant c1 | 0 | 42 | 0 | +| ModulusAnalysis.cs:34:17:34:18 | access to constant c1 | SSA entry def(ModulusAnalysis.c1) | 0 | 0 | +| ModulusAnalysis.cs:34:23:34:23 | 3 | 0 | 3 | 0 | +| ModulusAnalysis.cs:34:28:34:28 | access to parameter y | SSA param(y) | 0 | 0 | +| ModulusAnalysis.cs:34:32:34:33 | access to constant c1 | 0 | 42 | 0 | +| ModulusAnalysis.cs:34:32:34:33 | access to constant c1 | SSA entry def(ModulusAnalysis.c1) | 0 | 0 | +| ModulusAnalysis.cs:34:38:34:38 | 7 | 0 | 7 | 0 | +| ModulusAnalysis.cs:36:38:36:38 | access to parameter x | 0 | 3 | 42 | +| ModulusAnalysis.cs:36:38:36:38 | access to parameter x | SSA param(x) | 0 | 0 | +| ModulusAnalysis.cs:36:38:36:42 | ... + ... | 0 | 10 | 42 | +| ModulusAnalysis.cs:36:38:36:42 | ... + ... | SSA param(x) | 7 | 42 | +| ModulusAnalysis.cs:36:38:36:42 | ... + ... | SSA param(y) | 3 | 42 | +| ModulusAnalysis.cs:36:42:36:42 | access to parameter y | 0 | 7 | 42 | +| ModulusAnalysis.cs:36:42:36:42 | access to parameter y | SSA param(y) | 0 | 0 | +| ModulusAnalysis.cs:39:13:39:13 | access to parameter x | SSA param(x) | 0 | 0 | +| ModulusAnalysis.cs:39:17:39:18 | access to constant c1 | 0 | 42 | 0 | +| ModulusAnalysis.cs:39:17:39:18 | access to constant c1 | SSA entry def(ModulusAnalysis.c1) | 0 | 0 | +| ModulusAnalysis.cs:39:23:39:23 | 3 | 0 | 3 | 0 | +| ModulusAnalysis.cs:39:28:39:28 | access to parameter y | SSA param(y) | 0 | 0 | +| ModulusAnalysis.cs:39:32:39:33 | access to constant c1 | 0 | 42 | 0 | +| ModulusAnalysis.cs:39:32:39:33 | access to constant c1 | SSA entry def(ModulusAnalysis.c1) | 0 | 0 | +| ModulusAnalysis.cs:39:38:39:38 | 7 | 0 | 7 | 0 | +| ModulusAnalysis.cs:41:38:41:38 | access to parameter x | 0 | 3 | 42 | +| ModulusAnalysis.cs:41:38:41:38 | access to parameter x | SSA param(x) | 0 | 0 | +| ModulusAnalysis.cs:41:38:41:42 | ... - ... | 0 | 38 | 42 | +| ModulusAnalysis.cs:41:38:41:42 | ... - ... | SSA param(x) | 35 | 42 | +| ModulusAnalysis.cs:41:42:41:42 | access to parameter y | 0 | 7 | 42 | +| ModulusAnalysis.cs:41:42:41:42 | access to parameter y | SSA param(y) | 0 | 0 | +| ModulusAnalysis.cs:44:17:44:26 | access to property Length | [cond (line 9): false] SSA untracked def(arr.Length) | 0 | 0 | +| ModulusAnalysis.cs:44:17:44:26 | access to property Length | [cond (line 9): true] SSA untracked def(arr.Length) | 0 | 0 | +| ModulusAnalysis.cs:44:17:44:30 | ... * ... | 0 | 0 | 4 | +| ModulusAnalysis.cs:44:17:44:35 | ... - ... | 0 | 1 | 4 | +| ModulusAnalysis.cs:44:30:44:30 | 4 | 0 | 4 | 0 | +| ModulusAnalysis.cs:44:34:44:35 | 11 | 0 | 11 | 0 | +| ModulusAnalysis.cs:45:34:45:34 | access to local variable l | 0 | 1 | 4 | +| ModulusAnalysis.cs:45:34:45:34 | access to local variable l | [cond (line 9): false] SSA def(l) | 0 | 0 | +| ModulusAnalysis.cs:45:34:45:34 | access to local variable l | [cond (line 9): true] SSA def(l) | 0 | 0 | +| ModulusAnalysis.cs:47:9:47:38 | ... = ... | 0 | 1 | 4 | +| ModulusAnalysis.cs:47:13:47:29 | access to property Length | access to property Length | 0 | 0 | +| ModulusAnalysis.cs:47:13:47:33 | ... * ... | 0 | 0 | 4 | +| ModulusAnalysis.cs:47:13:47:38 | ... - ... | 0 | 1 | 4 | +| ModulusAnalysis.cs:47:33:47:33 | 4 | 0 | 4 | 0 | +| ModulusAnalysis.cs:47:37:47:38 | 11 | 0 | 11 | 0 | +| ModulusAnalysis.cs:48:34:48:34 | access to local variable l | 0 | 1 | 4 | +| ModulusAnalysis.cs:48:34:48:34 | access to local variable l | [cond (line 9): false] SSA def(l) | 0 | 0 | +| ModulusAnalysis.cs:48:34:48:34 | access to local variable l | [cond (line 9): true] SSA def(l) | 0 | 0 | +| ModulusAnalysis.cs:52:13:52:25 | ... = ... | 0 | 3 | 4 | +| ModulusAnalysis.cs:52:17:52:17 | access to parameter i | SSA param(i) | 0 | 0 | +| ModulusAnalysis.cs:52:17:52:21 | ... * ... | 0 | 0 | 4 | +| ModulusAnalysis.cs:52:17:52:25 | ... + ... | 0 | 3 | 4 | +| ModulusAnalysis.cs:52:21:52:21 | 4 | 0 | 4 | 0 | +| ModulusAnalysis.cs:52:25:52:25 | 3 | 0 | 3 | 0 | +| ModulusAnalysis.cs:56:13:56:25 | ... = ... | 0 | 7 | 8 | +| ModulusAnalysis.cs:56:17:56:17 | access to parameter i | SSA param(i) | 0 | 0 | +| ModulusAnalysis.cs:56:17:56:21 | ... * ... | 0 | 0 | 8 | +| ModulusAnalysis.cs:56:17:56:25 | ... + ... | 0 | 7 | 8 | +| ModulusAnalysis.cs:56:21:56:21 | 8 | 0 | 8 | 0 | +| ModulusAnalysis.cs:56:25:56:25 | 7 | 0 | 7 | 0 | +| ModulusAnalysis.cs:58:34:58:34 | access to local variable j | 0 | 3 | 4 | +| ModulusAnalysis.cs:58:34:58:34 | access to local variable j | 0 | 7 | 8 | +| ModulusAnalysis.cs:58:34:58:34 | access to local variable j | [cond (line 9): false] SSA def(j) | 0 | 0 | +| ModulusAnalysis.cs:58:34:58:34 | access to local variable j | [cond (line 9): true] SSA def(j) | 0 | 0 | +| ModulusAnalysis.cs:62:38:62:38 | access to local variable j | 0 | 3 | 4 | +| ModulusAnalysis.cs:62:38:62:38 | access to local variable j | [cond (line 9): true] SSA def(j) | 0 | 0 | +| ModulusAnalysis.cs:66:38:66:38 | access to local variable j | 0 | 7 | 8 | +| ModulusAnalysis.cs:66:38:66:38 | access to local variable j | [cond (line 9): false] SSA def(j) | 0 | 0 | +| ModulusAnalysis.cs:69:17:69:18 | 64 | 0 | 64 | 0 | +| ModulusAnalysis.cs:70:34:70:34 | access to local variable t | 0 | 64 | 0 | +| ModulusAnalysis.cs:70:34:70:34 | access to local variable t | SSA def(t) | 0 | 0 | +| ModulusAnalysis.cs:70:34:70:39 | ... & ... | 0 | 0 | 32 | +| ModulusAnalysis.cs:70:34:70:39 | ... & ... | 0 | 0 | 64 | +| ModulusAnalysis.cs:70:38:70:39 | 32 | 0 | 32 | 0 | +| ModulusAnalysis.cs:71:34:71:34 | access to local variable t | 0 | 64 | 0 | +| ModulusAnalysis.cs:71:34:71:34 | access to local variable t | SSA def(t) | 0 | 0 | +| ModulusAnalysis.cs:71:34:71:39 | ... & ... | 0 | 0 | 16 | +| ModulusAnalysis.cs:71:34:71:39 | ... & ... | 0 | 0 | 64 | +| ModulusAnalysis.cs:71:38:71:39 | 16 | 0 | 16 | 0 | +| ModulusAnalysis.cs:72:9:72:13 | ... = ... | 0 | 1 | 0 | +| ModulusAnalysis.cs:72:13:72:13 | 1 | 0 | 1 | 0 | +| ModulusAnalysis.cs:73:34:73:34 | access to local variable t | 0 | 1 | 0 | +| ModulusAnalysis.cs:73:34:73:34 | access to local variable t | SSA def(t) | 0 | 0 | +| ModulusAnalysis.cs:73:34:73:39 | ... << ... | 0 | 0 | 4 | +| ModulusAnalysis.cs:73:39:73:39 | 2 | 0 | 2 | 0 | +| ModulusAnalysis.cs:75:14:75:14 | access to parameter x | SSA param(x) | 0 | 0 | +| ModulusAnalysis.cs:75:18:75:19 | 15 | 0 | 15 | 0 | +| ModulusAnalysis.cs:75:25:75:25 | 3 | 0 | 3 | 0 | +| ModulusAnalysis.cs:77:38:77:38 | access to parameter x | 0 | 3 | 16 | +| ModulusAnalysis.cs:77:38:77:38 | access to parameter x | SSA param(x) | 0 | 0 | +| ModulusAnalysis.cs:83:38:83:39 | 42 | 0 | 42 | 0 | diff --git a/csharp/ql/test/library-tests/dataflow/modulusanalysis/ModulusAnalysis.ql b/csharp/ql/test/library-tests/dataflow/modulusanalysis/ModulusAnalysis.ql new file mode 100644 index 00000000000..f92649fa5b2 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/modulusanalysis/ModulusAnalysis.ql @@ -0,0 +1,7 @@ +import csharp +import semmle.code.csharp.dataflow.ModulusAnalysis +import semmle.code.csharp.dataflow.Bound + +from Expr e, Bound b, int delta, int mod +where exprModulus(e, b, delta, mod) +select e, b.toString(), delta, mod diff --git a/java/ql/src/semmle/code/java/dataflow/ModulusAnalysis.qll b/java/ql/src/semmle/code/java/dataflow/ModulusAnalysis.qll index 012a1ccf5de..2b3c3402415 100644 --- a/java/ql/src/semmle/code/java/dataflow/ModulusAnalysis.qll +++ b/java/ql/src/semmle/code/java/dataflow/ModulusAnalysis.qll @@ -4,12 +4,9 @@ * variable), and `v` is an integer in the range `[0 .. m-1]`. */ -import java -private import SSA -private import semmle.code.java.dataflow.internal.rangeanalysis.SsaReadPositionCommon -private import RangeUtils -private import semmle.code.java.controlflow.Guards -import Bound +private import internal.rangeanalysis.ModulusAnalysisSpecific::Private +private import Bound +private import internal.rangeanalysis.SsaReadPositionCommon /** * Holds if `e + delta` equals `v` at `pos`. @@ -29,16 +26,9 @@ private predicate valueFlowStepSsa(SsaVariable v, SsaReadPosition pos, Expr e, i * `ConstantIntegerExpr`s. */ private predicate nonConstAddition(Expr add, Expr larg, Expr rarg) { - ( - exists(AddExpr a | a = add | - larg = a.getLeftOperand() and - rarg = a.getRightOperand() - ) - or - exists(AssignAddExpr a | a = add | - larg = a.getDest() and - rarg = a.getRhs() - ) + exists(AddExpr a | a = add | + larg = a.getLhs() and + rarg = a.getRhs() ) and not larg instanceof ConstantIntegerExpr and not rarg instanceof ConstantIntegerExpr @@ -49,16 +39,9 @@ private predicate nonConstAddition(Expr add, Expr larg, Expr rarg) { * a `ConstantIntegerExpr`. */ private predicate nonConstSubtraction(Expr sub, Expr larg, Expr rarg) { - ( - exists(SubExpr s | s = sub | - larg = s.getLeftOperand() and - rarg = s.getRightOperand() - ) - or - exists(AssignSubExpr s | s = sub | - larg = s.getDest() and - rarg = s.getRhs() - ) + exists(SubExpr s | s = sub | + larg = s.getLhs() and + rarg = s.getRhs() ) and not rarg instanceof ConstantIntegerExpr } @@ -75,7 +58,7 @@ private Expr modExpr(Expr arg, int mod) { exists(ConstantIntegerExpr c | mod = 2.pow([1 .. 30]) and c.getIntValue() = mod - 1 and - result.(AndBitwiseExpr).hasOperands(arg, c) + result.(BitwiseAndExpr).hasOperands(arg, c) ) } @@ -122,24 +105,12 @@ private predicate evenlyDivisibleExpr(Expr e, int factor) { exists(ConstantIntegerExpr c, int k | k = c.getIntValue() | e.(MulExpr).getAnOperand() = c and factor = k.abs() and factor >= 2 or - e.(AssignMulExpr).getSource() = c and factor = k.abs() and factor >= 2 + e.(LShiftExpr).getRhs() = c and factor = 2.pow(k) and k > 0 or - e.(LShiftExpr).getRightOperand() = c and factor = 2.pow(k) and k > 0 - or - e.(AssignLShiftExpr).getRhs() = c and factor = 2.pow(k) and k > 0 - or - e.(AndBitwiseExpr).getAnOperand() = c and factor = max(int f | andmaskFactor(k, f)) - or - e.(AssignAndExpr).getSource() = c and factor = max(int f | andmaskFactor(k, f)) + e.(BitwiseAndExpr).getAnOperand() = c and factor = max(int f | andmaskFactor(k, f)) ) } -private predicate id(BasicBlock x, BasicBlock y) { x = y } - -private predicate idOf(BasicBlock x, int y) = equivalenceRelation(id/2)(x, y) - -private int getId(BasicBlock bb) { idOf(bb, result) } - /** * Holds if `inp` is an input to `phi` along `edge` and this input has index `r` * in an arbitrary 1-based numbering of the input edges to `phi`. @@ -267,7 +238,7 @@ predicate exprModulus(Expr e, Bound b, int val, int mod) { exists(SsaVariable v, SsaReadPositionBlock bb | ssaModulus(v, bb, b, val, mod) and e = v.getAUse() and - bb.getBlock() = e.getBasicBlock() + getABasicBlockExpr(bb.getBlock()) = e ) or exists(Expr mid, int val0, int delta | diff --git a/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/ModulusAnalysisSpecific.qll b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/ModulusAnalysisSpecific.qll new file mode 100644 index 00000000000..374cb102e0a --- /dev/null +++ b/java/ql/src/semmle/code/java/dataflow/internal/rangeanalysis/ModulusAnalysisSpecific.qll @@ -0,0 +1,119 @@ +module Private { + private import java as J + private import semmle.code.java.dataflow.SSA as Ssa + private import semmle.code.java.dataflow.RangeUtils as RU + private import semmle.code.java.controlflow.Guards as G + private import semmle.code.java.controlflow.BasicBlocks as BB + + class BasicBlock = BB::BasicBlock; + + class SsaVariable = Ssa::SsaVariable; + + class SsaPhiNode = Ssa::SsaPhiNode; + + class Expr = J::Expr; + + class Guard = G::Guard; + + class ConstantIntegerExpr = RU::ConstantIntegerExpr; + + class ConditionalExpr = J::ConditionalExpr; + + /** An addition or an assign-add expression. */ + class AddExpr extends J::Expr { + AddExpr() { this instanceof J::AddExpr or this instanceof J::AssignAddExpr } + + /** Gets the LHS operand of this add expression. */ + Expr getLhs() { + result = this.(J::AddExpr).getLeftOperand() + or + result = this.(J::AssignAddExpr).getDest() + } + + /** Gets the RHS operand of this add expression. */ + Expr getRhs() { + result = this.(J::AddExpr).getRightOperand() + or + result = this.(J::AssignAddExpr).getRhs() + } + } + + /** A subtraction or an assign-sub expression. */ + class SubExpr extends J::Expr { + SubExpr() { this instanceof J::SubExpr or this instanceof J::AssignSubExpr } + + /** Gets the LHS operand of this subtraction expression. */ + Expr getLhs() { + result = this.(J::SubExpr).getLeftOperand() + or + result = this.(J::AssignSubExpr).getDest() + } + + /** Gets the RHS operand of this subtraction expression. */ + Expr getRhs() { + result = this.(J::SubExpr).getRightOperand() + or + result = this.(J::AssignSubExpr).getRhs() + } + } + + class RemExpr = J::RemExpr; + + /** A multiplication or an assign-mul expression. */ + class MulExpr extends J::Expr { + MulExpr() { this instanceof J::MulExpr or this instanceof J::AssignMulExpr } + + /** Gets an operand of this multiplication. */ + Expr getAnOperand() { + result = this.(J::MulExpr).getAnOperand() or + result = this.(J::AssignMulExpr).getSource() + } + } + + /** A left shift or an assign-lshift expression. */ + class LShiftExpr extends J::Expr { + LShiftExpr() { this instanceof J::LShiftExpr or this instanceof J::AssignLShiftExpr } + + /** Gets the RHS operand of this shift. */ + Expr getRhs() { + result = this.(J::LShiftExpr).getRightOperand() or + result = this.(J::AssignLShiftExpr).getRhs() + } + } + + /** A bitwise and or an assign-and expression. */ + class BitwiseAndExpr extends J::Expr { + BitwiseAndExpr() { this instanceof J::AndBitwiseExpr or this instanceof J::AssignAndExpr } + + /** Gets an operand of this bitwise and operation. */ + Expr getAnOperand() { + result = this.(J::AndBitwiseExpr).getAnOperand() or + result = this.(J::AssignAndExpr).getSource() + } + + /** Holds if this expression has operands `e1` and `e2`. */ + predicate hasOperands(Expr e1, Expr e2) { + this.getAnOperand() = e1 and + this.getAnOperand() = e2 and + e1 != e2 + } + } + + predicate guardDirectlyControlsSsaRead = RU::guardDirectlyControlsSsaRead/3; + + predicate guardControlsSsaRead = RU::guardControlsSsaRead/3; + + predicate valueFlowStep = RU::valueFlowStep/3; + + predicate eqFlowCond = RU::eqFlowCond/5; + + predicate ssaUpdateStep = RU::ssaUpdateStep/3; + + Expr getABasicBlockExpr(BasicBlock bb) { result = bb.getANode() } + + private predicate id(BasicBlock x, BasicBlock y) { x = y } + + private predicate idOf(BasicBlock x, int y) = equivalenceRelation(id/2)(x, y) + + int getId(BasicBlock bb) { idOf(bb, result) } +} From 9c503c159159ae40288a1e2b69442a8132dfc908 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 7 Oct 2020 16:58:55 +0200 Subject: [PATCH 285/411] C#: Add more data/control-flow tests --- .../controlflow/graph/BasicBlock.expected | 52 +- .../controlflow/graph/Condition.expected | 92 +-- .../controlflow/graph/Conditions.cs | 13 +- .../controlflow/graph/Dominance.expected | 579 +++++++++++------- .../graph/EnclosingCallable.expected | 185 ++++-- .../controlflow/graph/EntryElement.expected | 138 +++-- .../controlflow/graph/ExitElement.expected | 249 +++++--- .../controlflow/graph/NodeGraph.expected | 205 ++++--- .../controlflow/graph/Nodes.expected | 10 + .../library-tests/controlflow/graph/Switch.cs | 51 +- .../dataflow/global/DataFlow.expected | 2 + .../dataflow/global/DataFlowPath.expected | 7 + .../dataflow/global/Splitting.cs | 18 + .../dataflow/global/TaintTracking.expected | 2 + .../global/TaintTrackingPath.expected | 7 + 15 files changed, 1025 insertions(+), 585 deletions(-) diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index d7ca5bdd073..d19f5bf1d34 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -139,7 +139,7 @@ | Conditions.cs:77:17:77:20 | ...; | Conditions.cs:77:17:77:19 | ...++ | 3 | | Conditions.cs:78:13:79:26 | if (...) ... | Conditions.cs:78:17:78:21 | ... > ... | 4 | | Conditions.cs:79:17:79:26 | ...; | Conditions.cs:79:17:79:25 | ... = ... | 3 | -| Conditions.cs:81:9:82:16 | if (...) ... | Conditions.cs:81:12:81:12 | access to local variable b | 2 | +| Conditions.cs:81:9:82:16 | if (...) ... | Conditions.cs:81:13:81:13 | access to local variable b | 2 | | Conditions.cs:82:13:82:16 | ...; | Conditions.cs:82:13:82:15 | ...++ | 3 | | Conditions.cs:83:16:83:16 | access to local variable x | Conditions.cs:70:9:70:10 | exit M6 | 3 | | Conditions.cs:86:9:86:10 | enter M7 | Conditions.cs:90:27:90:28 | access to parameter ss | 12 | @@ -157,10 +157,10 @@ | Conditions.cs:108:13:109:24 | [b (line 102): false] if (...) ... | Conditions.cs:109:17:109:23 | ... = ... | 8 | | Conditions.cs:108:13:109:24 | [b (line 102): true] if (...) ... | Conditions.cs:108:18:108:18 | [b (line 102): true] access to parameter b | 3 | | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:102:12:102:13 | exit M8 | 3 | -| Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:116:17:116:21 | Int32 i = ... | 8 | +| Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:116:18:116:22 | Int32 i = ... | 8 | | Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:113:10:113:11 | exit M9 | 1 | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:24:116:38 | ... < ... | 4 | -| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:116:41:116:43 | ...++ | 2 | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:116:25:116:39 | ... < ... | 4 | +| Conditions.cs:116:42:116:42 | access to local variable i | Conditions.cs:116:42:116:44 | ...++ | 2 | | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:119:18:119:21 | access to local variable last | 12 | | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | 5 | | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | Conditions.cs:122:17:122:24 | ... = ... | 5 | @@ -169,6 +169,10 @@ | Conditions.cs:131:16:131:19 | [Field1 (line 129): true, Field2 (line 129): false] true | Conditions.cs:135:21:135:26 | [Field1 (line 129): true, Field2 (line 129): false] access to field Field2 | 9 | | Conditions.cs:134:13:139:13 | [Field1 (line 129): true] {...} | Conditions.cs:135:21:135:26 | [Field1 (line 129): true] access to field Field2 | 4 | | Conditions.cs:136:17:138:17 | [Field1 (line 129): true, Field2 (line 129): true] {...} | Conditions.cs:135:21:135:26 | [Field1 (line 129): true, Field2 (line 129): true] access to field Field2 | 14 | +| Conditions.cs:143:10:143:12 | enter M11 | Conditions.cs:145:17:145:17 | access to parameter b | 5 | +| Conditions.cs:143:10:143:12 | exit M11 | Conditions.cs:143:10:143:12 | exit M11 | 1 | +| Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | Conditions.cs:147:13:147:48 | call to method WriteLine | 9 | +| Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | Conditions.cs:149:13:149:48 | call to method WriteLine | 9 | | ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:7:10:7:11 | exit M1 | 7 | | ExitMethods.cs:13:10:13:11 | enter M2 | ExitMethods.cs:13:10:13:11 | exit M2 | 7 | | ExitMethods.cs:19:10:19:11 | enter M3 | ExitMethods.cs:19:10:19:11 | exit M3 | 6 | @@ -670,35 +674,35 @@ | Switch.cs:55:10:55:11 | enter M5 | Switch.cs:55:10:55:11 | exit M5 | 12 | | Switch.cs:66:10:66:11 | enter M6 | Switch.cs:72:18:72:19 | "" | 9 | | Switch.cs:66:10:66:11 | exit M6 | Switch.cs:66:10:66:11 | exit M6 | 1 | -| Switch.cs:73:15:73:20 | break; | Switch.cs:73:15:73:20 | break; | 1 | +| Switch.cs:73:17:73:22 | break; | Switch.cs:73:17:73:22 | break; | 1 | | Switch.cs:77:10:77:11 | enter M7 | Switch.cs:81:18:81:18 | 1 | 6 | | Switch.cs:77:10:77:11 | exit M7 | Switch.cs:77:10:77:11 | exit M7 | 1 | -| Switch.cs:82:22:82:25 | true | Switch.cs:82:15:82:26 | return ...; | 2 | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:83:18:83:18 | 2 | 2 | -| Switch.cs:84:15:85:22 | if (...) ... | Switch.cs:84:19:84:23 | ... > ... | 4 | -| Switch.cs:85:17:85:22 | break; | Switch.cs:85:17:85:22 | break; | 1 | -| Switch.cs:86:22:86:25 | true | Switch.cs:86:15:86:26 | return ...; | 2 | +| Switch.cs:82:24:82:27 | true | Switch.cs:82:17:82:28 | return ...; | 2 | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:83:18:83:18 | 2 | 2 | +| Switch.cs:84:17:85:26 | if (...) ... | Switch.cs:84:21:84:25 | ... > ... | 4 | +| Switch.cs:85:21:85:26 | break; | Switch.cs:85:21:85:26 | break; | 1 | +| Switch.cs:86:24:86:27 | true | Switch.cs:86:17:86:28 | return ...; | 2 | | Switch.cs:88:16:88:20 | false | Switch.cs:88:9:88:21 | return ...; | 2 | | Switch.cs:91:10:91:11 | enter M8 | Switch.cs:95:18:95:20 | access to type Int32 | 6 | | Switch.cs:91:10:91:11 | exit M8 | Switch.cs:91:10:91:11 | exit M8 | 1 | -| Switch.cs:96:22:96:25 | true | Switch.cs:96:15:96:26 | return ...; | 2 | +| Switch.cs:96:24:96:27 | true | Switch.cs:96:17:96:28 | return ...; | 2 | | Switch.cs:98:16:98:20 | false | Switch.cs:98:9:98:21 | return ...; | 2 | | Switch.cs:101:9:101:10 | enter M9 | Switch.cs:103:17:103:17 | access to parameter s | 4 | | Switch.cs:101:9:101:10 | exit M9 | Switch.cs:101:9:101:10 | exit M9 | 1 | | Switch.cs:103:19:103:25 | access to property Length | Switch.cs:103:19:103:25 | access to property Length | 1 | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:105:18:105:18 | 0 | 2 | -| Switch.cs:105:29:105:29 | 0 | Switch.cs:105:22:105:30 | return ...; | 2 | -| Switch.cs:106:13:106:20 | case ...: | Switch.cs:106:18:106:18 | 1 | 2 | -| Switch.cs:106:29:106:29 | 1 | Switch.cs:106:22:106:30 | return ...; | 2 | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:105:18:105:18 | 0 | 2 | +| Switch.cs:105:28:105:28 | 0 | Switch.cs:105:21:105:29 | return ...; | 2 | +| Switch.cs:106:13:106:19 | case ...: | Switch.cs:106:18:106:18 | 1 | 2 | +| Switch.cs:106:28:106:28 | 1 | Switch.cs:106:21:106:29 | return ...; | 2 | | Switch.cs:108:17:108:17 | 1 | Switch.cs:108:9:108:18 | return ...; | 3 | | Switch.cs:111:17:111:21 | enter Throw | Switch.cs:111:17:111:21 | exit Throw | 4 | | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:117:18:117:18 | 3 | 7 | | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:113:9:113:11 | exit M10 | 1 | -| Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:25:117:32 | ... == ... | 3 | -| Switch.cs:117:43:117:43 | 1 | Switch.cs:117:36:117:44 | return ...; | 2 | -| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:18:118:18 | 2 | 2 | -| Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:25:118:31 | ... == ... | 3 | -| Switch.cs:118:42:118:42 | 2 | Switch.cs:118:35:118:43 | return ...; | 2 | +| Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:25:117:34 | ... == ... | 3 | +| Switch.cs:117:44:117:44 | 1 | Switch.cs:117:37:117:45 | return ...; | 2 | +| Switch.cs:118:13:118:34 | case ...: | Switch.cs:118:18:118:18 | 2 | 2 | +| Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:25:118:33 | ... == ... | 3 | +| Switch.cs:118:43:118:43 | 2 | Switch.cs:118:36:118:44 | return ...; | 2 | | Switch.cs:120:17:120:17 | 1 | Switch.cs:120:9:120:18 | return ...; | 3 | | Switch.cs:123:10:123:12 | enter M11 | Switch.cs:125:24:125:29 | Boolean b | 7 | | Switch.cs:123:10:123:12 | exit M11 | Switch.cs:123:10:123:12 | exit M11 | 1 | @@ -722,6 +726,14 @@ | Switch.cs:149:13:149:20 | default: | Switch.cs:149:22:149:31 | return ...; | 4 | | Switch.cs:150:13:150:19 | case ...: | Switch.cs:150:18:150:18 | 2 | 2 | | Switch.cs:150:28:150:28 | 2 | Switch.cs:150:21:150:29 | return ...; | 2 | +| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:156:28:156:31 | true | 7 | +| Switch.cs:154:10:154:12 | exit M15 | Switch.cs:154:10:154:12 | exit M15 | 1 | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:157:13:157:13 | access to parameter b | 3 | +| Switch.cs:156:36:156:38 | "a" | Switch.cs:156:36:156:38 | "a" | 1 | +| Switch.cs:156:41:156:52 | ... => ... | Switch.cs:156:41:156:45 | false | 2 | +| Switch.cs:156:50:156:52 | "b" | Switch.cs:156:50:156:52 | "b" | 1 | +| Switch.cs:158:13:158:49 | ...; | Switch.cs:158:13:158:48 | call to method WriteLine | 5 | +| Switch.cs:160:13:160:49 | ...; | Switch.cs:160:13:160:48 | call to method WriteLine | 5 | | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:7:13:7:22 | ... is ... | 14 | | TypeAccesses.cs:7:25:7:25 | ; | TypeAccesses.cs:7:25:7:25 | ; | 1 | | TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:3:10:3:10 | exit M | 4 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected index ea7fcbfc50f..338db5037e1 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Condition.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Condition.expected @@ -126,11 +126,11 @@ conditionBlock | Conditions.cs:102:12:102:13 | enter M8 | Conditions.cs:108:13:109:24 | [b (line 102): true] if (...) ... | true | | Conditions.cs:106:13:106:20 | [b (line 102): true] ...; | Conditions.cs:108:13:109:24 | [b (line 102): true] if (...) ... | true | | Conditions.cs:107:9:109:24 | [b (line 102): false] if (...) ... | Conditions.cs:108:13:109:24 | [b (line 102): false] if (...) ... | true | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:113:10:113:11 | exit M9 | false | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:41:116:41 | access to local variable i | true | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:117:9:123:9 | {...} | true | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | true | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | true | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:113:10:113:11 | exit M9 | false | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:116:42:116:42 | access to local variable i | true | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:117:9:123:9 | {...} | true | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | true | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | true | | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | false | | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | true | | Conditions.cs:129:10:129:12 | enter M10 | Conditions.cs:131:16:131:19 | [Field1 (line 129): false] true | false | @@ -139,6 +139,8 @@ conditionBlock | Conditions.cs:129:10:129:12 | enter M10 | Conditions.cs:136:17:138:17 | [Field1 (line 129): true, Field2 (line 129): true] {...} | true | | Conditions.cs:134:13:139:13 | [Field1 (line 129): true] {...} | Conditions.cs:131:16:131:19 | [Field1 (line 129): true, Field2 (line 129): false] true | false | | Conditions.cs:134:13:139:13 | [Field1 (line 129): true] {...} | Conditions.cs:136:17:138:17 | [Field1 (line 129): true, Field2 (line 129): true] {...} | true | +| Conditions.cs:143:10:143:12 | enter M11 | Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | true | +| Conditions.cs:143:10:143:12 | enter M11 | Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | false | | ExitMethods.cs:43:9:46:9 | [exception: Exception] catch (...) {...} | ExitMethods.cs:47:9:50:9 | [exception: Exception] catch (...) {...} | false | | ExitMethods.cs:65:17:65:26 | enter ErrorMaybe | ExitMethods.cs:68:19:68:33 | object creation of type Exception | true | | ExitMethods.cs:71:17:71:27 | enter ErrorAlways | ExitMethods.cs:74:19:74:33 | object creation of type Exception | true | @@ -567,33 +569,33 @@ conditionBlock | Switch.cs:50:13:50:39 | case ...: | Switch.cs:50:30:50:30 | access to parameter o | true | | Switch.cs:50:13:50:39 | case ...: | Switch.cs:51:17:51:22 | break; | true | | Switch.cs:50:30:50:30 | access to parameter o | Switch.cs:51:17:51:22 | break; | true | -| Switch.cs:66:10:66:11 | enter M6 | Switch.cs:73:15:73:20 | break; | true | -| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:82:22:82:25 | true | true | -| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:83:13:83:20 | case ...: | false | -| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:84:15:85:22 | if (...) ... | false | -| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:85:17:85:22 | break; | false | -| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:86:22:86:25 | true | false | +| Switch.cs:66:10:66:11 | enter M6 | Switch.cs:73:17:73:22 | break; | true | +| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:82:24:82:27 | true | true | +| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:83:13:83:19 | case ...: | false | +| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:84:17:85:26 | if (...) ... | false | +| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:85:21:85:26 | break; | false | +| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:86:24:86:27 | true | false | | Switch.cs:77:10:77:11 | enter M7 | Switch.cs:88:16:88:20 | false | false | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:84:15:85:22 | if (...) ... | true | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:85:17:85:22 | break; | true | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:86:22:86:25 | true | true | -| Switch.cs:84:15:85:22 | if (...) ... | Switch.cs:85:17:85:22 | break; | true | -| Switch.cs:84:15:85:22 | if (...) ... | Switch.cs:86:22:86:25 | true | false | -| Switch.cs:91:10:91:11 | enter M8 | Switch.cs:96:22:96:25 | true | true | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:84:17:85:26 | if (...) ... | true | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:85:21:85:26 | break; | true | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:86:24:86:27 | true | true | +| Switch.cs:84:17:85:26 | if (...) ... | Switch.cs:85:21:85:26 | break; | true | +| Switch.cs:84:17:85:26 | if (...) ... | Switch.cs:86:24:86:27 | true | false | +| Switch.cs:91:10:91:11 | enter M8 | Switch.cs:96:24:96:27 | true | true | | Switch.cs:91:10:91:11 | enter M8 | Switch.cs:98:16:98:20 | false | false | | Switch.cs:101:9:101:10 | enter M9 | Switch.cs:103:19:103:25 | access to property Length | false | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:105:29:105:29 | 0 | true | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:106:13:106:20 | case ...: | false | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:106:29:106:29 | 1 | false | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:108:17:108:17 | 1 | false | -| Switch.cs:106:13:106:20 | case ...: | Switch.cs:106:29:106:29 | 1 | true | -| Switch.cs:106:13:106:20 | case ...: | Switch.cs:108:17:108:17 | 1 | false | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:105:28:105:28 | 0 | true | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:106:13:106:19 | case ...: | false | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:106:28:106:28 | 1 | false | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:108:17:108:17 | 1 | false | +| Switch.cs:106:13:106:19 | case ...: | Switch.cs:106:28:106:28 | 1 | true | +| Switch.cs:106:13:106:19 | case ...: | Switch.cs:108:17:108:17 | 1 | false | | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:117:25:117:25 | access to parameter s | true | -| Switch.cs:113:9:113:11 | enter M10 | Switch.cs:117:43:117:43 | 1 | true | -| Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:43:117:43 | 1 | true | -| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:25:118:25 | access to parameter s | true | -| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:42:118:42 | 2 | true | -| Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:42:118:42 | 2 | true | +| Switch.cs:113:9:113:11 | enter M10 | Switch.cs:117:44:117:44 | 1 | true | +| Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:44:117:44 | 1 | true | +| Switch.cs:118:13:118:34 | case ...: | Switch.cs:118:25:118:25 | access to parameter s | true | +| Switch.cs:118:13:118:34 | case ...: | Switch.cs:118:43:118:43 | 2 | true | +| Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:43:118:43 | 2 | true | | Switch.cs:123:10:123:12 | enter M11 | Switch.cs:125:34:125:34 | access to local variable b | true | | Switch.cs:123:10:123:12 | enter M11 | Switch.cs:125:37:125:46 | ... => ... | false | | Switch.cs:123:10:123:12 | enter M11 | Switch.cs:126:13:126:19 | return ...; | true | @@ -614,6 +616,12 @@ conditionBlock | Switch.cs:144:9:144:11 | enter M14 | Switch.cs:150:28:150:28 | 2 | false | | Switch.cs:150:13:150:19 | case ...: | Switch.cs:149:13:149:20 | default: | false | | Switch.cs:150:13:150:19 | case ...: | Switch.cs:150:28:150:28 | 2 | true | +| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:156:36:156:38 | "a" | true | +| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:156:41:156:52 | ... => ... | false | +| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:156:50:156:52 | "b" | false | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:158:13:158:49 | ...; | true | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:160:13:160:49 | ...; | false | +| Switch.cs:156:41:156:52 | ... => ... | Switch.cs:156:50:156:52 | "b" | true | | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:7:25:7:25 | ; | true | | VarDecls.cs:19:7:19:8 | enter M3 | VarDecls.cs:25:24:25:24 | access to local variable x | true | | VarDecls.cs:19:7:19:8 | enter M3 | VarDecls.cs:25:28:25:28 | access to local variable y | false | @@ -869,8 +877,8 @@ conditionFlow | Conditions.cs:76:17:76:17 | access to local variable b | Conditions.cs:78:13:79:26 | if (...) ... | false | | Conditions.cs:78:17:78:21 | ... > ... | Conditions.cs:74:9:80:9 | foreach (... ... in ...) ... | false | | Conditions.cs:78:17:78:21 | ... > ... | Conditions.cs:79:17:79:26 | ...; | true | -| Conditions.cs:81:12:81:12 | access to local variable b | Conditions.cs:82:13:82:16 | ...; | true | -| Conditions.cs:81:12:81:12 | access to local variable b | Conditions.cs:83:16:83:16 | access to local variable x | false | +| Conditions.cs:81:13:81:13 | access to local variable b | Conditions.cs:82:13:82:16 | ...; | true | +| Conditions.cs:81:13:81:13 | access to local variable b | Conditions.cs:83:16:83:16 | access to local variable x | false | | Conditions.cs:92:17:92:17 | access to local variable b | Conditions.cs:93:17:93:20 | ...; | true | | Conditions.cs:92:17:92:17 | access to local variable b | Conditions.cs:94:13:95:26 | if (...) ... | false | | Conditions.cs:94:17:94:21 | ... > ... | Conditions.cs:95:17:95:26 | ...; | true | @@ -885,11 +893,11 @@ conditionFlow | Conditions.cs:107:13:107:24 | [b (line 102): true] ... > ... | Conditions.cs:110:16:110:16 | access to local variable x | false | | Conditions.cs:108:18:108:18 | [b (line 102): false] access to parameter b | Conditions.cs:109:17:109:24 | ...; | false | | Conditions.cs:108:18:108:18 | [b (line 102): true] access to parameter b | Conditions.cs:110:16:110:16 | access to local variable x | true | -| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:113:10:113:11 | exit M9 | false | -| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:117:9:123:9 | {...} | true | +| Conditions.cs:116:25:116:39 | ... < ... | Conditions.cs:113:10:113:11 | exit M9 | false | +| Conditions.cs:116:25:116:39 | ... < ... | Conditions.cs:117:9:123:9 | {...} | true | | Conditions.cs:119:18:119:21 | access to local variable last | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | false | | Conditions.cs:119:18:119:21 | access to local variable last | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | true | -| Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | Conditions.cs:116:41:116:41 | access to local variable i | false | +| Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | Conditions.cs:116:42:116:42 | access to local variable i | false | | Conditions.cs:121:17:121:20 | [last (line 118): true] access to local variable last | Conditions.cs:122:17:122:25 | ...; | true | | Conditions.cs:131:16:131:19 | [Field1 (line 129): false] true | Conditions.cs:132:9:140:9 | [Field1 (line 129): false] {...} | true | | Conditions.cs:131:16:131:19 | [Field1 (line 129): true, Field2 (line 129): false] true | Conditions.cs:132:9:140:9 | [Field1 (line 129): true, Field2 (line 129): false] {...} | true | @@ -904,6 +912,10 @@ conditionFlow | Conditions.cs:135:21:135:26 | [Field1 (line 129): true, Field2 (line 129): true] access to field Field2 | Conditions.cs:136:17:138:17 | [Field1 (line 129): true, Field2 (line 129): true] {...} | true | | Conditions.cs:135:21:135:26 | [Field1 (line 129): true] access to field Field2 | Conditions.cs:131:16:131:19 | [Field1 (line 129): true, Field2 (line 129): false] true | false | | Conditions.cs:135:21:135:26 | [Field1 (line 129): true] access to field Field2 | Conditions.cs:136:17:138:17 | [Field1 (line 129): true, Field2 (line 129): true] {...} | true | +| Conditions.cs:145:17:145:17 | access to parameter b | Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | true | +| Conditions.cs:145:17:145:17 | access to parameter b | Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | false | +| Conditions.cs:146:13:146:13 | [b (line 143): false] access to parameter b | Conditions.cs:149:13:149:49 | ...; | false | +| Conditions.cs:146:13:146:13 | [b (line 143): true] access to parameter b | Conditions.cs:147:13:147:49 | ...; | true | | ExitMethods.cs:67:13:67:13 | access to parameter b | ExitMethods.cs:65:17:65:26 | exit ErrorMaybe | false | | ExitMethods.cs:67:13:67:13 | access to parameter b | ExitMethods.cs:68:19:68:33 | object creation of type Exception | true | | ExitMethods.cs:73:13:73:13 | access to parameter b | ExitMethods.cs:74:19:74:33 | object creation of type Exception | true | @@ -1043,15 +1055,17 @@ conditionFlow | Switch.cs:24:48:24:55 | ... != ... | Switch.cs:27:13:27:39 | case ...: | false | | Switch.cs:50:30:50:38 | ... != ... | Switch.cs:44:10:44:11 | exit M4 | false | | Switch.cs:50:30:50:38 | ... != ... | Switch.cs:51:17:51:22 | break; | true | -| Switch.cs:84:19:84:23 | ... > ... | Switch.cs:85:17:85:22 | break; | true | -| Switch.cs:84:19:84:23 | ... > ... | Switch.cs:86:22:86:25 | true | false | -| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:117:43:117:43 | 1 | true | -| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:118:13:118:33 | case ...: | false | -| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:118:42:118:42 | 2 | true | -| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:120:17:120:17 | 1 | false | +| Switch.cs:84:21:84:25 | ... > ... | Switch.cs:85:21:85:26 | break; | true | +| Switch.cs:84:21:84:25 | ... > ... | Switch.cs:86:24:86:27 | true | false | +| Switch.cs:117:25:117:34 | ... == ... | Switch.cs:117:44:117:44 | 1 | true | +| Switch.cs:117:25:117:34 | ... == ... | Switch.cs:118:13:118:34 | case ...: | false | +| Switch.cs:118:25:118:33 | ... == ... | Switch.cs:118:43:118:43 | 2 | true | +| Switch.cs:118:25:118:33 | ... == ... | Switch.cs:120:17:120:17 | 1 | false | | Switch.cs:125:34:125:34 | access to local variable b | Switch.cs:123:10:123:12 | exit M11 | false | | Switch.cs:125:34:125:34 | access to local variable b | Switch.cs:126:13:126:19 | return ...; | true | | Switch.cs:125:42:125:46 | false | Switch.cs:123:10:123:12 | exit M11 | false | +| Switch.cs:157:13:157:13 | access to parameter b | Switch.cs:158:13:158:49 | ...; | true | +| Switch.cs:157:13:157:13 | access to parameter b | Switch.cs:160:13:160:49 | ...; | false | | TypeAccesses.cs:7:13:7:22 | ... is ... | TypeAccesses.cs:7:25:7:25 | ; | true | | TypeAccesses.cs:7:13:7:22 | ... is ... | TypeAccesses.cs:8:9:8:28 | ... ...; | false | | VarDecls.cs:25:20:25:20 | access to parameter b | VarDecls.cs:25:24:25:24 | access to local variable x | true | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Conditions.cs b/csharp/ql/test/library-tests/controlflow/graph/Conditions.cs index bedcba97884..761718082ab 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Conditions.cs +++ b/csharp/ql/test/library-tests/controlflow/graph/Conditions.cs @@ -78,7 +78,7 @@ class Conditions if (x > 0) b = false; } - if(b) + if (b) x++; return x; } @@ -113,7 +113,7 @@ class Conditions void M9(string[] args) { string s = null; - for(var i = 0; i < args.Length; i++) + for (var i = 0; i < args.Length; i++) { var last = i == args.Length - 1; if (!last) @@ -139,4 +139,13 @@ class Conditions } } } + + void M11(bool b) + { + var s = b ? "a" : "b"; + if (b) + System.Console.WriteLine($"a = {s}"); + else + System.Console.WriteLine($"b = {s}"); + } } diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index 773e3cd0204..82aea8adba1 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -733,9 +733,9 @@ dominance | Conditions.cs:78:21:78:21 | 0 | Conditions.cs:78:17:78:21 | ... > ... | | Conditions.cs:79:17:79:26 | ...; | Conditions.cs:79:21:79:25 | false | | Conditions.cs:79:21:79:25 | false | Conditions.cs:79:17:79:25 | ... = ... | -| Conditions.cs:81:9:82:16 | if (...) ... | Conditions.cs:81:12:81:12 | access to local variable b | -| Conditions.cs:81:12:81:12 | access to local variable b | Conditions.cs:82:13:82:16 | ...; | -| Conditions.cs:81:12:81:12 | access to local variable b | Conditions.cs:83:16:83:16 | access to local variable x | +| Conditions.cs:81:9:82:16 | if (...) ... | Conditions.cs:81:13:81:13 | access to local variable b | +| Conditions.cs:81:13:81:13 | access to local variable b | Conditions.cs:82:13:82:16 | ...; | +| Conditions.cs:81:13:81:13 | access to local variable b | Conditions.cs:83:16:83:16 | access to local variable x | | Conditions.cs:82:13:82:13 | access to local variable x | Conditions.cs:82:13:82:15 | ...++ | | Conditions.cs:82:13:82:16 | ...; | Conditions.cs:82:13:82:13 | access to local variable x | | Conditions.cs:83:9:83:17 | return ...; | Conditions.cs:70:9:70:10 | exit M6 | @@ -814,15 +814,15 @@ dominance | Conditions.cs:115:9:115:24 | ... ...; | Conditions.cs:115:20:115:23 | null | | Conditions.cs:115:16:115:23 | String s = ... | Conditions.cs:116:9:123:9 | for (...;...;...) ... | | Conditions.cs:115:20:115:23 | null | Conditions.cs:115:16:115:23 | String s = ... | -| Conditions.cs:116:9:123:9 | for (...;...;...) ... | Conditions.cs:116:21:116:21 | 0 | -| Conditions.cs:116:17:116:21 | Int32 i = ... | Conditions.cs:116:24:116:24 | access to local variable i | -| Conditions.cs:116:21:116:21 | 0 | Conditions.cs:116:17:116:21 | Int32 i = ... | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:28:116:31 | access to parameter args | -| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:113:10:113:11 | exit M9 | -| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:117:9:123:9 | {...} | -| Conditions.cs:116:28:116:31 | access to parameter args | Conditions.cs:116:28:116:38 | access to property Length | -| Conditions.cs:116:28:116:38 | access to property Length | Conditions.cs:116:24:116:38 | ... < ... | -| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:116:41:116:43 | ...++ | +| Conditions.cs:116:9:123:9 | for (...;...;...) ... | Conditions.cs:116:22:116:22 | 0 | +| Conditions.cs:116:18:116:22 | Int32 i = ... | Conditions.cs:116:25:116:25 | access to local variable i | +| Conditions.cs:116:22:116:22 | 0 | Conditions.cs:116:18:116:22 | Int32 i = ... | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:116:29:116:32 | access to parameter args | +| Conditions.cs:116:25:116:39 | ... < ... | Conditions.cs:113:10:113:11 | exit M9 | +| Conditions.cs:116:25:116:39 | ... < ... | Conditions.cs:117:9:123:9 | {...} | +| Conditions.cs:116:29:116:32 | access to parameter args | Conditions.cs:116:29:116:39 | access to property Length | +| Conditions.cs:116:29:116:39 | access to property Length | Conditions.cs:116:25:116:39 | ... < ... | +| Conditions.cs:116:42:116:42 | access to local variable i | Conditions.cs:116:42:116:44 | ...++ | | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:118:13:118:44 | ... ...; | | Conditions.cs:118:13:118:44 | ... ...; | Conditions.cs:118:24:118:24 | access to local variable i | | Conditions.cs:118:17:118:43 | Boolean last = ... | Conditions.cs:119:13:120:23 | if (...) ... | @@ -883,6 +883,28 @@ dominance | Conditions.cs:137:21:137:26 | [Field1 (line 129): true, Field2 (line 129): true] this access | Conditions.cs:137:21:137:26 | [Field1 (line 129): true, Field2 (line 129): true] access to field Field1 | | Conditions.cs:137:21:137:37 | [Field1 (line 129): true, Field2 (line 129): true] call to method ToString | Conditions.cs:131:16:131:19 | [Field1 (line 129): true, Field2 (line 129): true] true | | Conditions.cs:137:21:137:38 | [Field1 (line 129): true, Field2 (line 129): true] ...; | Conditions.cs:137:21:137:26 | [Field1 (line 129): true, Field2 (line 129): true] this access | +| Conditions.cs:143:10:143:12 | enter M11 | Conditions.cs:144:5:150:5 | {...} | +| Conditions.cs:144:5:150:5 | {...} | Conditions.cs:145:9:145:30 | ... ...; | +| Conditions.cs:145:9:145:30 | ... ...; | Conditions.cs:145:17:145:29 | ... ? ... : ... | +| Conditions.cs:145:13:145:29 | [b (line 143): false] String s = ... | Conditions.cs:146:9:149:49 | [b (line 143): false] if (...) ... | +| Conditions.cs:145:13:145:29 | [b (line 143): true] String s = ... | Conditions.cs:146:9:149:49 | [b (line 143): true] if (...) ... | +| Conditions.cs:145:17:145:17 | access to parameter b | Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | +| Conditions.cs:145:17:145:17 | access to parameter b | Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | +| Conditions.cs:145:17:145:29 | ... ? ... : ... | Conditions.cs:145:17:145:17 | access to parameter b | +| Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | Conditions.cs:145:13:145:29 | [b (line 143): true] String s = ... | +| Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | Conditions.cs:145:13:145:29 | [b (line 143): false] String s = ... | +| Conditions.cs:146:9:149:49 | [b (line 143): false] if (...) ... | Conditions.cs:146:13:146:13 | [b (line 143): false] access to parameter b | +| Conditions.cs:146:9:149:49 | [b (line 143): true] if (...) ... | Conditions.cs:146:13:146:13 | [b (line 143): true] access to parameter b | +| Conditions.cs:146:13:146:13 | [b (line 143): false] access to parameter b | Conditions.cs:149:13:149:49 | ...; | +| Conditions.cs:146:13:146:13 | [b (line 143): true] access to parameter b | Conditions.cs:147:13:147:49 | ...; | +| Conditions.cs:147:13:147:49 | ...; | Conditions.cs:147:40:147:43 | "a = " | +| Conditions.cs:147:38:147:47 | $"..." | Conditions.cs:147:13:147:48 | call to method WriteLine | +| Conditions.cs:147:40:147:43 | "a = " | Conditions.cs:147:45:147:45 | access to local variable s | +| Conditions.cs:147:45:147:45 | access to local variable s | Conditions.cs:147:38:147:47 | $"..." | +| Conditions.cs:149:13:149:49 | ...; | Conditions.cs:149:40:149:43 | "b = " | +| Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:149:13:149:48 | call to method WriteLine | +| Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:149:45:149:45 | access to local variable s | +| Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:149:38:149:47 | $"..." | | ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:8:5:11:5 | {...} | | ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:9:9:9:25 | ...; | | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | ExitMethods.cs:10:9:10:15 | return ...; | @@ -2387,9 +2409,9 @@ dominance | Switch.cs:25:35:25:35 | access to local variable s | Switch.cs:25:17:25:36 | call to method WriteLine | | Switch.cs:27:13:27:39 | case ...: | Switch.cs:27:18:27:25 | Double d | | Switch.cs:27:18:27:25 | Double d | Switch.cs:27:32:27:38 | call to method Throw | -| Switch.cs:28:17:28:21 | Label: | Switch.cs:29:17:29:23 | return ...; | +| Switch.cs:28:13:28:17 | Label: | Switch.cs:29:17:29:23 | return ...; | | Switch.cs:30:13:30:20 | default: | Switch.cs:31:17:31:27 | goto ...; | -| Switch.cs:31:17:31:27 | goto ...; | Switch.cs:28:17:28:21 | Label: | +| Switch.cs:31:17:31:27 | goto ...; | Switch.cs:28:13:28:17 | Label: | | Switch.cs:35:10:35:11 | enter M3 | Switch.cs:36:5:42:5 | {...} | | Switch.cs:36:5:42:5 | {...} | Switch.cs:37:9:41:9 | switch (...) {...} | | Switch.cs:37:9:41:9 | switch (...) {...} | Switch.cs:37:17:37:23 | call to method Throw | @@ -2410,63 +2432,63 @@ dominance | Switch.cs:56:5:64:5 | {...} | Switch.cs:57:9:63:9 | switch (...) {...} | | Switch.cs:57:9:63:9 | switch (...) {...} | Switch.cs:57:17:57:17 | 1 | | Switch.cs:57:17:57:17 | 1 | Switch.cs:57:21:57:21 | 2 | -| Switch.cs:57:17:57:21 | ... + ... | Switch.cs:59:13:59:20 | case ...: | +| Switch.cs:57:17:57:21 | ... + ... | Switch.cs:59:13:59:19 | case ...: | | Switch.cs:57:21:57:21 | 2 | Switch.cs:57:17:57:21 | ... + ... | -| Switch.cs:59:13:59:20 | case ...: | Switch.cs:59:18:59:18 | 2 | -| Switch.cs:59:18:59:18 | 2 | Switch.cs:61:13:61:20 | case ...: | -| Switch.cs:61:13:61:20 | case ...: | Switch.cs:61:18:61:18 | 3 | -| Switch.cs:61:18:61:18 | 3 | Switch.cs:62:15:62:20 | break; | -| Switch.cs:62:15:62:20 | break; | Switch.cs:55:10:55:11 | exit M5 | +| Switch.cs:59:13:59:19 | case ...: | Switch.cs:59:18:59:18 | 2 | +| Switch.cs:59:18:59:18 | 2 | Switch.cs:61:13:61:19 | case ...: | +| Switch.cs:61:13:61:19 | case ...: | Switch.cs:61:18:61:18 | 3 | +| Switch.cs:61:18:61:18 | 3 | Switch.cs:62:17:62:22 | break; | +| Switch.cs:62:17:62:22 | break; | Switch.cs:55:10:55:11 | exit M5 | | Switch.cs:66:10:66:11 | enter M6 | Switch.cs:67:5:75:5 | {...} | | Switch.cs:67:5:75:5 | {...} | Switch.cs:68:9:74:9 | switch (...) {...} | | Switch.cs:68:9:74:9 | switch (...) {...} | Switch.cs:68:25:68:25 | access to parameter s | -| Switch.cs:68:17:68:25 | (...) ... | Switch.cs:70:13:70:24 | case ...: | +| Switch.cs:68:17:68:25 | (...) ... | Switch.cs:70:13:70:23 | case ...: | | Switch.cs:68:25:68:25 | access to parameter s | Switch.cs:68:17:68:25 | (...) ... | -| Switch.cs:70:13:70:24 | case ...: | Switch.cs:70:18:70:20 | access to type Int32 | -| Switch.cs:70:18:70:20 | access to type Int32 | Switch.cs:72:13:72:21 | case ...: | -| Switch.cs:72:13:72:21 | case ...: | Switch.cs:72:18:72:19 | "" | +| Switch.cs:70:13:70:23 | case ...: | Switch.cs:70:18:70:20 | access to type Int32 | +| Switch.cs:70:18:70:20 | access to type Int32 | Switch.cs:72:13:72:20 | case ...: | +| Switch.cs:72:13:72:20 | case ...: | Switch.cs:72:18:72:19 | "" | | Switch.cs:72:18:72:19 | "" | Switch.cs:66:10:66:11 | exit M6 | -| Switch.cs:72:18:72:19 | "" | Switch.cs:73:15:73:20 | break; | +| Switch.cs:72:18:72:19 | "" | Switch.cs:73:17:73:22 | break; | | Switch.cs:77:10:77:11 | enter M7 | Switch.cs:78:5:89:5 | {...} | | Switch.cs:78:5:89:5 | {...} | Switch.cs:79:9:87:9 | switch (...) {...} | | Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:79:17:79:17 | access to parameter i | -| Switch.cs:79:17:79:17 | access to parameter i | Switch.cs:81:13:81:20 | case ...: | -| Switch.cs:81:13:81:20 | case ...: | Switch.cs:81:18:81:18 | 1 | -| Switch.cs:81:18:81:18 | 1 | Switch.cs:82:22:82:25 | true | -| Switch.cs:81:18:81:18 | 1 | Switch.cs:83:13:83:20 | case ...: | -| Switch.cs:82:22:82:25 | true | Switch.cs:82:15:82:26 | return ...; | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:83:18:83:18 | 2 | -| Switch.cs:83:18:83:18 | 2 | Switch.cs:84:15:85:22 | if (...) ... | +| Switch.cs:79:17:79:17 | access to parameter i | Switch.cs:81:13:81:19 | case ...: | +| Switch.cs:81:13:81:19 | case ...: | Switch.cs:81:18:81:18 | 1 | +| Switch.cs:81:18:81:18 | 1 | Switch.cs:82:24:82:27 | true | +| Switch.cs:81:18:81:18 | 1 | Switch.cs:83:13:83:19 | case ...: | +| Switch.cs:82:24:82:27 | true | Switch.cs:82:17:82:28 | return ...; | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:83:18:83:18 | 2 | +| Switch.cs:83:18:83:18 | 2 | Switch.cs:84:17:85:26 | if (...) ... | | Switch.cs:83:18:83:18 | 2 | Switch.cs:88:16:88:20 | false | -| Switch.cs:84:15:85:22 | if (...) ... | Switch.cs:84:19:84:19 | access to parameter j | -| Switch.cs:84:19:84:19 | access to parameter j | Switch.cs:84:23:84:23 | 2 | -| Switch.cs:84:19:84:23 | ... > ... | Switch.cs:85:17:85:22 | break; | -| Switch.cs:84:19:84:23 | ... > ... | Switch.cs:86:22:86:25 | true | -| Switch.cs:84:23:84:23 | 2 | Switch.cs:84:19:84:23 | ... > ... | -| Switch.cs:86:22:86:25 | true | Switch.cs:86:15:86:26 | return ...; | +| Switch.cs:84:17:85:26 | if (...) ... | Switch.cs:84:21:84:21 | access to parameter j | +| Switch.cs:84:21:84:21 | access to parameter j | Switch.cs:84:25:84:25 | 2 | +| Switch.cs:84:21:84:25 | ... > ... | Switch.cs:85:21:85:26 | break; | +| Switch.cs:84:21:84:25 | ... > ... | Switch.cs:86:24:86:27 | true | +| Switch.cs:84:25:84:25 | 2 | Switch.cs:84:21:84:25 | ... > ... | +| Switch.cs:86:24:86:27 | true | Switch.cs:86:17:86:28 | return ...; | | Switch.cs:88:16:88:20 | false | Switch.cs:88:9:88:21 | return ...; | | Switch.cs:91:10:91:11 | enter M8 | Switch.cs:92:5:99:5 | {...} | | Switch.cs:92:5:99:5 | {...} | Switch.cs:93:9:97:9 | switch (...) {...} | | Switch.cs:93:9:97:9 | switch (...) {...} | Switch.cs:93:17:93:17 | access to parameter o | -| Switch.cs:93:17:93:17 | access to parameter o | Switch.cs:95:13:95:24 | case ...: | -| Switch.cs:95:13:95:24 | case ...: | Switch.cs:95:18:95:20 | access to type Int32 | -| Switch.cs:95:18:95:20 | access to type Int32 | Switch.cs:96:22:96:25 | true | +| Switch.cs:93:17:93:17 | access to parameter o | Switch.cs:95:13:95:23 | case ...: | +| Switch.cs:95:13:95:23 | case ...: | Switch.cs:95:18:95:20 | access to type Int32 | +| Switch.cs:95:18:95:20 | access to type Int32 | Switch.cs:96:24:96:27 | true | | Switch.cs:95:18:95:20 | access to type Int32 | Switch.cs:98:16:98:20 | false | -| Switch.cs:96:22:96:25 | true | Switch.cs:96:15:96:26 | return ...; | +| Switch.cs:96:24:96:27 | true | Switch.cs:96:17:96:28 | return ...; | | Switch.cs:98:16:98:20 | false | Switch.cs:98:9:98:21 | return ...; | | Switch.cs:101:9:101:10 | enter M9 | Switch.cs:102:5:109:5 | {...} | | Switch.cs:102:5:109:5 | {...} | Switch.cs:103:9:107:9 | switch (...) {...} | | Switch.cs:103:9:107:9 | switch (...) {...} | Switch.cs:103:17:103:17 | access to parameter s | | Switch.cs:103:17:103:17 | access to parameter s | Switch.cs:103:19:103:25 | access to property Length | -| Switch.cs:103:17:103:17 | access to parameter s | Switch.cs:105:13:105:20 | case ...: | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:105:18:105:18 | 0 | -| Switch.cs:105:18:105:18 | 0 | Switch.cs:105:29:105:29 | 0 | -| Switch.cs:105:18:105:18 | 0 | Switch.cs:106:13:106:20 | case ...: | -| Switch.cs:105:29:105:29 | 0 | Switch.cs:105:22:105:30 | return ...; | -| Switch.cs:106:13:106:20 | case ...: | Switch.cs:106:18:106:18 | 1 | -| Switch.cs:106:18:106:18 | 1 | Switch.cs:106:29:106:29 | 1 | +| Switch.cs:103:17:103:17 | access to parameter s | Switch.cs:105:13:105:19 | case ...: | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:105:18:105:18 | 0 | +| Switch.cs:105:18:105:18 | 0 | Switch.cs:105:28:105:28 | 0 | +| Switch.cs:105:18:105:18 | 0 | Switch.cs:106:13:106:19 | case ...: | +| Switch.cs:105:28:105:28 | 0 | Switch.cs:105:21:105:29 | return ...; | +| Switch.cs:106:13:106:19 | case ...: | Switch.cs:106:18:106:18 | 1 | +| Switch.cs:106:18:106:18 | 1 | Switch.cs:106:28:106:28 | 1 | | Switch.cs:106:18:106:18 | 1 | Switch.cs:108:17:108:17 | 1 | -| Switch.cs:106:29:106:29 | 1 | Switch.cs:106:22:106:30 | return ...; | +| Switch.cs:106:28:106:28 | 1 | Switch.cs:106:21:106:29 | return ...; | | Switch.cs:108:16:108:17 | -... | Switch.cs:108:9:108:18 | return ...; | | Switch.cs:108:17:108:17 | 1 | Switch.cs:108:16:108:17 | -... | | Switch.cs:111:17:111:21 | enter Throw | Switch.cs:111:34:111:48 | object creation of type Exception | @@ -2476,21 +2498,21 @@ dominance | Switch.cs:114:5:121:5 | {...} | Switch.cs:115:9:119:9 | switch (...) {...} | | Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:115:17:115:17 | access to parameter s | | Switch.cs:115:17:115:17 | access to parameter s | Switch.cs:115:17:115:24 | access to property Length | -| Switch.cs:115:17:115:24 | access to property Length | Switch.cs:117:13:117:34 | case ...: | -| Switch.cs:117:13:117:34 | case ...: | Switch.cs:117:18:117:18 | 3 | +| Switch.cs:115:17:115:24 | access to property Length | Switch.cs:117:13:117:35 | case ...: | +| Switch.cs:117:13:117:35 | case ...: | Switch.cs:117:18:117:18 | 3 | | Switch.cs:117:18:117:18 | 3 | Switch.cs:117:25:117:25 | access to parameter s | -| Switch.cs:117:18:117:18 | 3 | Switch.cs:118:13:118:33 | case ...: | -| Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:28:117:32 | "foo" | -| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:117:43:117:43 | 1 | -| Switch.cs:117:28:117:32 | "foo" | Switch.cs:117:25:117:32 | ... == ... | -| Switch.cs:117:43:117:43 | 1 | Switch.cs:117:36:117:44 | return ...; | -| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:18:118:18 | 2 | +| Switch.cs:117:18:117:18 | 3 | Switch.cs:118:13:118:34 | case ...: | +| Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:30:117:34 | "foo" | +| Switch.cs:117:25:117:34 | ... == ... | Switch.cs:117:44:117:44 | 1 | +| Switch.cs:117:30:117:34 | "foo" | Switch.cs:117:25:117:34 | ... == ... | +| Switch.cs:117:44:117:44 | 1 | Switch.cs:117:37:117:45 | return ...; | +| Switch.cs:118:13:118:34 | case ...: | Switch.cs:118:18:118:18 | 2 | | Switch.cs:118:18:118:18 | 2 | Switch.cs:118:25:118:25 | access to parameter s | | Switch.cs:118:18:118:18 | 2 | Switch.cs:120:17:120:17 | 1 | -| Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:28:118:31 | "fu" | -| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:118:42:118:42 | 2 | -| Switch.cs:118:28:118:31 | "fu" | Switch.cs:118:25:118:31 | ... == ... | -| Switch.cs:118:42:118:42 | 2 | Switch.cs:118:35:118:43 | return ...; | +| Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:30:118:33 | "fu" | +| Switch.cs:118:25:118:33 | ... == ... | Switch.cs:118:43:118:43 | 2 | +| Switch.cs:118:30:118:33 | "fu" | Switch.cs:118:25:118:33 | ... == ... | +| Switch.cs:118:43:118:43 | 2 | Switch.cs:118:36:118:44 | return ...; | | Switch.cs:120:16:120:17 | -... | Switch.cs:120:9:120:18 | return ...; | | Switch.cs:120:17:120:17 | 1 | Switch.cs:120:16:120:17 | -... | | Switch.cs:123:10:123:12 | enter M11 | Switch.cs:124:5:127:5 | {...} | @@ -2545,6 +2567,28 @@ dominance | Switch.cs:150:18:150:18 | 2 | Switch.cs:149:13:149:20 | default: | | Switch.cs:150:18:150:18 | 2 | Switch.cs:150:28:150:28 | 2 | | Switch.cs:150:28:150:28 | 2 | Switch.cs:150:21:150:29 | return ...; | +| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:155:5:161:5 | {...} | +| Switch.cs:155:5:161:5 | {...} | Switch.cs:156:9:156:55 | ... ...; | +| Switch.cs:156:9:156:55 | ... ...; | Switch.cs:156:17:156:54 | ... switch { ... } | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:157:9:160:49 | if (...) ... | +| Switch.cs:156:17:156:17 | access to parameter b | Switch.cs:156:28:156:38 | ... => ... | +| Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:156:17:156:17 | access to parameter b | +| Switch.cs:156:28:156:31 | true | Switch.cs:156:36:156:38 | "a" | +| Switch.cs:156:28:156:31 | true | Switch.cs:156:41:156:52 | ... => ... | +| Switch.cs:156:28:156:38 | ... => ... | Switch.cs:156:28:156:31 | true | +| Switch.cs:156:41:156:45 | false | Switch.cs:156:50:156:52 | "b" | +| Switch.cs:156:41:156:52 | ... => ... | Switch.cs:156:41:156:45 | false | +| Switch.cs:157:9:160:49 | if (...) ... | Switch.cs:157:13:157:13 | access to parameter b | +| Switch.cs:157:13:157:13 | access to parameter b | Switch.cs:158:13:158:49 | ...; | +| Switch.cs:157:13:157:13 | access to parameter b | Switch.cs:160:13:160:49 | ...; | +| Switch.cs:158:13:158:49 | ...; | Switch.cs:158:40:158:43 | "a = " | +| Switch.cs:158:38:158:47 | $"..." | Switch.cs:158:13:158:48 | call to method WriteLine | +| Switch.cs:158:40:158:43 | "a = " | Switch.cs:158:45:158:45 | access to local variable s | +| Switch.cs:158:45:158:45 | access to local variable s | Switch.cs:158:38:158:47 | $"..." | +| Switch.cs:160:13:160:49 | ...; | Switch.cs:160:40:160:43 | "b = " | +| Switch.cs:160:38:160:47 | $"..." | Switch.cs:160:13:160:48 | call to method WriteLine | +| Switch.cs:160:40:160:43 | "b = " | Switch.cs:160:45:160:45 | access to local variable s | +| Switch.cs:160:45:160:45 | access to local variable s | Switch.cs:160:38:160:47 | $"..." | | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:4:5:9:5 | {...} | | TypeAccesses.cs:4:5:9:5 | {...} | TypeAccesses.cs:5:9:5:26 | ... ...; | | TypeAccesses.cs:5:9:5:26 | ... ...; | TypeAccesses.cs:5:25:5:25 | access to parameter o | @@ -3935,11 +3979,11 @@ postDominance | Conditions.cs:79:17:79:25 | ... = ... | Conditions.cs:79:21:79:25 | false | | Conditions.cs:79:21:79:25 | false | Conditions.cs:79:17:79:26 | ...; | | Conditions.cs:81:9:82:16 | if (...) ... | Conditions.cs:74:9:80:9 | foreach (... ... in ...) ... | -| Conditions.cs:81:12:81:12 | access to local variable b | Conditions.cs:81:9:82:16 | if (...) ... | +| Conditions.cs:81:13:81:13 | access to local variable b | Conditions.cs:81:9:82:16 | if (...) ... | | Conditions.cs:82:13:82:13 | access to local variable x | Conditions.cs:82:13:82:16 | ...; | | Conditions.cs:82:13:82:15 | ...++ | Conditions.cs:82:13:82:13 | access to local variable x | | Conditions.cs:83:9:83:17 | return ...; | Conditions.cs:83:16:83:16 | access to local variable x | -| Conditions.cs:83:16:83:16 | access to local variable x | Conditions.cs:81:12:81:12 | access to local variable b | +| Conditions.cs:83:16:83:16 | access to local variable x | Conditions.cs:81:13:81:13 | access to local variable b | | Conditions.cs:83:16:83:16 | access to local variable x | Conditions.cs:82:13:82:15 | ...++ | | Conditions.cs:86:9:86:10 | exit M7 | Conditions.cs:99:9:99:17 | return ...; | | Conditions.cs:87:5:100:5 | {...} | Conditions.cs:86:9:86:10 | enter M7 | @@ -4010,22 +4054,22 @@ postDominance | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:107:13:107:24 | [b (line 102): true] ... > ... | | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:108:18:108:18 | [b (line 102): true] access to parameter b | | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:109:17:109:23 | ... = ... | -| Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:116:24:116:38 | ... < ... | +| Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:116:25:116:39 | ... < ... | | Conditions.cs:114:5:124:5 | {...} | Conditions.cs:113:10:113:11 | enter M9 | | Conditions.cs:115:9:115:24 | ... ...; | Conditions.cs:114:5:124:5 | {...} | | Conditions.cs:115:16:115:23 | String s = ... | Conditions.cs:115:20:115:23 | null | | Conditions.cs:115:20:115:23 | null | Conditions.cs:115:9:115:24 | ... ...; | | Conditions.cs:116:9:123:9 | for (...;...;...) ... | Conditions.cs:115:16:115:23 | String s = ... | -| Conditions.cs:116:17:116:21 | Int32 i = ... | Conditions.cs:116:21:116:21 | 0 | -| Conditions.cs:116:21:116:21 | 0 | Conditions.cs:116:9:123:9 | for (...;...;...) ... | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:17:116:21 | Int32 i = ... | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:41:116:43 | ...++ | -| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:116:28:116:38 | access to property Length | -| Conditions.cs:116:28:116:31 | access to parameter args | Conditions.cs:116:24:116:24 | access to local variable i | -| Conditions.cs:116:28:116:38 | access to property Length | Conditions.cs:116:28:116:31 | access to parameter args | -| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | -| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:122:17:122:24 | ... = ... | -| Conditions.cs:116:41:116:43 | ...++ | Conditions.cs:116:41:116:41 | access to local variable i | +| Conditions.cs:116:18:116:22 | Int32 i = ... | Conditions.cs:116:22:116:22 | 0 | +| Conditions.cs:116:22:116:22 | 0 | Conditions.cs:116:9:123:9 | for (...;...;...) ... | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:116:18:116:22 | Int32 i = ... | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:116:42:116:44 | ...++ | +| Conditions.cs:116:25:116:39 | ... < ... | Conditions.cs:116:29:116:39 | access to property Length | +| Conditions.cs:116:29:116:32 | access to parameter args | Conditions.cs:116:25:116:25 | access to local variable i | +| Conditions.cs:116:29:116:39 | access to property Length | Conditions.cs:116:29:116:32 | access to parameter args | +| Conditions.cs:116:42:116:42 | access to local variable i | Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | +| Conditions.cs:116:42:116:42 | access to local variable i | Conditions.cs:122:17:122:24 | ... = ... | +| Conditions.cs:116:42:116:44 | ...++ | Conditions.cs:116:42:116:42 | access to local variable i | | Conditions.cs:118:13:118:44 | ... ...; | Conditions.cs:117:9:123:9 | {...} | | Conditions.cs:118:17:118:43 | Boolean last = ... | Conditions.cs:118:24:118:43 | ... == ... | | Conditions.cs:118:24:118:24 | access to local variable i | Conditions.cs:118:13:118:44 | ... ...; | @@ -4080,6 +4124,28 @@ postDominance | Conditions.cs:137:21:137:26 | [Field1 (line 129): true, Field2 (line 129): true] this access | Conditions.cs:137:21:137:38 | [Field1 (line 129): true, Field2 (line 129): true] ...; | | Conditions.cs:137:21:137:37 | [Field1 (line 129): true, Field2 (line 129): true] call to method ToString | Conditions.cs:137:21:137:26 | [Field1 (line 129): true, Field2 (line 129): true] access to field Field1 | | Conditions.cs:137:21:137:38 | [Field1 (line 129): true, Field2 (line 129): true] ...; | Conditions.cs:136:17:138:17 | [Field1 (line 129): true, Field2 (line 129): true] {...} | +| Conditions.cs:143:10:143:12 | exit M11 | Conditions.cs:147:13:147:48 | call to method WriteLine | +| Conditions.cs:143:10:143:12 | exit M11 | Conditions.cs:149:13:149:48 | call to method WriteLine | +| Conditions.cs:144:5:150:5 | {...} | Conditions.cs:143:10:143:12 | enter M11 | +| Conditions.cs:145:9:145:30 | ... ...; | Conditions.cs:144:5:150:5 | {...} | +| Conditions.cs:145:13:145:29 | [b (line 143): false] String s = ... | Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | +| Conditions.cs:145:13:145:29 | [b (line 143): true] String s = ... | Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | +| Conditions.cs:145:17:145:17 | access to parameter b | Conditions.cs:145:17:145:29 | ... ? ... : ... | +| Conditions.cs:145:17:145:29 | ... ? ... : ... | Conditions.cs:145:9:145:30 | ... ...; | +| Conditions.cs:146:9:149:49 | [b (line 143): false] if (...) ... | Conditions.cs:145:13:145:29 | [b (line 143): false] String s = ... | +| Conditions.cs:146:9:149:49 | [b (line 143): true] if (...) ... | Conditions.cs:145:13:145:29 | [b (line 143): true] String s = ... | +| Conditions.cs:146:13:146:13 | [b (line 143): false] access to parameter b | Conditions.cs:146:9:149:49 | [b (line 143): false] if (...) ... | +| Conditions.cs:146:13:146:13 | [b (line 143): true] access to parameter b | Conditions.cs:146:9:149:49 | [b (line 143): true] if (...) ... | +| Conditions.cs:147:13:147:48 | call to method WriteLine | Conditions.cs:147:38:147:47 | $"..." | +| Conditions.cs:147:13:147:49 | ...; | Conditions.cs:146:13:146:13 | [b (line 143): true] access to parameter b | +| Conditions.cs:147:38:147:47 | $"..." | Conditions.cs:147:45:147:45 | access to local variable s | +| Conditions.cs:147:40:147:43 | "a = " | Conditions.cs:147:13:147:49 | ...; | +| Conditions.cs:147:45:147:45 | access to local variable s | Conditions.cs:147:40:147:43 | "a = " | +| Conditions.cs:149:13:149:48 | call to method WriteLine | Conditions.cs:149:38:149:47 | $"..." | +| Conditions.cs:149:13:149:49 | ...; | Conditions.cs:146:13:146:13 | [b (line 143): false] access to parameter b | +| Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:149:45:149:45 | access to local variable s | +| Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:149:13:149:49 | ...; | +| Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:149:40:149:43 | "b = " | | ExitMethods.cs:7:10:7:11 | exit M1 | ExitMethods.cs:10:9:10:15 | return ...; | | ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:7:10:7:11 | enter M1 | | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | ExitMethods.cs:9:20:9:23 | true | @@ -5533,8 +5599,8 @@ postDominance | Switch.cs:25:35:25:35 | access to local variable s | Switch.cs:25:17:25:37 | ...; | | Switch.cs:26:17:26:23 | return ...; | Switch.cs:25:17:25:36 | call to method WriteLine | | Switch.cs:27:18:27:25 | Double d | Switch.cs:27:13:27:39 | case ...: | -| Switch.cs:28:17:28:21 | Label: | Switch.cs:31:17:31:27 | goto ...; | -| Switch.cs:29:17:29:23 | return ...; | Switch.cs:28:17:28:21 | Label: | +| Switch.cs:28:13:28:17 | Label: | Switch.cs:31:17:31:27 | goto ...; | +| Switch.cs:29:17:29:23 | return ...; | Switch.cs:28:13:28:17 | Label: | | Switch.cs:30:13:30:20 | default: | Switch.cs:19:17:19:29 | goto default; | | Switch.cs:31:17:31:27 | goto ...; | Switch.cs:30:13:30:20 | default: | | Switch.cs:35:10:35:11 | exit M3 | Switch.cs:37:17:37:23 | call to method Throw | @@ -5553,85 +5619,85 @@ postDominance | Switch.cs:50:18:50:21 | access to type Boolean | Switch.cs:50:13:50:39 | case ...: | | Switch.cs:50:30:50:38 | ... != ... | Switch.cs:50:35:50:38 | null | | Switch.cs:50:35:50:38 | null | Switch.cs:50:30:50:30 | access to parameter o | -| Switch.cs:55:10:55:11 | exit M5 | Switch.cs:62:15:62:20 | break; | +| Switch.cs:55:10:55:11 | exit M5 | Switch.cs:62:17:62:22 | break; | | Switch.cs:56:5:64:5 | {...} | Switch.cs:55:10:55:11 | enter M5 | | Switch.cs:57:9:63:9 | switch (...) {...} | Switch.cs:56:5:64:5 | {...} | | Switch.cs:57:17:57:17 | 1 | Switch.cs:57:9:63:9 | switch (...) {...} | | Switch.cs:57:17:57:21 | ... + ... | Switch.cs:57:21:57:21 | 2 | | Switch.cs:57:21:57:21 | 2 | Switch.cs:57:17:57:17 | 1 | -| Switch.cs:59:13:59:20 | case ...: | Switch.cs:57:17:57:21 | ... + ... | -| Switch.cs:59:18:59:18 | 2 | Switch.cs:59:13:59:20 | case ...: | -| Switch.cs:61:13:61:20 | case ...: | Switch.cs:59:18:59:18 | 2 | -| Switch.cs:61:18:61:18 | 3 | Switch.cs:61:13:61:20 | case ...: | -| Switch.cs:62:15:62:20 | break; | Switch.cs:61:18:61:18 | 3 | +| Switch.cs:59:13:59:19 | case ...: | Switch.cs:57:17:57:21 | ... + ... | +| Switch.cs:59:18:59:18 | 2 | Switch.cs:59:13:59:19 | case ...: | +| Switch.cs:61:13:61:19 | case ...: | Switch.cs:59:18:59:18 | 2 | +| Switch.cs:61:18:61:18 | 3 | Switch.cs:61:13:61:19 | case ...: | +| Switch.cs:62:17:62:22 | break; | Switch.cs:61:18:61:18 | 3 | | Switch.cs:66:10:66:11 | exit M6 | Switch.cs:72:18:72:19 | "" | -| Switch.cs:66:10:66:11 | exit M6 | Switch.cs:73:15:73:20 | break; | +| Switch.cs:66:10:66:11 | exit M6 | Switch.cs:73:17:73:22 | break; | | Switch.cs:67:5:75:5 | {...} | Switch.cs:66:10:66:11 | enter M6 | | Switch.cs:68:9:74:9 | switch (...) {...} | Switch.cs:67:5:75:5 | {...} | | Switch.cs:68:17:68:25 | (...) ... | Switch.cs:68:25:68:25 | access to parameter s | | Switch.cs:68:25:68:25 | access to parameter s | Switch.cs:68:9:74:9 | switch (...) {...} | -| Switch.cs:70:13:70:24 | case ...: | Switch.cs:68:17:68:25 | (...) ... | -| Switch.cs:70:18:70:20 | access to type Int32 | Switch.cs:70:13:70:24 | case ...: | -| Switch.cs:72:13:72:21 | case ...: | Switch.cs:70:18:70:20 | access to type Int32 | -| Switch.cs:72:18:72:19 | "" | Switch.cs:72:13:72:21 | case ...: | -| Switch.cs:77:10:77:11 | exit M7 | Switch.cs:82:15:82:26 | return ...; | -| Switch.cs:77:10:77:11 | exit M7 | Switch.cs:86:15:86:26 | return ...; | +| Switch.cs:70:13:70:23 | case ...: | Switch.cs:68:17:68:25 | (...) ... | +| Switch.cs:70:18:70:20 | access to type Int32 | Switch.cs:70:13:70:23 | case ...: | +| Switch.cs:72:13:72:20 | case ...: | Switch.cs:70:18:70:20 | access to type Int32 | +| Switch.cs:72:18:72:19 | "" | Switch.cs:72:13:72:20 | case ...: | +| Switch.cs:77:10:77:11 | exit M7 | Switch.cs:82:17:82:28 | return ...; | +| Switch.cs:77:10:77:11 | exit M7 | Switch.cs:86:17:86:28 | return ...; | | Switch.cs:77:10:77:11 | exit M7 | Switch.cs:88:9:88:21 | return ...; | | Switch.cs:78:5:89:5 | {...} | Switch.cs:77:10:77:11 | enter M7 | | Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:78:5:89:5 | {...} | | Switch.cs:79:17:79:17 | access to parameter i | Switch.cs:79:9:87:9 | switch (...) {...} | -| Switch.cs:81:13:81:20 | case ...: | Switch.cs:79:17:79:17 | access to parameter i | -| Switch.cs:81:18:81:18 | 1 | Switch.cs:81:13:81:20 | case ...: | -| Switch.cs:82:15:82:26 | return ...; | Switch.cs:82:22:82:25 | true | -| Switch.cs:83:18:83:18 | 2 | Switch.cs:83:13:83:20 | case ...: | -| Switch.cs:84:19:84:19 | access to parameter j | Switch.cs:84:15:85:22 | if (...) ... | -| Switch.cs:84:19:84:23 | ... > ... | Switch.cs:84:23:84:23 | 2 | -| Switch.cs:84:23:84:23 | 2 | Switch.cs:84:19:84:19 | access to parameter j | -| Switch.cs:86:15:86:26 | return ...; | Switch.cs:86:22:86:25 | true | +| Switch.cs:81:13:81:19 | case ...: | Switch.cs:79:17:79:17 | access to parameter i | +| Switch.cs:81:18:81:18 | 1 | Switch.cs:81:13:81:19 | case ...: | +| Switch.cs:82:17:82:28 | return ...; | Switch.cs:82:24:82:27 | true | +| Switch.cs:83:18:83:18 | 2 | Switch.cs:83:13:83:19 | case ...: | +| Switch.cs:84:21:84:21 | access to parameter j | Switch.cs:84:17:85:26 | if (...) ... | +| Switch.cs:84:21:84:25 | ... > ... | Switch.cs:84:25:84:25 | 2 | +| Switch.cs:84:25:84:25 | 2 | Switch.cs:84:21:84:21 | access to parameter j | +| Switch.cs:86:17:86:28 | return ...; | Switch.cs:86:24:86:27 | true | | Switch.cs:88:9:88:21 | return ...; | Switch.cs:88:16:88:20 | false | -| Switch.cs:88:16:88:20 | false | Switch.cs:85:17:85:22 | break; | -| Switch.cs:91:10:91:11 | exit M8 | Switch.cs:96:15:96:26 | return ...; | +| Switch.cs:88:16:88:20 | false | Switch.cs:85:21:85:26 | break; | +| Switch.cs:91:10:91:11 | exit M8 | Switch.cs:96:17:96:28 | return ...; | | Switch.cs:91:10:91:11 | exit M8 | Switch.cs:98:9:98:21 | return ...; | | Switch.cs:92:5:99:5 | {...} | Switch.cs:91:10:91:11 | enter M8 | | Switch.cs:93:9:97:9 | switch (...) {...} | Switch.cs:92:5:99:5 | {...} | | Switch.cs:93:17:93:17 | access to parameter o | Switch.cs:93:9:97:9 | switch (...) {...} | -| Switch.cs:95:13:95:24 | case ...: | Switch.cs:93:17:93:17 | access to parameter o | -| Switch.cs:95:18:95:20 | access to type Int32 | Switch.cs:95:13:95:24 | case ...: | -| Switch.cs:96:15:96:26 | return ...; | Switch.cs:96:22:96:25 | true | +| Switch.cs:95:13:95:23 | case ...: | Switch.cs:93:17:93:17 | access to parameter o | +| Switch.cs:95:18:95:20 | access to type Int32 | Switch.cs:95:13:95:23 | case ...: | +| Switch.cs:96:17:96:28 | return ...; | Switch.cs:96:24:96:27 | true | | Switch.cs:98:9:98:21 | return ...; | Switch.cs:98:16:98:20 | false | -| Switch.cs:101:9:101:10 | exit M9 | Switch.cs:105:22:105:30 | return ...; | -| Switch.cs:101:9:101:10 | exit M9 | Switch.cs:106:22:106:30 | return ...; | +| Switch.cs:101:9:101:10 | exit M9 | Switch.cs:105:21:105:29 | return ...; | +| Switch.cs:101:9:101:10 | exit M9 | Switch.cs:106:21:106:29 | return ...; | | Switch.cs:101:9:101:10 | exit M9 | Switch.cs:108:9:108:18 | return ...; | | Switch.cs:102:5:109:5 | {...} | Switch.cs:101:9:101:10 | enter M9 | | Switch.cs:103:9:107:9 | switch (...) {...} | Switch.cs:102:5:109:5 | {...} | | Switch.cs:103:17:103:17 | access to parameter s | Switch.cs:103:9:107:9 | switch (...) {...} | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:103:17:103:17 | access to parameter s | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:103:19:103:25 | access to property Length | -| Switch.cs:105:18:105:18 | 0 | Switch.cs:105:13:105:20 | case ...: | -| Switch.cs:105:22:105:30 | return ...; | Switch.cs:105:29:105:29 | 0 | -| Switch.cs:106:18:106:18 | 1 | Switch.cs:106:13:106:20 | case ...: | -| Switch.cs:106:22:106:30 | return ...; | Switch.cs:106:29:106:29 | 1 | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:103:17:103:17 | access to parameter s | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:103:19:103:25 | access to property Length | +| Switch.cs:105:18:105:18 | 0 | Switch.cs:105:13:105:19 | case ...: | +| Switch.cs:105:21:105:29 | return ...; | Switch.cs:105:28:105:28 | 0 | +| Switch.cs:106:18:106:18 | 1 | Switch.cs:106:13:106:19 | case ...: | +| Switch.cs:106:21:106:29 | return ...; | Switch.cs:106:28:106:28 | 1 | | Switch.cs:108:9:108:18 | return ...; | Switch.cs:108:16:108:17 | -... | | Switch.cs:108:16:108:17 | -... | Switch.cs:108:17:108:17 | 1 | | Switch.cs:111:17:111:21 | exit Throw | Switch.cs:111:28:111:48 | throw ... | | Switch.cs:111:28:111:48 | throw ... | Switch.cs:111:34:111:48 | object creation of type Exception | | Switch.cs:111:34:111:48 | object creation of type Exception | Switch.cs:111:17:111:21 | enter Throw | -| Switch.cs:113:9:113:11 | exit M10 | Switch.cs:117:36:117:44 | return ...; | -| Switch.cs:113:9:113:11 | exit M10 | Switch.cs:118:35:118:43 | return ...; | +| Switch.cs:113:9:113:11 | exit M10 | Switch.cs:117:37:117:45 | return ...; | +| Switch.cs:113:9:113:11 | exit M10 | Switch.cs:118:36:118:44 | return ...; | | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:120:9:120:18 | return ...; | | Switch.cs:114:5:121:5 | {...} | Switch.cs:113:9:113:11 | enter M10 | | Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:114:5:121:5 | {...} | | Switch.cs:115:17:115:17 | access to parameter s | Switch.cs:115:9:119:9 | switch (...) {...} | | Switch.cs:115:17:115:24 | access to property Length | Switch.cs:115:17:115:17 | access to parameter s | -| Switch.cs:117:13:117:34 | case ...: | Switch.cs:115:17:115:24 | access to property Length | -| Switch.cs:117:18:117:18 | 3 | Switch.cs:117:13:117:34 | case ...: | -| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:117:28:117:32 | "foo" | -| Switch.cs:117:28:117:32 | "foo" | Switch.cs:117:25:117:25 | access to parameter s | -| Switch.cs:117:36:117:44 | return ...; | Switch.cs:117:43:117:43 | 1 | -| Switch.cs:118:18:118:18 | 2 | Switch.cs:118:13:118:33 | case ...: | -| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:118:28:118:31 | "fu" | -| Switch.cs:118:28:118:31 | "fu" | Switch.cs:118:25:118:25 | access to parameter s | -| Switch.cs:118:35:118:43 | return ...; | Switch.cs:118:42:118:42 | 2 | +| Switch.cs:117:13:117:35 | case ...: | Switch.cs:115:17:115:24 | access to property Length | +| Switch.cs:117:18:117:18 | 3 | Switch.cs:117:13:117:35 | case ...: | +| Switch.cs:117:25:117:34 | ... == ... | Switch.cs:117:30:117:34 | "foo" | +| Switch.cs:117:30:117:34 | "foo" | Switch.cs:117:25:117:25 | access to parameter s | +| Switch.cs:117:37:117:45 | return ...; | Switch.cs:117:44:117:44 | 1 | +| Switch.cs:118:18:118:18 | 2 | Switch.cs:118:13:118:34 | case ...: | +| Switch.cs:118:25:118:33 | ... == ... | Switch.cs:118:30:118:33 | "fu" | +| Switch.cs:118:30:118:33 | "fu" | Switch.cs:118:25:118:25 | access to parameter s | +| Switch.cs:118:36:118:44 | return ...; | Switch.cs:118:43:118:43 | 2 | | Switch.cs:120:9:120:18 | return ...; | Switch.cs:120:16:120:17 | -... | | Switch.cs:120:16:120:17 | -... | Switch.cs:120:17:120:17 | 1 | | Switch.cs:123:10:123:12 | exit M11 | Switch.cs:125:34:125:34 | access to local variable b | @@ -5684,6 +5750,28 @@ postDominance | Switch.cs:149:30:149:30 | 1 | Switch.cs:149:13:149:20 | default: | | Switch.cs:150:18:150:18 | 2 | Switch.cs:150:13:150:19 | case ...: | | Switch.cs:150:21:150:29 | return ...; | Switch.cs:150:28:150:28 | 2 | +| Switch.cs:154:10:154:12 | exit M15 | Switch.cs:156:41:156:45 | false | +| Switch.cs:154:10:154:12 | exit M15 | Switch.cs:158:13:158:48 | call to method WriteLine | +| Switch.cs:154:10:154:12 | exit M15 | Switch.cs:160:13:160:48 | call to method WriteLine | +| Switch.cs:155:5:161:5 | {...} | Switch.cs:154:10:154:12 | enter M15 | +| Switch.cs:156:9:156:55 | ... ...; | Switch.cs:155:5:161:5 | {...} | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:156:36:156:38 | "a" | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:156:50:156:52 | "b" | +| Switch.cs:156:17:156:17 | access to parameter b | Switch.cs:156:17:156:54 | ... switch { ... } | +| Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:156:9:156:55 | ... ...; | +| Switch.cs:156:28:156:31 | true | Switch.cs:156:28:156:38 | ... => ... | +| Switch.cs:156:28:156:38 | ... => ... | Switch.cs:156:17:156:17 | access to parameter b | +| Switch.cs:156:41:156:45 | false | Switch.cs:156:41:156:52 | ... => ... | +| Switch.cs:157:9:160:49 | if (...) ... | Switch.cs:156:13:156:54 | String s = ... | +| Switch.cs:157:13:157:13 | access to parameter b | Switch.cs:157:9:160:49 | if (...) ... | +| Switch.cs:158:13:158:48 | call to method WriteLine | Switch.cs:158:38:158:47 | $"..." | +| Switch.cs:158:38:158:47 | $"..." | Switch.cs:158:45:158:45 | access to local variable s | +| Switch.cs:158:40:158:43 | "a = " | Switch.cs:158:13:158:49 | ...; | +| Switch.cs:158:45:158:45 | access to local variable s | Switch.cs:158:40:158:43 | "a = " | +| Switch.cs:160:13:160:48 | call to method WriteLine | Switch.cs:160:38:160:47 | $"..." | +| Switch.cs:160:38:160:47 | $"..." | Switch.cs:160:45:160:45 | access to local variable s | +| Switch.cs:160:40:160:43 | "b = " | Switch.cs:160:13:160:49 | ...; | +| Switch.cs:160:45:160:45 | access to local variable s | Switch.cs:160:40:160:43 | "b = " | | TypeAccesses.cs:3:10:3:10 | exit M | TypeAccesses.cs:8:13:8:27 | Type t = ... | | TypeAccesses.cs:4:5:9:5 | {...} | TypeAccesses.cs:3:10:3:10 | enter M | | TypeAccesses.cs:5:9:5:26 | ... ...; | TypeAccesses.cs:4:5:9:5 | {...} | @@ -6712,20 +6800,20 @@ blockDominance | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:110:16:110:16 | access to local variable x | | Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:113:10:113:11 | enter M9 | | Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:113:10:113:11 | exit M9 | -| Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:116:24:116:24 | access to local variable i | -| Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:116:41:116:41 | access to local variable i | +| Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:116:25:116:25 | access to local variable i | +| Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:116:42:116:42 | access to local variable i | | Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:117:9:123:9 | {...} | | Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | | Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | | Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:113:10:113:11 | exit M9 | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:113:10:113:11 | exit M9 | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:24:116:24 | access to local variable i | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:41:116:41 | access to local variable i | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:117:9:123:9 | {...} | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | -| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:116:41:116:41 | access to local variable i | -| Conditions.cs:117:9:123:9 | {...} | Conditions.cs:116:41:116:41 | access to local variable i | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:113:10:113:11 | exit M9 | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:116:25:116:25 | access to local variable i | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:116:42:116:42 | access to local variable i | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:117:9:123:9 | {...} | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | +| Conditions.cs:116:42:116:42 | access to local variable i | Conditions.cs:116:42:116:42 | access to local variable i | +| Conditions.cs:117:9:123:9 | {...} | Conditions.cs:116:42:116:42 | access to local variable i | | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:117:9:123:9 | {...} | | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | @@ -6742,6 +6830,13 @@ blockDominance | Conditions.cs:134:13:139:13 | [Field1 (line 129): true] {...} | Conditions.cs:134:13:139:13 | [Field1 (line 129): true] {...} | | Conditions.cs:134:13:139:13 | [Field1 (line 129): true] {...} | Conditions.cs:136:17:138:17 | [Field1 (line 129): true, Field2 (line 129): true] {...} | | Conditions.cs:136:17:138:17 | [Field1 (line 129): true, Field2 (line 129): true] {...} | Conditions.cs:136:17:138:17 | [Field1 (line 129): true, Field2 (line 129): true] {...} | +| Conditions.cs:143:10:143:12 | enter M11 | Conditions.cs:143:10:143:12 | enter M11 | +| Conditions.cs:143:10:143:12 | enter M11 | Conditions.cs:143:10:143:12 | exit M11 | +| Conditions.cs:143:10:143:12 | enter M11 | Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | +| Conditions.cs:143:10:143:12 | enter M11 | Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | +| Conditions.cs:143:10:143:12 | exit M11 | Conditions.cs:143:10:143:12 | exit M11 | +| Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | +| Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | | ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:7:10:7:11 | enter M1 | | ExitMethods.cs:13:10:13:11 | enter M2 | ExitMethods.cs:13:10:13:11 | enter M2 | | ExitMethods.cs:19:10:19:11 | enter M3 | ExitMethods.cs:19:10:19:11 | enter M3 | @@ -8122,79 +8217,79 @@ blockDominance | Switch.cs:55:10:55:11 | enter M5 | Switch.cs:55:10:55:11 | enter M5 | | Switch.cs:66:10:66:11 | enter M6 | Switch.cs:66:10:66:11 | enter M6 | | Switch.cs:66:10:66:11 | enter M6 | Switch.cs:66:10:66:11 | exit M6 | -| Switch.cs:66:10:66:11 | enter M6 | Switch.cs:73:15:73:20 | break; | +| Switch.cs:66:10:66:11 | enter M6 | Switch.cs:73:17:73:22 | break; | | Switch.cs:66:10:66:11 | exit M6 | Switch.cs:66:10:66:11 | exit M6 | -| Switch.cs:73:15:73:20 | break; | Switch.cs:73:15:73:20 | break; | +| Switch.cs:73:17:73:22 | break; | Switch.cs:73:17:73:22 | break; | | Switch.cs:77:10:77:11 | enter M7 | Switch.cs:77:10:77:11 | enter M7 | | Switch.cs:77:10:77:11 | enter M7 | Switch.cs:77:10:77:11 | exit M7 | -| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:82:22:82:25 | true | -| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:83:13:83:20 | case ...: | -| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:84:15:85:22 | if (...) ... | -| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:85:17:85:22 | break; | -| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:86:22:86:25 | true | +| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:82:24:82:27 | true | +| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:83:13:83:19 | case ...: | +| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:84:17:85:26 | if (...) ... | +| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:85:21:85:26 | break; | +| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:86:24:86:27 | true | | Switch.cs:77:10:77:11 | enter M7 | Switch.cs:88:16:88:20 | false | | Switch.cs:77:10:77:11 | exit M7 | Switch.cs:77:10:77:11 | exit M7 | -| Switch.cs:82:22:82:25 | true | Switch.cs:82:22:82:25 | true | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:83:13:83:20 | case ...: | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:84:15:85:22 | if (...) ... | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:85:17:85:22 | break; | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:86:22:86:25 | true | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:88:16:88:20 | false | -| Switch.cs:84:15:85:22 | if (...) ... | Switch.cs:84:15:85:22 | if (...) ... | -| Switch.cs:84:15:85:22 | if (...) ... | Switch.cs:85:17:85:22 | break; | -| Switch.cs:84:15:85:22 | if (...) ... | Switch.cs:86:22:86:25 | true | -| Switch.cs:85:17:85:22 | break; | Switch.cs:85:17:85:22 | break; | -| Switch.cs:86:22:86:25 | true | Switch.cs:86:22:86:25 | true | +| Switch.cs:82:24:82:27 | true | Switch.cs:82:24:82:27 | true | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:83:13:83:19 | case ...: | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:84:17:85:26 | if (...) ... | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:85:21:85:26 | break; | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:86:24:86:27 | true | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:88:16:88:20 | false | +| Switch.cs:84:17:85:26 | if (...) ... | Switch.cs:84:17:85:26 | if (...) ... | +| Switch.cs:84:17:85:26 | if (...) ... | Switch.cs:85:21:85:26 | break; | +| Switch.cs:84:17:85:26 | if (...) ... | Switch.cs:86:24:86:27 | true | +| Switch.cs:85:21:85:26 | break; | Switch.cs:85:21:85:26 | break; | +| Switch.cs:86:24:86:27 | true | Switch.cs:86:24:86:27 | true | | Switch.cs:88:16:88:20 | false | Switch.cs:88:16:88:20 | false | | Switch.cs:91:10:91:11 | enter M8 | Switch.cs:91:10:91:11 | enter M8 | | Switch.cs:91:10:91:11 | enter M8 | Switch.cs:91:10:91:11 | exit M8 | -| Switch.cs:91:10:91:11 | enter M8 | Switch.cs:96:22:96:25 | true | +| Switch.cs:91:10:91:11 | enter M8 | Switch.cs:96:24:96:27 | true | | Switch.cs:91:10:91:11 | enter M8 | Switch.cs:98:16:98:20 | false | | Switch.cs:91:10:91:11 | exit M8 | Switch.cs:91:10:91:11 | exit M8 | -| Switch.cs:96:22:96:25 | true | Switch.cs:96:22:96:25 | true | +| Switch.cs:96:24:96:27 | true | Switch.cs:96:24:96:27 | true | | Switch.cs:98:16:98:20 | false | Switch.cs:98:16:98:20 | false | | Switch.cs:101:9:101:10 | enter M9 | Switch.cs:101:9:101:10 | enter M9 | | Switch.cs:101:9:101:10 | enter M9 | Switch.cs:101:9:101:10 | exit M9 | | Switch.cs:101:9:101:10 | enter M9 | Switch.cs:103:19:103:25 | access to property Length | -| Switch.cs:101:9:101:10 | enter M9 | Switch.cs:105:13:105:20 | case ...: | -| Switch.cs:101:9:101:10 | enter M9 | Switch.cs:105:29:105:29 | 0 | -| Switch.cs:101:9:101:10 | enter M9 | Switch.cs:106:13:106:20 | case ...: | -| Switch.cs:101:9:101:10 | enter M9 | Switch.cs:106:29:106:29 | 1 | +| Switch.cs:101:9:101:10 | enter M9 | Switch.cs:105:13:105:19 | case ...: | +| Switch.cs:101:9:101:10 | enter M9 | Switch.cs:105:28:105:28 | 0 | +| Switch.cs:101:9:101:10 | enter M9 | Switch.cs:106:13:106:19 | case ...: | +| Switch.cs:101:9:101:10 | enter M9 | Switch.cs:106:28:106:28 | 1 | | Switch.cs:101:9:101:10 | enter M9 | Switch.cs:108:17:108:17 | 1 | | Switch.cs:101:9:101:10 | exit M9 | Switch.cs:101:9:101:10 | exit M9 | | Switch.cs:103:19:103:25 | access to property Length | Switch.cs:103:19:103:25 | access to property Length | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:101:9:101:10 | exit M9 | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:105:13:105:20 | case ...: | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:105:29:105:29 | 0 | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:106:13:106:20 | case ...: | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:106:29:106:29 | 1 | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:108:17:108:17 | 1 | -| Switch.cs:105:29:105:29 | 0 | Switch.cs:105:29:105:29 | 0 | -| Switch.cs:106:13:106:20 | case ...: | Switch.cs:106:13:106:20 | case ...: | -| Switch.cs:106:13:106:20 | case ...: | Switch.cs:106:29:106:29 | 1 | -| Switch.cs:106:13:106:20 | case ...: | Switch.cs:108:17:108:17 | 1 | -| Switch.cs:106:29:106:29 | 1 | Switch.cs:106:29:106:29 | 1 | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:101:9:101:10 | exit M9 | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:105:13:105:19 | case ...: | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:105:28:105:28 | 0 | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:106:13:106:19 | case ...: | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:106:28:106:28 | 1 | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:108:17:108:17 | 1 | +| Switch.cs:105:28:105:28 | 0 | Switch.cs:105:28:105:28 | 0 | +| Switch.cs:106:13:106:19 | case ...: | Switch.cs:106:13:106:19 | case ...: | +| Switch.cs:106:13:106:19 | case ...: | Switch.cs:106:28:106:28 | 1 | +| Switch.cs:106:13:106:19 | case ...: | Switch.cs:108:17:108:17 | 1 | +| Switch.cs:106:28:106:28 | 1 | Switch.cs:106:28:106:28 | 1 | | Switch.cs:108:17:108:17 | 1 | Switch.cs:108:17:108:17 | 1 | | Switch.cs:111:17:111:21 | enter Throw | Switch.cs:111:17:111:21 | enter Throw | | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:113:9:113:11 | enter M10 | | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:113:9:113:11 | exit M10 | | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:117:25:117:25 | access to parameter s | -| Switch.cs:113:9:113:11 | enter M10 | Switch.cs:117:43:117:43 | 1 | -| Switch.cs:113:9:113:11 | enter M10 | Switch.cs:118:13:118:33 | case ...: | +| Switch.cs:113:9:113:11 | enter M10 | Switch.cs:117:44:117:44 | 1 | +| Switch.cs:113:9:113:11 | enter M10 | Switch.cs:118:13:118:34 | case ...: | | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:118:25:118:25 | access to parameter s | -| Switch.cs:113:9:113:11 | enter M10 | Switch.cs:118:42:118:42 | 2 | +| Switch.cs:113:9:113:11 | enter M10 | Switch.cs:118:43:118:43 | 2 | | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:120:17:120:17 | 1 | | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:113:9:113:11 | exit M10 | | Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:25:117:25 | access to parameter s | -| Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:43:117:43 | 1 | -| Switch.cs:117:43:117:43 | 1 | Switch.cs:117:43:117:43 | 1 | -| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:13:118:33 | case ...: | -| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:25:118:25 | access to parameter s | -| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:42:118:42 | 2 | -| Switch.cs:118:13:118:33 | case ...: | Switch.cs:120:17:120:17 | 1 | +| Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:44:117:44 | 1 | +| Switch.cs:117:44:117:44 | 1 | Switch.cs:117:44:117:44 | 1 | +| Switch.cs:118:13:118:34 | case ...: | Switch.cs:118:13:118:34 | case ...: | +| Switch.cs:118:13:118:34 | case ...: | Switch.cs:118:25:118:25 | access to parameter s | +| Switch.cs:118:13:118:34 | case ...: | Switch.cs:118:43:118:43 | 2 | +| Switch.cs:118:13:118:34 | case ...: | Switch.cs:120:17:120:17 | 1 | | Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:25:118:25 | access to parameter s | -| Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:42:118:42 | 2 | -| Switch.cs:118:42:118:42 | 2 | Switch.cs:118:42:118:42 | 2 | +| Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:43:118:43 | 2 | +| Switch.cs:118:43:118:43 | 2 | Switch.cs:118:43:118:43 | 2 | | Switch.cs:120:17:120:17 | 1 | Switch.cs:120:17:120:17 | 1 | | Switch.cs:123:10:123:12 | enter M11 | Switch.cs:123:10:123:12 | enter M11 | | Switch.cs:123:10:123:12 | enter M11 | Switch.cs:123:10:123:12 | exit M11 | @@ -8242,6 +8337,24 @@ blockDominance | Switch.cs:150:13:150:19 | case ...: | Switch.cs:150:13:150:19 | case ...: | | Switch.cs:150:13:150:19 | case ...: | Switch.cs:150:28:150:28 | 2 | | Switch.cs:150:28:150:28 | 2 | Switch.cs:150:28:150:28 | 2 | +| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:154:10:154:12 | enter M15 | +| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:154:10:154:12 | exit M15 | +| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:156:13:156:54 | String s = ... | +| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:156:36:156:38 | "a" | +| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:156:41:156:52 | ... => ... | +| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:156:50:156:52 | "b" | +| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:158:13:158:49 | ...; | +| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:160:13:160:49 | ...; | +| Switch.cs:154:10:154:12 | exit M15 | Switch.cs:154:10:154:12 | exit M15 | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:156:13:156:54 | String s = ... | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:158:13:158:49 | ...; | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:160:13:160:49 | ...; | +| Switch.cs:156:36:156:38 | "a" | Switch.cs:156:36:156:38 | "a" | +| Switch.cs:156:41:156:52 | ... => ... | Switch.cs:156:41:156:52 | ... => ... | +| Switch.cs:156:41:156:52 | ... => ... | Switch.cs:156:50:156:52 | "b" | +| Switch.cs:156:50:156:52 | "b" | Switch.cs:156:50:156:52 | "b" | +| Switch.cs:158:13:158:49 | ...; | Switch.cs:158:13:158:49 | ...; | +| Switch.cs:160:13:160:49 | ...; | Switch.cs:160:13:160:49 | ...; | | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:3:10:3:10 | enter M | | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:7:25:7:25 | ; | | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:8:9:8:28 | ... ...; | @@ -9127,21 +9240,21 @@ postBlockDominance | Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:113:10:113:11 | enter M9 | | Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:113:10:113:11 | enter M9 | | Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:113:10:113:11 | exit M9 | -| Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:116:24:116:24 | access to local variable i | -| Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:116:41:116:41 | access to local variable i | +| Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:116:25:116:25 | access to local variable i | +| Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:116:42:116:42 | access to local variable i | | Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:117:9:123:9 | {...} | | Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | | Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:113:10:113:11 | enter M9 | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:24:116:24 | access to local variable i | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:41:116:41 | access to local variable i | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:117:9:123:9 | {...} | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | -| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:116:41:116:41 | access to local variable i | -| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:117:9:123:9 | {...} | -| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | -| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:113:10:113:11 | enter M9 | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:116:25:116:25 | access to local variable i | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:116:42:116:42 | access to local variable i | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:117:9:123:9 | {...} | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | +| Conditions.cs:116:42:116:42 | access to local variable i | Conditions.cs:116:42:116:42 | access to local variable i | +| Conditions.cs:116:42:116:42 | access to local variable i | Conditions.cs:117:9:123:9 | {...} | +| Conditions.cs:116:42:116:42 | access to local variable i | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | +| Conditions.cs:116:42:116:42 | access to local variable i | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:117:9:123:9 | {...} | | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | @@ -9150,6 +9263,13 @@ postBlockDominance | Conditions.cs:131:16:131:19 | [Field1 (line 129): true, Field2 (line 129): false] true | Conditions.cs:131:16:131:19 | [Field1 (line 129): true, Field2 (line 129): false] true | | Conditions.cs:134:13:139:13 | [Field1 (line 129): true] {...} | Conditions.cs:134:13:139:13 | [Field1 (line 129): true] {...} | | Conditions.cs:136:17:138:17 | [Field1 (line 129): true, Field2 (line 129): true] {...} | Conditions.cs:136:17:138:17 | [Field1 (line 129): true, Field2 (line 129): true] {...} | +| Conditions.cs:143:10:143:12 | enter M11 | Conditions.cs:143:10:143:12 | enter M11 | +| Conditions.cs:143:10:143:12 | exit M11 | Conditions.cs:143:10:143:12 | enter M11 | +| Conditions.cs:143:10:143:12 | exit M11 | Conditions.cs:143:10:143:12 | exit M11 | +| Conditions.cs:143:10:143:12 | exit M11 | Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | +| Conditions.cs:143:10:143:12 | exit M11 | Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | +| Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | +| Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | | ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:7:10:7:11 | enter M1 | | ExitMethods.cs:13:10:13:11 | enter M2 | ExitMethods.cs:13:10:13:11 | enter M2 | | ExitMethods.cs:19:10:19:11 | enter M3 | ExitMethods.cs:19:10:19:11 | enter M3 | @@ -10120,63 +10240,63 @@ postBlockDominance | Switch.cs:66:10:66:11 | enter M6 | Switch.cs:66:10:66:11 | enter M6 | | Switch.cs:66:10:66:11 | exit M6 | Switch.cs:66:10:66:11 | enter M6 | | Switch.cs:66:10:66:11 | exit M6 | Switch.cs:66:10:66:11 | exit M6 | -| Switch.cs:66:10:66:11 | exit M6 | Switch.cs:73:15:73:20 | break; | -| Switch.cs:73:15:73:20 | break; | Switch.cs:73:15:73:20 | break; | +| Switch.cs:66:10:66:11 | exit M6 | Switch.cs:73:17:73:22 | break; | +| Switch.cs:73:17:73:22 | break; | Switch.cs:73:17:73:22 | break; | | Switch.cs:77:10:77:11 | enter M7 | Switch.cs:77:10:77:11 | enter M7 | | Switch.cs:77:10:77:11 | exit M7 | Switch.cs:77:10:77:11 | enter M7 | | Switch.cs:77:10:77:11 | exit M7 | Switch.cs:77:10:77:11 | exit M7 | -| Switch.cs:77:10:77:11 | exit M7 | Switch.cs:82:22:82:25 | true | -| Switch.cs:77:10:77:11 | exit M7 | Switch.cs:83:13:83:20 | case ...: | -| Switch.cs:77:10:77:11 | exit M7 | Switch.cs:84:15:85:22 | if (...) ... | -| Switch.cs:77:10:77:11 | exit M7 | Switch.cs:85:17:85:22 | break; | -| Switch.cs:77:10:77:11 | exit M7 | Switch.cs:86:22:86:25 | true | +| Switch.cs:77:10:77:11 | exit M7 | Switch.cs:82:24:82:27 | true | +| Switch.cs:77:10:77:11 | exit M7 | Switch.cs:83:13:83:19 | case ...: | +| Switch.cs:77:10:77:11 | exit M7 | Switch.cs:84:17:85:26 | if (...) ... | +| Switch.cs:77:10:77:11 | exit M7 | Switch.cs:85:21:85:26 | break; | +| Switch.cs:77:10:77:11 | exit M7 | Switch.cs:86:24:86:27 | true | | Switch.cs:77:10:77:11 | exit M7 | Switch.cs:88:16:88:20 | false | -| Switch.cs:82:22:82:25 | true | Switch.cs:82:22:82:25 | true | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:83:13:83:20 | case ...: | -| Switch.cs:84:15:85:22 | if (...) ... | Switch.cs:84:15:85:22 | if (...) ... | -| Switch.cs:85:17:85:22 | break; | Switch.cs:85:17:85:22 | break; | -| Switch.cs:86:22:86:25 | true | Switch.cs:86:22:86:25 | true | -| Switch.cs:88:16:88:20 | false | Switch.cs:85:17:85:22 | break; | +| Switch.cs:82:24:82:27 | true | Switch.cs:82:24:82:27 | true | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:83:13:83:19 | case ...: | +| Switch.cs:84:17:85:26 | if (...) ... | Switch.cs:84:17:85:26 | if (...) ... | +| Switch.cs:85:21:85:26 | break; | Switch.cs:85:21:85:26 | break; | +| Switch.cs:86:24:86:27 | true | Switch.cs:86:24:86:27 | true | +| Switch.cs:88:16:88:20 | false | Switch.cs:85:21:85:26 | break; | | Switch.cs:88:16:88:20 | false | Switch.cs:88:16:88:20 | false | | Switch.cs:91:10:91:11 | enter M8 | Switch.cs:91:10:91:11 | enter M8 | | Switch.cs:91:10:91:11 | exit M8 | Switch.cs:91:10:91:11 | enter M8 | | Switch.cs:91:10:91:11 | exit M8 | Switch.cs:91:10:91:11 | exit M8 | -| Switch.cs:91:10:91:11 | exit M8 | Switch.cs:96:22:96:25 | true | +| Switch.cs:91:10:91:11 | exit M8 | Switch.cs:96:24:96:27 | true | | Switch.cs:91:10:91:11 | exit M8 | Switch.cs:98:16:98:20 | false | -| Switch.cs:96:22:96:25 | true | Switch.cs:96:22:96:25 | true | +| Switch.cs:96:24:96:27 | true | Switch.cs:96:24:96:27 | true | | Switch.cs:98:16:98:20 | false | Switch.cs:98:16:98:20 | false | | Switch.cs:101:9:101:10 | enter M9 | Switch.cs:101:9:101:10 | enter M9 | | Switch.cs:101:9:101:10 | exit M9 | Switch.cs:101:9:101:10 | enter M9 | | Switch.cs:101:9:101:10 | exit M9 | Switch.cs:101:9:101:10 | exit M9 | | Switch.cs:101:9:101:10 | exit M9 | Switch.cs:103:19:103:25 | access to property Length | -| Switch.cs:101:9:101:10 | exit M9 | Switch.cs:105:13:105:20 | case ...: | -| Switch.cs:101:9:101:10 | exit M9 | Switch.cs:105:29:105:29 | 0 | -| Switch.cs:101:9:101:10 | exit M9 | Switch.cs:106:13:106:20 | case ...: | -| Switch.cs:101:9:101:10 | exit M9 | Switch.cs:106:29:106:29 | 1 | +| Switch.cs:101:9:101:10 | exit M9 | Switch.cs:105:13:105:19 | case ...: | +| Switch.cs:101:9:101:10 | exit M9 | Switch.cs:105:28:105:28 | 0 | +| Switch.cs:101:9:101:10 | exit M9 | Switch.cs:106:13:106:19 | case ...: | +| Switch.cs:101:9:101:10 | exit M9 | Switch.cs:106:28:106:28 | 1 | | Switch.cs:101:9:101:10 | exit M9 | Switch.cs:108:17:108:17 | 1 | | Switch.cs:103:19:103:25 | access to property Length | Switch.cs:103:19:103:25 | access to property Length | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:101:9:101:10 | enter M9 | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:103:19:103:25 | access to property Length | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:105:13:105:20 | case ...: | -| Switch.cs:105:29:105:29 | 0 | Switch.cs:105:29:105:29 | 0 | -| Switch.cs:106:13:106:20 | case ...: | Switch.cs:106:13:106:20 | case ...: | -| Switch.cs:106:29:106:29 | 1 | Switch.cs:106:29:106:29 | 1 | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:101:9:101:10 | enter M9 | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:103:19:103:25 | access to property Length | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:105:13:105:19 | case ...: | +| Switch.cs:105:28:105:28 | 0 | Switch.cs:105:28:105:28 | 0 | +| Switch.cs:106:13:106:19 | case ...: | Switch.cs:106:13:106:19 | case ...: | +| Switch.cs:106:28:106:28 | 1 | Switch.cs:106:28:106:28 | 1 | | Switch.cs:108:17:108:17 | 1 | Switch.cs:108:17:108:17 | 1 | | Switch.cs:111:17:111:21 | enter Throw | Switch.cs:111:17:111:21 | enter Throw | | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:113:9:113:11 | enter M10 | | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:113:9:113:11 | enter M10 | | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:113:9:113:11 | exit M10 | | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:117:25:117:25 | access to parameter s | -| Switch.cs:113:9:113:11 | exit M10 | Switch.cs:117:43:117:43 | 1 | -| Switch.cs:113:9:113:11 | exit M10 | Switch.cs:118:13:118:33 | case ...: | +| Switch.cs:113:9:113:11 | exit M10 | Switch.cs:117:44:117:44 | 1 | +| Switch.cs:113:9:113:11 | exit M10 | Switch.cs:118:13:118:34 | case ...: | | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:118:25:118:25 | access to parameter s | -| Switch.cs:113:9:113:11 | exit M10 | Switch.cs:118:42:118:42 | 2 | +| Switch.cs:113:9:113:11 | exit M10 | Switch.cs:118:43:118:43 | 2 | | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:120:17:120:17 | 1 | | Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:25:117:25 | access to parameter s | -| Switch.cs:117:43:117:43 | 1 | Switch.cs:117:43:117:43 | 1 | -| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:13:118:33 | case ...: | +| Switch.cs:117:44:117:44 | 1 | Switch.cs:117:44:117:44 | 1 | +| Switch.cs:118:13:118:34 | case ...: | Switch.cs:118:13:118:34 | case ...: | | Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:25:118:25 | access to parameter s | -| Switch.cs:118:42:118:42 | 2 | Switch.cs:118:42:118:42 | 2 | +| Switch.cs:118:43:118:43 | 2 | Switch.cs:118:43:118:43 | 2 | | Switch.cs:120:17:120:17 | 1 | Switch.cs:120:17:120:17 | 1 | | Switch.cs:123:10:123:12 | enter M11 | Switch.cs:123:10:123:12 | enter M11 | | Switch.cs:123:10:123:12 | exit M11 | Switch.cs:123:10:123:12 | enter M11 | @@ -10218,6 +10338,23 @@ postBlockDominance | Switch.cs:149:13:149:20 | default: | Switch.cs:149:13:149:20 | default: | | Switch.cs:150:13:150:19 | case ...: | Switch.cs:150:13:150:19 | case ...: | | Switch.cs:150:28:150:28 | 2 | Switch.cs:150:28:150:28 | 2 | +| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:154:10:154:12 | enter M15 | +| Switch.cs:154:10:154:12 | exit M15 | Switch.cs:154:10:154:12 | enter M15 | +| Switch.cs:154:10:154:12 | exit M15 | Switch.cs:154:10:154:12 | exit M15 | +| Switch.cs:154:10:154:12 | exit M15 | Switch.cs:156:13:156:54 | String s = ... | +| Switch.cs:154:10:154:12 | exit M15 | Switch.cs:156:36:156:38 | "a" | +| Switch.cs:154:10:154:12 | exit M15 | Switch.cs:156:41:156:52 | ... => ... | +| Switch.cs:154:10:154:12 | exit M15 | Switch.cs:156:50:156:52 | "b" | +| Switch.cs:154:10:154:12 | exit M15 | Switch.cs:158:13:158:49 | ...; | +| Switch.cs:154:10:154:12 | exit M15 | Switch.cs:160:13:160:49 | ...; | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:156:13:156:54 | String s = ... | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:156:36:156:38 | "a" | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:156:50:156:52 | "b" | +| Switch.cs:156:36:156:38 | "a" | Switch.cs:156:36:156:38 | "a" | +| Switch.cs:156:41:156:52 | ... => ... | Switch.cs:156:41:156:52 | ... => ... | +| Switch.cs:156:50:156:52 | "b" | Switch.cs:156:50:156:52 | "b" | +| Switch.cs:158:13:158:49 | ...; | Switch.cs:158:13:158:49 | ...; | +| Switch.cs:160:13:160:49 | ...; | Switch.cs:160:13:160:49 | ...; | | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:3:10:3:10 | enter M | | TypeAccesses.cs:7:25:7:25 | ; | TypeAccesses.cs:7:25:7:25 | ; | | TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:3:10:3:10 | enter M | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected index 10afd142066..79febe7779e 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected @@ -794,7 +794,7 @@ nodeEnclosing | Conditions.cs:79:17:79:26 | ...; | Conditions.cs:70:9:70:10 | M6 | | Conditions.cs:79:21:79:25 | false | Conditions.cs:70:9:70:10 | M6 | | Conditions.cs:81:9:82:16 | if (...) ... | Conditions.cs:70:9:70:10 | M6 | -| Conditions.cs:81:12:81:12 | access to local variable b | Conditions.cs:70:9:70:10 | M6 | +| Conditions.cs:81:13:81:13 | access to local variable b | Conditions.cs:70:9:70:10 | M6 | | Conditions.cs:82:13:82:13 | access to local variable x | Conditions.cs:70:9:70:10 | M6 | | Conditions.cs:82:13:82:15 | ...++ | Conditions.cs:70:9:70:10 | M6 | | Conditions.cs:82:13:82:16 | ...; | Conditions.cs:70:9:70:10 | M6 | @@ -879,14 +879,14 @@ nodeEnclosing | Conditions.cs:115:16:115:23 | String s = ... | Conditions.cs:113:10:113:11 | M9 | | Conditions.cs:115:20:115:23 | null | Conditions.cs:113:10:113:11 | M9 | | Conditions.cs:116:9:123:9 | for (...;...;...) ... | Conditions.cs:113:10:113:11 | M9 | -| Conditions.cs:116:17:116:21 | Int32 i = ... | Conditions.cs:113:10:113:11 | M9 | -| Conditions.cs:116:21:116:21 | 0 | Conditions.cs:113:10:113:11 | M9 | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:113:10:113:11 | M9 | -| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:113:10:113:11 | M9 | -| Conditions.cs:116:28:116:31 | access to parameter args | Conditions.cs:113:10:113:11 | M9 | -| Conditions.cs:116:28:116:38 | access to property Length | Conditions.cs:113:10:113:11 | M9 | -| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:113:10:113:11 | M9 | -| Conditions.cs:116:41:116:43 | ...++ | Conditions.cs:113:10:113:11 | M9 | +| Conditions.cs:116:18:116:22 | Int32 i = ... | Conditions.cs:113:10:113:11 | M9 | +| Conditions.cs:116:22:116:22 | 0 | Conditions.cs:113:10:113:11 | M9 | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:113:10:113:11 | M9 | +| Conditions.cs:116:25:116:39 | ... < ... | Conditions.cs:113:10:113:11 | M9 | +| Conditions.cs:116:29:116:32 | access to parameter args | Conditions.cs:113:10:113:11 | M9 | +| Conditions.cs:116:29:116:39 | access to property Length | Conditions.cs:113:10:113:11 | M9 | +| Conditions.cs:116:42:116:42 | access to local variable i | Conditions.cs:113:10:113:11 | M9 | +| Conditions.cs:116:42:116:44 | ...++ | Conditions.cs:113:10:113:11 | M9 | | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:113:10:113:11 | M9 | | Conditions.cs:118:13:118:44 | ... ...; | Conditions.cs:113:10:113:11 | M9 | | Conditions.cs:118:17:118:43 | Boolean last = ... | Conditions.cs:113:10:113:11 | M9 | @@ -949,6 +949,30 @@ nodeEnclosing | Conditions.cs:137:21:137:26 | [Field1 (line 129): true, Field2 (line 129): true] this access | Conditions.cs:129:10:129:12 | M10 | | Conditions.cs:137:21:137:37 | [Field1 (line 129): true, Field2 (line 129): true] call to method ToString | Conditions.cs:129:10:129:12 | M10 | | Conditions.cs:137:21:137:38 | [Field1 (line 129): true, Field2 (line 129): true] ...; | Conditions.cs:129:10:129:12 | M10 | +| Conditions.cs:143:10:143:12 | enter M11 | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:143:10:143:12 | exit M11 | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:144:5:150:5 | {...} | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:145:9:145:30 | ... ...; | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:145:13:145:29 | [b (line 143): false] String s = ... | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:145:13:145:29 | [b (line 143): true] String s = ... | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:145:17:145:17 | access to parameter b | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:145:17:145:29 | ... ? ... : ... | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:146:9:149:49 | [b (line 143): false] if (...) ... | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:146:9:149:49 | [b (line 143): true] if (...) ... | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:146:13:146:13 | [b (line 143): false] access to parameter b | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:146:13:146:13 | [b (line 143): true] access to parameter b | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:147:13:147:48 | call to method WriteLine | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:147:13:147:49 | ...; | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:147:38:147:47 | $"..." | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:147:40:147:43 | "a = " | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:147:45:147:45 | access to local variable s | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:149:13:149:48 | call to method WriteLine | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:149:13:149:49 | ...; | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:143:10:143:12 | M11 | | ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:7:10:7:11 | M1 | | ExitMethods.cs:7:10:7:11 | exit M1 | ExitMethods.cs:7:10:7:11 | M1 | | ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:7:10:7:11 | M1 | @@ -2725,7 +2749,7 @@ nodeEnclosing | Switch.cs:27:13:27:39 | case ...: | Switch.cs:10:10:10:11 | M2 | | Switch.cs:27:18:27:25 | Double d | Switch.cs:10:10:10:11 | M2 | | Switch.cs:27:32:27:38 | call to method Throw | Switch.cs:10:10:10:11 | M2 | -| Switch.cs:28:17:28:21 | Label: | Switch.cs:10:10:10:11 | M2 | +| Switch.cs:28:13:28:17 | Label: | Switch.cs:10:10:10:11 | M2 | | Switch.cs:29:17:29:23 | return ...; | Switch.cs:10:10:10:11 | M2 | | Switch.cs:30:13:30:20 | default: | Switch.cs:10:10:10:11 | M2 | | Switch.cs:31:17:31:27 | goto ...; | Switch.cs:10:10:10:11 | M2 | @@ -2755,40 +2779,40 @@ nodeEnclosing | Switch.cs:57:17:57:17 | 1 | Switch.cs:55:10:55:11 | M5 | | Switch.cs:57:17:57:21 | ... + ... | Switch.cs:55:10:55:11 | M5 | | Switch.cs:57:21:57:21 | 2 | Switch.cs:55:10:55:11 | M5 | -| Switch.cs:59:13:59:20 | case ...: | Switch.cs:55:10:55:11 | M5 | +| Switch.cs:59:13:59:19 | case ...: | Switch.cs:55:10:55:11 | M5 | | Switch.cs:59:18:59:18 | 2 | Switch.cs:55:10:55:11 | M5 | -| Switch.cs:61:13:61:20 | case ...: | Switch.cs:55:10:55:11 | M5 | +| Switch.cs:61:13:61:19 | case ...: | Switch.cs:55:10:55:11 | M5 | | Switch.cs:61:18:61:18 | 3 | Switch.cs:55:10:55:11 | M5 | -| Switch.cs:62:15:62:20 | break; | Switch.cs:55:10:55:11 | M5 | +| Switch.cs:62:17:62:22 | break; | Switch.cs:55:10:55:11 | M5 | | Switch.cs:66:10:66:11 | enter M6 | Switch.cs:66:10:66:11 | M6 | | Switch.cs:66:10:66:11 | exit M6 | Switch.cs:66:10:66:11 | M6 | | Switch.cs:67:5:75:5 | {...} | Switch.cs:66:10:66:11 | M6 | | Switch.cs:68:9:74:9 | switch (...) {...} | Switch.cs:66:10:66:11 | M6 | | Switch.cs:68:17:68:25 | (...) ... | Switch.cs:66:10:66:11 | M6 | | Switch.cs:68:25:68:25 | access to parameter s | Switch.cs:66:10:66:11 | M6 | -| Switch.cs:70:13:70:24 | case ...: | Switch.cs:66:10:66:11 | M6 | +| Switch.cs:70:13:70:23 | case ...: | Switch.cs:66:10:66:11 | M6 | | Switch.cs:70:18:70:20 | access to type Int32 | Switch.cs:66:10:66:11 | M6 | -| Switch.cs:72:13:72:21 | case ...: | Switch.cs:66:10:66:11 | M6 | +| Switch.cs:72:13:72:20 | case ...: | Switch.cs:66:10:66:11 | M6 | | Switch.cs:72:18:72:19 | "" | Switch.cs:66:10:66:11 | M6 | -| Switch.cs:73:15:73:20 | break; | Switch.cs:66:10:66:11 | M6 | +| Switch.cs:73:17:73:22 | break; | Switch.cs:66:10:66:11 | M6 | | Switch.cs:77:10:77:11 | enter M7 | Switch.cs:77:10:77:11 | M7 | | Switch.cs:77:10:77:11 | exit M7 | Switch.cs:77:10:77:11 | M7 | | Switch.cs:78:5:89:5 | {...} | Switch.cs:77:10:77:11 | M7 | | Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:77:10:77:11 | M7 | | Switch.cs:79:17:79:17 | access to parameter i | Switch.cs:77:10:77:11 | M7 | -| Switch.cs:81:13:81:20 | case ...: | Switch.cs:77:10:77:11 | M7 | +| Switch.cs:81:13:81:19 | case ...: | Switch.cs:77:10:77:11 | M7 | | Switch.cs:81:18:81:18 | 1 | Switch.cs:77:10:77:11 | M7 | -| Switch.cs:82:15:82:26 | return ...; | Switch.cs:77:10:77:11 | M7 | -| Switch.cs:82:22:82:25 | true | Switch.cs:77:10:77:11 | M7 | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:77:10:77:11 | M7 | +| Switch.cs:82:17:82:28 | return ...; | Switch.cs:77:10:77:11 | M7 | +| Switch.cs:82:24:82:27 | true | Switch.cs:77:10:77:11 | M7 | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:77:10:77:11 | M7 | | Switch.cs:83:18:83:18 | 2 | Switch.cs:77:10:77:11 | M7 | -| Switch.cs:84:15:85:22 | if (...) ... | Switch.cs:77:10:77:11 | M7 | -| Switch.cs:84:19:84:19 | access to parameter j | Switch.cs:77:10:77:11 | M7 | -| Switch.cs:84:19:84:23 | ... > ... | Switch.cs:77:10:77:11 | M7 | -| Switch.cs:84:23:84:23 | 2 | Switch.cs:77:10:77:11 | M7 | -| Switch.cs:85:17:85:22 | break; | Switch.cs:77:10:77:11 | M7 | -| Switch.cs:86:15:86:26 | return ...; | Switch.cs:77:10:77:11 | M7 | -| Switch.cs:86:22:86:25 | true | Switch.cs:77:10:77:11 | M7 | +| Switch.cs:84:17:85:26 | if (...) ... | Switch.cs:77:10:77:11 | M7 | +| Switch.cs:84:21:84:21 | access to parameter j | Switch.cs:77:10:77:11 | M7 | +| Switch.cs:84:21:84:25 | ... > ... | Switch.cs:77:10:77:11 | M7 | +| Switch.cs:84:25:84:25 | 2 | Switch.cs:77:10:77:11 | M7 | +| Switch.cs:85:21:85:26 | break; | Switch.cs:77:10:77:11 | M7 | +| Switch.cs:86:17:86:28 | return ...; | Switch.cs:77:10:77:11 | M7 | +| Switch.cs:86:24:86:27 | true | Switch.cs:77:10:77:11 | M7 | | Switch.cs:88:9:88:21 | return ...; | Switch.cs:77:10:77:11 | M7 | | Switch.cs:88:16:88:20 | false | Switch.cs:77:10:77:11 | M7 | | Switch.cs:91:10:91:11 | enter M8 | Switch.cs:91:10:91:11 | M8 | @@ -2796,10 +2820,10 @@ nodeEnclosing | Switch.cs:92:5:99:5 | {...} | Switch.cs:91:10:91:11 | M8 | | Switch.cs:93:9:97:9 | switch (...) {...} | Switch.cs:91:10:91:11 | M8 | | Switch.cs:93:17:93:17 | access to parameter o | Switch.cs:91:10:91:11 | M8 | -| Switch.cs:95:13:95:24 | case ...: | Switch.cs:91:10:91:11 | M8 | +| Switch.cs:95:13:95:23 | case ...: | Switch.cs:91:10:91:11 | M8 | | Switch.cs:95:18:95:20 | access to type Int32 | Switch.cs:91:10:91:11 | M8 | -| Switch.cs:96:15:96:26 | return ...; | Switch.cs:91:10:91:11 | M8 | -| Switch.cs:96:22:96:25 | true | Switch.cs:91:10:91:11 | M8 | +| Switch.cs:96:17:96:28 | return ...; | Switch.cs:91:10:91:11 | M8 | +| Switch.cs:96:24:96:27 | true | Switch.cs:91:10:91:11 | M8 | | Switch.cs:98:9:98:21 | return ...; | Switch.cs:91:10:91:11 | M8 | | Switch.cs:98:16:98:20 | false | Switch.cs:91:10:91:11 | M8 | | Switch.cs:101:9:101:10 | enter M9 | Switch.cs:101:9:101:10 | M9 | @@ -2808,14 +2832,14 @@ nodeEnclosing | Switch.cs:103:9:107:9 | switch (...) {...} | Switch.cs:101:9:101:10 | M9 | | Switch.cs:103:17:103:17 | access to parameter s | Switch.cs:101:9:101:10 | M9 | | Switch.cs:103:19:103:25 | access to property Length | Switch.cs:101:9:101:10 | M9 | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:101:9:101:10 | M9 | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:101:9:101:10 | M9 | | Switch.cs:105:18:105:18 | 0 | Switch.cs:101:9:101:10 | M9 | -| Switch.cs:105:22:105:30 | return ...; | Switch.cs:101:9:101:10 | M9 | -| Switch.cs:105:29:105:29 | 0 | Switch.cs:101:9:101:10 | M9 | -| Switch.cs:106:13:106:20 | case ...: | Switch.cs:101:9:101:10 | M9 | +| Switch.cs:105:21:105:29 | return ...; | Switch.cs:101:9:101:10 | M9 | +| Switch.cs:105:28:105:28 | 0 | Switch.cs:101:9:101:10 | M9 | +| Switch.cs:106:13:106:19 | case ...: | Switch.cs:101:9:101:10 | M9 | | Switch.cs:106:18:106:18 | 1 | Switch.cs:101:9:101:10 | M9 | -| Switch.cs:106:22:106:30 | return ...; | Switch.cs:101:9:101:10 | M9 | -| Switch.cs:106:29:106:29 | 1 | Switch.cs:101:9:101:10 | M9 | +| Switch.cs:106:21:106:29 | return ...; | Switch.cs:101:9:101:10 | M9 | +| Switch.cs:106:28:106:28 | 1 | Switch.cs:101:9:101:10 | M9 | | Switch.cs:108:9:108:18 | return ...; | Switch.cs:101:9:101:10 | M9 | | Switch.cs:108:16:108:17 | -... | Switch.cs:101:9:101:10 | M9 | | Switch.cs:108:17:108:17 | 1 | Switch.cs:101:9:101:10 | M9 | @@ -2829,20 +2853,20 @@ nodeEnclosing | Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:113:9:113:11 | M10 | | Switch.cs:115:17:115:17 | access to parameter s | Switch.cs:113:9:113:11 | M10 | | Switch.cs:115:17:115:24 | access to property Length | Switch.cs:113:9:113:11 | M10 | -| Switch.cs:117:13:117:34 | case ...: | Switch.cs:113:9:113:11 | M10 | +| Switch.cs:117:13:117:35 | case ...: | Switch.cs:113:9:113:11 | M10 | | Switch.cs:117:18:117:18 | 3 | Switch.cs:113:9:113:11 | M10 | | Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:113:9:113:11 | M10 | -| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:113:9:113:11 | M10 | -| Switch.cs:117:28:117:32 | "foo" | Switch.cs:113:9:113:11 | M10 | -| Switch.cs:117:36:117:44 | return ...; | Switch.cs:113:9:113:11 | M10 | -| Switch.cs:117:43:117:43 | 1 | Switch.cs:113:9:113:11 | M10 | -| Switch.cs:118:13:118:33 | case ...: | Switch.cs:113:9:113:11 | M10 | +| Switch.cs:117:25:117:34 | ... == ... | Switch.cs:113:9:113:11 | M10 | +| Switch.cs:117:30:117:34 | "foo" | Switch.cs:113:9:113:11 | M10 | +| Switch.cs:117:37:117:45 | return ...; | Switch.cs:113:9:113:11 | M10 | +| Switch.cs:117:44:117:44 | 1 | Switch.cs:113:9:113:11 | M10 | +| Switch.cs:118:13:118:34 | case ...: | Switch.cs:113:9:113:11 | M10 | | Switch.cs:118:18:118:18 | 2 | Switch.cs:113:9:113:11 | M10 | | Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:113:9:113:11 | M10 | -| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:113:9:113:11 | M10 | -| Switch.cs:118:28:118:31 | "fu" | Switch.cs:113:9:113:11 | M10 | -| Switch.cs:118:35:118:43 | return ...; | Switch.cs:113:9:113:11 | M10 | -| Switch.cs:118:42:118:42 | 2 | Switch.cs:113:9:113:11 | M10 | +| Switch.cs:118:25:118:33 | ... == ... | Switch.cs:113:9:113:11 | M10 | +| Switch.cs:118:30:118:33 | "fu" | Switch.cs:113:9:113:11 | M10 | +| Switch.cs:118:36:118:44 | return ...; | Switch.cs:113:9:113:11 | M10 | +| Switch.cs:118:43:118:43 | 2 | Switch.cs:113:9:113:11 | M10 | | Switch.cs:120:9:120:18 | return ...; | Switch.cs:113:9:113:11 | M10 | | Switch.cs:120:16:120:17 | -... | Switch.cs:113:9:113:11 | M10 | | Switch.cs:120:17:120:17 | 1 | Switch.cs:113:9:113:11 | M10 | @@ -2906,6 +2930,31 @@ nodeEnclosing | Switch.cs:150:18:150:18 | 2 | Switch.cs:144:9:144:11 | M14 | | Switch.cs:150:21:150:29 | return ...; | Switch.cs:144:9:144:11 | M14 | | Switch.cs:150:28:150:28 | 2 | Switch.cs:144:9:144:11 | M14 | +| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:154:10:154:12 | exit M15 | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:155:5:161:5 | {...} | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:156:9:156:55 | ... ...; | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:156:17:156:17 | access to parameter b | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:156:28:156:31 | true | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:156:28:156:38 | ... => ... | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:156:36:156:38 | "a" | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:156:41:156:45 | false | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:156:41:156:52 | ... => ... | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:156:50:156:52 | "b" | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:157:9:160:49 | if (...) ... | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:157:13:157:13 | access to parameter b | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:158:13:158:48 | call to method WriteLine | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:158:13:158:49 | ...; | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:158:38:158:47 | $"..." | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:158:40:158:43 | "a = " | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:158:45:158:45 | access to local variable s | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:160:13:160:48 | call to method WriteLine | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:160:13:160:49 | ...; | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:160:38:160:47 | $"..." | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:160:40:160:43 | "b = " | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:160:45:160:45 | access to local variable s | Switch.cs:154:10:154:12 | M15 | | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:3:10:3:10 | M | | TypeAccesses.cs:3:10:3:10 | exit M | TypeAccesses.cs:3:10:3:10 | M | | TypeAccesses.cs:4:5:9:5 | {...} | TypeAccesses.cs:3:10:3:10 | M | @@ -3779,8 +3828,8 @@ blockEnclosing | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:102:12:102:13 | M8 | | Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:113:10:113:11 | M9 | | Conditions.cs:113:10:113:11 | exit M9 | Conditions.cs:113:10:113:11 | M9 | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:113:10:113:11 | M9 | -| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:113:10:113:11 | M9 | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:113:10:113:11 | M9 | +| Conditions.cs:116:42:116:42 | access to local variable i | Conditions.cs:113:10:113:11 | M9 | | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:113:10:113:11 | M9 | | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | Conditions.cs:113:10:113:11 | M9 | | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | Conditions.cs:113:10:113:11 | M9 | @@ -3789,6 +3838,10 @@ blockEnclosing | Conditions.cs:131:16:131:19 | [Field1 (line 129): true, Field2 (line 129): false] true | Conditions.cs:129:10:129:12 | M10 | | Conditions.cs:134:13:139:13 | [Field1 (line 129): true] {...} | Conditions.cs:129:10:129:12 | M10 | | Conditions.cs:136:17:138:17 | [Field1 (line 129): true, Field2 (line 129): true] {...} | Conditions.cs:129:10:129:12 | M10 | +| Conditions.cs:143:10:143:12 | enter M11 | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:143:10:143:12 | exit M11 | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | Conditions.cs:143:10:143:12 | M11 | +| Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | Conditions.cs:143:10:143:12 | M11 | | ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:7:10:7:11 | M1 | | ExitMethods.cs:13:10:13:11 | enter M2 | ExitMethods.cs:13:10:13:11 | M2 | | ExitMethods.cs:19:10:19:11 | enter M3 | ExitMethods.cs:19:10:19:11 | M3 | @@ -4321,35 +4374,35 @@ blockEnclosing | Switch.cs:55:10:55:11 | enter M5 | Switch.cs:55:10:55:11 | M5 | | Switch.cs:66:10:66:11 | enter M6 | Switch.cs:66:10:66:11 | M6 | | Switch.cs:66:10:66:11 | exit M6 | Switch.cs:66:10:66:11 | M6 | -| Switch.cs:73:15:73:20 | break; | Switch.cs:66:10:66:11 | M6 | +| Switch.cs:73:17:73:22 | break; | Switch.cs:66:10:66:11 | M6 | | Switch.cs:77:10:77:11 | enter M7 | Switch.cs:77:10:77:11 | M7 | | Switch.cs:77:10:77:11 | exit M7 | Switch.cs:77:10:77:11 | M7 | -| Switch.cs:82:22:82:25 | true | Switch.cs:77:10:77:11 | M7 | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:77:10:77:11 | M7 | -| Switch.cs:84:15:85:22 | if (...) ... | Switch.cs:77:10:77:11 | M7 | -| Switch.cs:85:17:85:22 | break; | Switch.cs:77:10:77:11 | M7 | -| Switch.cs:86:22:86:25 | true | Switch.cs:77:10:77:11 | M7 | +| Switch.cs:82:24:82:27 | true | Switch.cs:77:10:77:11 | M7 | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:77:10:77:11 | M7 | +| Switch.cs:84:17:85:26 | if (...) ... | Switch.cs:77:10:77:11 | M7 | +| Switch.cs:85:21:85:26 | break; | Switch.cs:77:10:77:11 | M7 | +| Switch.cs:86:24:86:27 | true | Switch.cs:77:10:77:11 | M7 | | Switch.cs:88:16:88:20 | false | Switch.cs:77:10:77:11 | M7 | | Switch.cs:91:10:91:11 | enter M8 | Switch.cs:91:10:91:11 | M8 | | Switch.cs:91:10:91:11 | exit M8 | Switch.cs:91:10:91:11 | M8 | -| Switch.cs:96:22:96:25 | true | Switch.cs:91:10:91:11 | M8 | +| Switch.cs:96:24:96:27 | true | Switch.cs:91:10:91:11 | M8 | | Switch.cs:98:16:98:20 | false | Switch.cs:91:10:91:11 | M8 | | Switch.cs:101:9:101:10 | enter M9 | Switch.cs:101:9:101:10 | M9 | | Switch.cs:101:9:101:10 | exit M9 | Switch.cs:101:9:101:10 | M9 | | Switch.cs:103:19:103:25 | access to property Length | Switch.cs:101:9:101:10 | M9 | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:101:9:101:10 | M9 | -| Switch.cs:105:29:105:29 | 0 | Switch.cs:101:9:101:10 | M9 | -| Switch.cs:106:13:106:20 | case ...: | Switch.cs:101:9:101:10 | M9 | -| Switch.cs:106:29:106:29 | 1 | Switch.cs:101:9:101:10 | M9 | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:101:9:101:10 | M9 | +| Switch.cs:105:28:105:28 | 0 | Switch.cs:101:9:101:10 | M9 | +| Switch.cs:106:13:106:19 | case ...: | Switch.cs:101:9:101:10 | M9 | +| Switch.cs:106:28:106:28 | 1 | Switch.cs:101:9:101:10 | M9 | | Switch.cs:108:17:108:17 | 1 | Switch.cs:101:9:101:10 | M9 | | Switch.cs:111:17:111:21 | enter Throw | Switch.cs:111:17:111:21 | Throw | | Switch.cs:113:9:113:11 | enter M10 | Switch.cs:113:9:113:11 | M10 | | Switch.cs:113:9:113:11 | exit M10 | Switch.cs:113:9:113:11 | M10 | | Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:113:9:113:11 | M10 | -| Switch.cs:117:43:117:43 | 1 | Switch.cs:113:9:113:11 | M10 | -| Switch.cs:118:13:118:33 | case ...: | Switch.cs:113:9:113:11 | M10 | +| Switch.cs:117:44:117:44 | 1 | Switch.cs:113:9:113:11 | M10 | +| Switch.cs:118:13:118:34 | case ...: | Switch.cs:113:9:113:11 | M10 | | Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:113:9:113:11 | M10 | -| Switch.cs:118:42:118:42 | 2 | Switch.cs:113:9:113:11 | M10 | +| Switch.cs:118:43:118:43 | 2 | Switch.cs:113:9:113:11 | M10 | | Switch.cs:120:17:120:17 | 1 | Switch.cs:113:9:113:11 | M10 | | Switch.cs:123:10:123:12 | enter M11 | Switch.cs:123:10:123:12 | M11 | | Switch.cs:123:10:123:12 | exit M11 | Switch.cs:123:10:123:12 | M11 | @@ -4373,6 +4426,14 @@ blockEnclosing | Switch.cs:149:13:149:20 | default: | Switch.cs:144:9:144:11 | M14 | | Switch.cs:150:13:150:19 | case ...: | Switch.cs:144:9:144:11 | M14 | | Switch.cs:150:28:150:28 | 2 | Switch.cs:144:9:144:11 | M14 | +| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:154:10:154:12 | exit M15 | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:156:36:156:38 | "a" | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:156:41:156:52 | ... => ... | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:156:50:156:52 | "b" | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:158:13:158:49 | ...; | Switch.cs:154:10:154:12 | M15 | +| Switch.cs:160:13:160:49 | ...; | Switch.cs:154:10:154:12 | M15 | | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:3:10:3:10 | M | | TypeAccesses.cs:7:25:7:25 | ; | TypeAccesses.cs:3:10:3:10 | M | | TypeAccesses.cs:8:9:8:28 | ... ...; | TypeAccesses.cs:3:10:3:10 | M | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected index cf3a8c054eb..ca5f0f00d78 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected @@ -649,7 +649,7 @@ | Conditions.cs:79:17:79:26 | ...; | Conditions.cs:79:17:79:26 | ...; | | Conditions.cs:79:21:79:25 | false | Conditions.cs:79:21:79:25 | false | | Conditions.cs:81:9:82:16 | if (...) ... | Conditions.cs:81:9:82:16 | if (...) ... | -| Conditions.cs:81:12:81:12 | access to local variable b | Conditions.cs:81:12:81:12 | access to local variable b | +| Conditions.cs:81:13:81:13 | access to local variable b | Conditions.cs:81:13:81:13 | access to local variable b | | Conditions.cs:82:13:82:13 | access to local variable x | Conditions.cs:82:13:82:13 | access to local variable x | | Conditions.cs:82:13:82:15 | ...++ | Conditions.cs:82:13:82:13 | access to local variable x | | Conditions.cs:82:13:82:16 | ...; | Conditions.cs:82:13:82:16 | ...; | @@ -722,14 +722,14 @@ | Conditions.cs:115:16:115:23 | String s = ... | Conditions.cs:115:20:115:23 | null | | Conditions.cs:115:20:115:23 | null | Conditions.cs:115:20:115:23 | null | | Conditions.cs:116:9:123:9 | for (...;...;...) ... | Conditions.cs:116:9:123:9 | for (...;...;...) ... | -| Conditions.cs:116:17:116:21 | Int32 i = ... | Conditions.cs:116:21:116:21 | 0 | -| Conditions.cs:116:21:116:21 | 0 | Conditions.cs:116:21:116:21 | 0 | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:24:116:24 | access to local variable i | -| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:116:24:116:24 | access to local variable i | -| Conditions.cs:116:28:116:31 | access to parameter args | Conditions.cs:116:28:116:31 | access to parameter args | -| Conditions.cs:116:28:116:38 | access to property Length | Conditions.cs:116:28:116:31 | access to parameter args | -| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:116:41:116:41 | access to local variable i | -| Conditions.cs:116:41:116:43 | ...++ | Conditions.cs:116:41:116:41 | access to local variable i | +| Conditions.cs:116:18:116:22 | Int32 i = ... | Conditions.cs:116:22:116:22 | 0 | +| Conditions.cs:116:22:116:22 | 0 | Conditions.cs:116:22:116:22 | 0 | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:116:25:116:25 | access to local variable i | +| Conditions.cs:116:25:116:39 | ... < ... | Conditions.cs:116:25:116:25 | access to local variable i | +| Conditions.cs:116:29:116:32 | access to parameter args | Conditions.cs:116:29:116:32 | access to parameter args | +| Conditions.cs:116:29:116:39 | access to property Length | Conditions.cs:116:29:116:32 | access to parameter args | +| Conditions.cs:116:42:116:42 | access to local variable i | Conditions.cs:116:42:116:42 | access to local variable i | +| Conditions.cs:116:42:116:44 | ...++ | Conditions.cs:116:42:116:42 | access to local variable i | | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:117:9:123:9 | {...} | | Conditions.cs:118:13:118:44 | ... ...; | Conditions.cs:118:13:118:44 | ... ...; | | Conditions.cs:118:17:118:43 | Boolean last = ... | Conditions.cs:118:24:118:24 | access to local variable i | @@ -766,6 +766,25 @@ | Conditions.cs:137:21:137:26 | this access | Conditions.cs:137:21:137:26 | this access | | Conditions.cs:137:21:137:37 | call to method ToString | Conditions.cs:137:21:137:26 | this access | | Conditions.cs:137:21:137:38 | ...; | Conditions.cs:137:21:137:38 | ...; | +| Conditions.cs:144:5:150:5 | {...} | Conditions.cs:144:5:150:5 | {...} | +| Conditions.cs:145:9:145:30 | ... ...; | Conditions.cs:145:9:145:30 | ... ...; | +| Conditions.cs:145:13:145:29 | String s = ... | Conditions.cs:145:17:145:29 | ... ? ... : ... | +| Conditions.cs:145:17:145:17 | access to parameter b | Conditions.cs:145:17:145:17 | access to parameter b | +| Conditions.cs:145:17:145:29 | ... ? ... : ... | Conditions.cs:145:17:145:29 | ... ? ... : ... | +| Conditions.cs:145:21:145:23 | "a" | Conditions.cs:145:21:145:23 | "a" | +| Conditions.cs:145:27:145:29 | "b" | Conditions.cs:145:27:145:29 | "b" | +| Conditions.cs:146:9:149:49 | if (...) ... | Conditions.cs:146:9:149:49 | if (...) ... | +| Conditions.cs:146:13:146:13 | access to parameter b | Conditions.cs:146:13:146:13 | access to parameter b | +| Conditions.cs:147:13:147:48 | call to method WriteLine | Conditions.cs:147:40:147:43 | "a = " | +| Conditions.cs:147:13:147:49 | ...; | Conditions.cs:147:13:147:49 | ...; | +| Conditions.cs:147:38:147:47 | $"..." | Conditions.cs:147:40:147:43 | "a = " | +| Conditions.cs:147:40:147:43 | "a = " | Conditions.cs:147:40:147:43 | "a = " | +| Conditions.cs:147:45:147:45 | access to local variable s | Conditions.cs:147:45:147:45 | access to local variable s | +| Conditions.cs:149:13:149:48 | call to method WriteLine | Conditions.cs:149:40:149:43 | "b = " | +| Conditions.cs:149:13:149:49 | ...; | Conditions.cs:149:13:149:49 | ...; | +| Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:149:40:149:43 | "b = " | +| Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:149:40:149:43 | "b = " | +| Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:149:45:149:45 | access to local variable s | | ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:8:5:11:5 | {...} | | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | ExitMethods.cs:9:20:9:23 | true | | ExitMethods.cs:9:9:9:25 | ...; | ExitMethods.cs:9:9:9:25 | ...; | @@ -1884,7 +1903,7 @@ | Switch.cs:27:13:27:39 | case ...: | Switch.cs:27:13:27:39 | case ...: | | Switch.cs:27:18:27:25 | Double d | Switch.cs:27:18:27:25 | Double d | | Switch.cs:27:32:27:38 | call to method Throw | Switch.cs:27:32:27:38 | call to method Throw | -| Switch.cs:28:17:28:21 | Label: | Switch.cs:28:17:28:21 | Label: | +| Switch.cs:28:13:28:17 | Label: | Switch.cs:28:13:28:17 | Label: | | Switch.cs:29:17:29:23 | return ...; | Switch.cs:29:17:29:23 | return ...; | | Switch.cs:30:13:30:20 | default: | Switch.cs:30:13:30:20 | default: | | Switch.cs:31:17:31:27 | goto ...; | Switch.cs:31:17:31:27 | goto ...; | @@ -1910,61 +1929,61 @@ | Switch.cs:57:17:57:17 | 1 | Switch.cs:57:17:57:17 | 1 | | Switch.cs:57:17:57:21 | ... + ... | Switch.cs:57:17:57:17 | 1 | | Switch.cs:57:21:57:21 | 2 | Switch.cs:57:21:57:21 | 2 | -| Switch.cs:59:13:59:20 | case ...: | Switch.cs:59:13:59:20 | case ...: | +| Switch.cs:59:13:59:19 | case ...: | Switch.cs:59:13:59:19 | case ...: | | Switch.cs:59:18:59:18 | 2 | Switch.cs:59:18:59:18 | 2 | -| Switch.cs:60:15:60:20 | break; | Switch.cs:60:15:60:20 | break; | -| Switch.cs:61:13:61:20 | case ...: | Switch.cs:61:13:61:20 | case ...: | +| Switch.cs:60:17:60:22 | break; | Switch.cs:60:17:60:22 | break; | +| Switch.cs:61:13:61:19 | case ...: | Switch.cs:61:13:61:19 | case ...: | | Switch.cs:61:18:61:18 | 3 | Switch.cs:61:18:61:18 | 3 | -| Switch.cs:62:15:62:20 | break; | Switch.cs:62:15:62:20 | break; | +| Switch.cs:62:17:62:22 | break; | Switch.cs:62:17:62:22 | break; | | Switch.cs:67:5:75:5 | {...} | Switch.cs:67:5:75:5 | {...} | | Switch.cs:68:9:74:9 | switch (...) {...} | Switch.cs:68:9:74:9 | switch (...) {...} | | Switch.cs:68:17:68:25 | (...) ... | Switch.cs:68:25:68:25 | access to parameter s | | Switch.cs:68:25:68:25 | access to parameter s | Switch.cs:68:25:68:25 | access to parameter s | -| Switch.cs:70:13:70:24 | case ...: | Switch.cs:70:13:70:24 | case ...: | +| Switch.cs:70:13:70:23 | case ...: | Switch.cs:70:13:70:23 | case ...: | | Switch.cs:70:18:70:20 | access to type Int32 | Switch.cs:70:18:70:20 | access to type Int32 | -| Switch.cs:71:15:71:20 | break; | Switch.cs:71:15:71:20 | break; | -| Switch.cs:72:13:72:21 | case ...: | Switch.cs:72:13:72:21 | case ...: | +| Switch.cs:71:17:71:22 | break; | Switch.cs:71:17:71:22 | break; | +| Switch.cs:72:13:72:20 | case ...: | Switch.cs:72:13:72:20 | case ...: | | Switch.cs:72:18:72:19 | "" | Switch.cs:72:18:72:19 | "" | -| Switch.cs:73:15:73:20 | break; | Switch.cs:73:15:73:20 | break; | +| Switch.cs:73:17:73:22 | break; | Switch.cs:73:17:73:22 | break; | | Switch.cs:78:5:89:5 | {...} | Switch.cs:78:5:89:5 | {...} | | Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:79:9:87:9 | switch (...) {...} | | Switch.cs:79:17:79:17 | access to parameter i | Switch.cs:79:17:79:17 | access to parameter i | -| Switch.cs:81:13:81:20 | case ...: | Switch.cs:81:13:81:20 | case ...: | +| Switch.cs:81:13:81:19 | case ...: | Switch.cs:81:13:81:19 | case ...: | | Switch.cs:81:18:81:18 | 1 | Switch.cs:81:18:81:18 | 1 | -| Switch.cs:82:15:82:26 | return ...; | Switch.cs:82:22:82:25 | true | -| Switch.cs:82:22:82:25 | true | Switch.cs:82:22:82:25 | true | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:83:13:83:20 | case ...: | +| Switch.cs:82:17:82:28 | return ...; | Switch.cs:82:24:82:27 | true | +| Switch.cs:82:24:82:27 | true | Switch.cs:82:24:82:27 | true | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:83:13:83:19 | case ...: | | Switch.cs:83:18:83:18 | 2 | Switch.cs:83:18:83:18 | 2 | -| Switch.cs:84:15:85:22 | if (...) ... | Switch.cs:84:15:85:22 | if (...) ... | -| Switch.cs:84:19:84:19 | access to parameter j | Switch.cs:84:19:84:19 | access to parameter j | -| Switch.cs:84:19:84:23 | ... > ... | Switch.cs:84:19:84:19 | access to parameter j | -| Switch.cs:84:23:84:23 | 2 | Switch.cs:84:23:84:23 | 2 | -| Switch.cs:85:17:85:22 | break; | Switch.cs:85:17:85:22 | break; | -| Switch.cs:86:15:86:26 | return ...; | Switch.cs:86:22:86:25 | true | -| Switch.cs:86:22:86:25 | true | Switch.cs:86:22:86:25 | true | +| Switch.cs:84:17:85:26 | if (...) ... | Switch.cs:84:17:85:26 | if (...) ... | +| Switch.cs:84:21:84:21 | access to parameter j | Switch.cs:84:21:84:21 | access to parameter j | +| Switch.cs:84:21:84:25 | ... > ... | Switch.cs:84:21:84:21 | access to parameter j | +| Switch.cs:84:25:84:25 | 2 | Switch.cs:84:25:84:25 | 2 | +| Switch.cs:85:21:85:26 | break; | Switch.cs:85:21:85:26 | break; | +| Switch.cs:86:17:86:28 | return ...; | Switch.cs:86:24:86:27 | true | +| Switch.cs:86:24:86:27 | true | Switch.cs:86:24:86:27 | true | | Switch.cs:88:9:88:21 | return ...; | Switch.cs:88:16:88:20 | false | | Switch.cs:88:16:88:20 | false | Switch.cs:88:16:88:20 | false | | Switch.cs:92:5:99:5 | {...} | Switch.cs:92:5:99:5 | {...} | | Switch.cs:93:9:97:9 | switch (...) {...} | Switch.cs:93:9:97:9 | switch (...) {...} | | Switch.cs:93:17:93:17 | access to parameter o | Switch.cs:93:17:93:17 | access to parameter o | -| Switch.cs:95:13:95:24 | case ...: | Switch.cs:95:13:95:24 | case ...: | +| Switch.cs:95:13:95:23 | case ...: | Switch.cs:95:13:95:23 | case ...: | | Switch.cs:95:18:95:20 | access to type Int32 | Switch.cs:95:18:95:20 | access to type Int32 | -| Switch.cs:96:15:96:26 | return ...; | Switch.cs:96:22:96:25 | true | -| Switch.cs:96:22:96:25 | true | Switch.cs:96:22:96:25 | true | +| Switch.cs:96:17:96:28 | return ...; | Switch.cs:96:24:96:27 | true | +| Switch.cs:96:24:96:27 | true | Switch.cs:96:24:96:27 | true | | Switch.cs:98:9:98:21 | return ...; | Switch.cs:98:16:98:20 | false | | Switch.cs:98:16:98:20 | false | Switch.cs:98:16:98:20 | false | | Switch.cs:102:5:109:5 | {...} | Switch.cs:102:5:109:5 | {...} | | Switch.cs:103:9:107:9 | switch (...) {...} | Switch.cs:103:9:107:9 | switch (...) {...} | | Switch.cs:103:17:103:17 | access to parameter s | Switch.cs:103:17:103:17 | access to parameter s | | Switch.cs:103:19:103:25 | access to property Length | Switch.cs:103:17:103:17 | access to parameter s | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:105:13:105:20 | case ...: | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:105:13:105:19 | case ...: | | Switch.cs:105:18:105:18 | 0 | Switch.cs:105:18:105:18 | 0 | -| Switch.cs:105:22:105:30 | return ...; | Switch.cs:105:29:105:29 | 0 | -| Switch.cs:105:29:105:29 | 0 | Switch.cs:105:29:105:29 | 0 | -| Switch.cs:106:13:106:20 | case ...: | Switch.cs:106:13:106:20 | case ...: | +| Switch.cs:105:21:105:29 | return ...; | Switch.cs:105:28:105:28 | 0 | +| Switch.cs:105:28:105:28 | 0 | Switch.cs:105:28:105:28 | 0 | +| Switch.cs:106:13:106:19 | case ...: | Switch.cs:106:13:106:19 | case ...: | | Switch.cs:106:18:106:18 | 1 | Switch.cs:106:18:106:18 | 1 | -| Switch.cs:106:22:106:30 | return ...; | Switch.cs:106:29:106:29 | 1 | -| Switch.cs:106:29:106:29 | 1 | Switch.cs:106:29:106:29 | 1 | +| Switch.cs:106:21:106:29 | return ...; | Switch.cs:106:28:106:28 | 1 | +| Switch.cs:106:28:106:28 | 1 | Switch.cs:106:28:106:28 | 1 | | Switch.cs:108:9:108:18 | return ...; | Switch.cs:108:17:108:17 | 1 | | Switch.cs:108:16:108:17 | -... | Switch.cs:108:17:108:17 | 1 | | Switch.cs:108:17:108:17 | 1 | Switch.cs:108:17:108:17 | 1 | @@ -1974,20 +1993,20 @@ | Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:115:9:119:9 | switch (...) {...} | | Switch.cs:115:17:115:17 | access to parameter s | Switch.cs:115:17:115:17 | access to parameter s | | Switch.cs:115:17:115:24 | access to property Length | Switch.cs:115:17:115:17 | access to parameter s | -| Switch.cs:117:13:117:34 | case ...: | Switch.cs:117:13:117:34 | case ...: | +| Switch.cs:117:13:117:35 | case ...: | Switch.cs:117:13:117:35 | case ...: | | Switch.cs:117:18:117:18 | 3 | Switch.cs:117:18:117:18 | 3 | | Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:25:117:25 | access to parameter s | -| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:117:25:117:25 | access to parameter s | -| Switch.cs:117:28:117:32 | "foo" | Switch.cs:117:28:117:32 | "foo" | -| Switch.cs:117:36:117:44 | return ...; | Switch.cs:117:43:117:43 | 1 | -| Switch.cs:117:43:117:43 | 1 | Switch.cs:117:43:117:43 | 1 | -| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:13:118:33 | case ...: | +| Switch.cs:117:25:117:34 | ... == ... | Switch.cs:117:25:117:25 | access to parameter s | +| Switch.cs:117:30:117:34 | "foo" | Switch.cs:117:30:117:34 | "foo" | +| Switch.cs:117:37:117:45 | return ...; | Switch.cs:117:44:117:44 | 1 | +| Switch.cs:117:44:117:44 | 1 | Switch.cs:117:44:117:44 | 1 | +| Switch.cs:118:13:118:34 | case ...: | Switch.cs:118:13:118:34 | case ...: | | Switch.cs:118:18:118:18 | 2 | Switch.cs:118:18:118:18 | 2 | | Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:25:118:25 | access to parameter s | -| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:118:25:118:25 | access to parameter s | -| Switch.cs:118:28:118:31 | "fu" | Switch.cs:118:28:118:31 | "fu" | -| Switch.cs:118:35:118:43 | return ...; | Switch.cs:118:42:118:42 | 2 | -| Switch.cs:118:42:118:42 | 2 | Switch.cs:118:42:118:42 | 2 | +| Switch.cs:118:25:118:33 | ... == ... | Switch.cs:118:25:118:25 | access to parameter s | +| Switch.cs:118:30:118:33 | "fu" | Switch.cs:118:30:118:33 | "fu" | +| Switch.cs:118:36:118:44 | return ...; | Switch.cs:118:43:118:43 | 2 | +| Switch.cs:118:43:118:43 | 2 | Switch.cs:118:43:118:43 | 2 | | Switch.cs:120:9:120:18 | return ...; | Switch.cs:120:17:120:17 | 1 | | Switch.cs:120:16:120:17 | -... | Switch.cs:120:17:120:17 | 1 | | Switch.cs:120:17:120:17 | 1 | Switch.cs:120:17:120:17 | 1 | @@ -2043,6 +2062,29 @@ | Switch.cs:150:18:150:18 | 2 | Switch.cs:150:18:150:18 | 2 | | Switch.cs:150:21:150:29 | return ...; | Switch.cs:150:28:150:28 | 2 | | Switch.cs:150:28:150:28 | 2 | Switch.cs:150:28:150:28 | 2 | +| Switch.cs:155:5:161:5 | {...} | Switch.cs:155:5:161:5 | {...} | +| Switch.cs:156:9:156:55 | ... ...; | Switch.cs:156:9:156:55 | ... ...; | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:156:17:156:54 | ... switch { ... } | +| Switch.cs:156:17:156:17 | access to parameter b | Switch.cs:156:17:156:17 | access to parameter b | +| Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:156:17:156:54 | ... switch { ... } | +| Switch.cs:156:28:156:31 | true | Switch.cs:156:28:156:31 | true | +| Switch.cs:156:28:156:38 | ... => ... | Switch.cs:156:28:156:38 | ... => ... | +| Switch.cs:156:36:156:38 | "a" | Switch.cs:156:36:156:38 | "a" | +| Switch.cs:156:41:156:45 | false | Switch.cs:156:41:156:45 | false | +| Switch.cs:156:41:156:52 | ... => ... | Switch.cs:156:41:156:52 | ... => ... | +| Switch.cs:156:50:156:52 | "b" | Switch.cs:156:50:156:52 | "b" | +| Switch.cs:157:9:160:49 | if (...) ... | Switch.cs:157:9:160:49 | if (...) ... | +| Switch.cs:157:13:157:13 | access to parameter b | Switch.cs:157:13:157:13 | access to parameter b | +| Switch.cs:158:13:158:48 | call to method WriteLine | Switch.cs:158:40:158:43 | "a = " | +| Switch.cs:158:13:158:49 | ...; | Switch.cs:158:13:158:49 | ...; | +| Switch.cs:158:38:158:47 | $"..." | Switch.cs:158:40:158:43 | "a = " | +| Switch.cs:158:40:158:43 | "a = " | Switch.cs:158:40:158:43 | "a = " | +| Switch.cs:158:45:158:45 | access to local variable s | Switch.cs:158:45:158:45 | access to local variable s | +| Switch.cs:160:13:160:48 | call to method WriteLine | Switch.cs:160:40:160:43 | "b = " | +| Switch.cs:160:13:160:49 | ...; | Switch.cs:160:13:160:49 | ...; | +| Switch.cs:160:38:160:47 | $"..." | Switch.cs:160:40:160:43 | "b = " | +| Switch.cs:160:40:160:43 | "b = " | Switch.cs:160:40:160:43 | "b = " | +| Switch.cs:160:45:160:45 | access to local variable s | Switch.cs:160:45:160:45 | access to local variable s | | TypeAccesses.cs:4:5:9:5 | {...} | TypeAccesses.cs:4:5:9:5 | {...} | | TypeAccesses.cs:5:9:5:26 | ... ...; | TypeAccesses.cs:5:9:5:26 | ... ...; | | TypeAccesses.cs:5:13:5:25 | String s = ... | TypeAccesses.cs:5:25:5:25 | access to parameter o | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index 428ddfeca24..8af21a59cdb 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -783,10 +783,10 @@ | Conditions.cs:79:17:79:25 | ... = ... | Conditions.cs:79:17:79:25 | ... = ... | normal | | Conditions.cs:79:17:79:26 | ...; | Conditions.cs:79:17:79:25 | ... = ... | normal | | Conditions.cs:79:21:79:25 | false | Conditions.cs:79:21:79:25 | false | normal | -| Conditions.cs:81:9:82:16 | if (...) ... | Conditions.cs:81:12:81:12 | access to local variable b | false | +| Conditions.cs:81:9:82:16 | if (...) ... | Conditions.cs:81:13:81:13 | access to local variable b | false | | Conditions.cs:81:9:82:16 | if (...) ... | Conditions.cs:82:13:82:15 | ...++ | normal | -| Conditions.cs:81:12:81:12 | access to local variable b | Conditions.cs:81:12:81:12 | access to local variable b | false | -| Conditions.cs:81:12:81:12 | access to local variable b | Conditions.cs:81:12:81:12 | access to local variable b | true | +| Conditions.cs:81:13:81:13 | access to local variable b | Conditions.cs:81:13:81:13 | access to local variable b | false | +| Conditions.cs:81:13:81:13 | access to local variable b | Conditions.cs:81:13:81:13 | access to local variable b | true | | Conditions.cs:82:13:82:13 | access to local variable x | Conditions.cs:82:13:82:13 | access to local variable x | normal | | Conditions.cs:82:13:82:15 | ...++ | Conditions.cs:82:13:82:15 | ...++ | normal | | Conditions.cs:82:13:82:16 | ...; | Conditions.cs:82:13:82:15 | ...++ | normal | @@ -869,20 +869,20 @@ | Conditions.cs:109:22:109:23 | "" | Conditions.cs:109:22:109:23 | "" | normal | | Conditions.cs:110:9:110:17 | return ...; | Conditions.cs:110:9:110:17 | return ...; | return | | Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:110:16:110:16 | access to local variable x | normal | -| Conditions.cs:114:5:124:5 | {...} | Conditions.cs:116:24:116:38 | ... < ... | false | +| Conditions.cs:114:5:124:5 | {...} | Conditions.cs:116:25:116:39 | ... < ... | false | | Conditions.cs:115:9:115:24 | ... ...; | Conditions.cs:115:16:115:23 | String s = ... | normal | | Conditions.cs:115:16:115:23 | String s = ... | Conditions.cs:115:16:115:23 | String s = ... | normal | | Conditions.cs:115:20:115:23 | null | Conditions.cs:115:20:115:23 | null | normal | -| Conditions.cs:116:9:123:9 | for (...;...;...) ... | Conditions.cs:116:24:116:38 | ... < ... | false | -| Conditions.cs:116:17:116:21 | Int32 i = ... | Conditions.cs:116:17:116:21 | Int32 i = ... | normal | -| Conditions.cs:116:21:116:21 | 0 | Conditions.cs:116:21:116:21 | 0 | normal | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:24:116:24 | access to local variable i | normal | -| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:116:24:116:38 | ... < ... | false | -| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:116:24:116:38 | ... < ... | true | -| Conditions.cs:116:28:116:31 | access to parameter args | Conditions.cs:116:28:116:31 | access to parameter args | normal | -| Conditions.cs:116:28:116:38 | access to property Length | Conditions.cs:116:28:116:38 | access to property Length | normal | -| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:116:41:116:41 | access to local variable i | normal | -| Conditions.cs:116:41:116:43 | ...++ | Conditions.cs:116:41:116:43 | ...++ | normal | +| Conditions.cs:116:9:123:9 | for (...;...;...) ... | Conditions.cs:116:25:116:39 | ... < ... | false | +| Conditions.cs:116:18:116:22 | Int32 i = ... | Conditions.cs:116:18:116:22 | Int32 i = ... | normal | +| Conditions.cs:116:22:116:22 | 0 | Conditions.cs:116:22:116:22 | 0 | normal | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:116:25:116:25 | access to local variable i | normal | +| Conditions.cs:116:25:116:39 | ... < ... | Conditions.cs:116:25:116:39 | ... < ... | false | +| Conditions.cs:116:25:116:39 | ... < ... | Conditions.cs:116:25:116:39 | ... < ... | true | +| Conditions.cs:116:29:116:32 | access to parameter args | Conditions.cs:116:29:116:32 | access to parameter args | normal | +| Conditions.cs:116:29:116:39 | access to property Length | Conditions.cs:116:29:116:39 | access to property Length | normal | +| Conditions.cs:116:42:116:42 | access to local variable i | Conditions.cs:116:42:116:42 | access to local variable i | normal | +| Conditions.cs:116:42:116:44 | ...++ | Conditions.cs:116:42:116:44 | ...++ | normal | | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:121:17:121:20 | access to local variable last | false | | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:122:17:122:24 | ... = ... | normal | | Conditions.cs:118:13:118:44 | ... ...; | Conditions.cs:118:17:118:43 | Boolean last = ... | normal | @@ -931,6 +931,30 @@ | Conditions.cs:137:21:137:26 | this access | Conditions.cs:137:21:137:26 | this access | normal | | Conditions.cs:137:21:137:37 | call to method ToString | Conditions.cs:137:21:137:37 | call to method ToString | normal | | Conditions.cs:137:21:137:38 | ...; | Conditions.cs:137:21:137:37 | call to method ToString | normal | +| Conditions.cs:144:5:150:5 | {...} | Conditions.cs:147:13:147:48 | call to method WriteLine | normal | +| Conditions.cs:144:5:150:5 | {...} | Conditions.cs:149:13:149:48 | call to method WriteLine | normal | +| Conditions.cs:145:9:145:30 | ... ...; | Conditions.cs:145:13:145:29 | String s = ... | normal | +| Conditions.cs:145:13:145:29 | String s = ... | Conditions.cs:145:13:145:29 | String s = ... | normal | +| Conditions.cs:145:17:145:17 | access to parameter b | Conditions.cs:145:17:145:17 | access to parameter b | false | +| Conditions.cs:145:17:145:17 | access to parameter b | Conditions.cs:145:17:145:17 | access to parameter b | true | +| Conditions.cs:145:17:145:29 | ... ? ... : ... | Conditions.cs:145:21:145:23 | "a" | normal | +| Conditions.cs:145:17:145:29 | ... ? ... : ... | Conditions.cs:145:27:145:29 | "b" | normal | +| Conditions.cs:145:21:145:23 | "a" | Conditions.cs:145:21:145:23 | "a" | normal | +| Conditions.cs:145:27:145:29 | "b" | Conditions.cs:145:27:145:29 | "b" | normal | +| Conditions.cs:146:9:149:49 | if (...) ... | Conditions.cs:147:13:147:48 | call to method WriteLine | normal | +| Conditions.cs:146:9:149:49 | if (...) ... | Conditions.cs:149:13:149:48 | call to method WriteLine | normal | +| Conditions.cs:146:13:146:13 | access to parameter b | Conditions.cs:146:13:146:13 | access to parameter b | false | +| Conditions.cs:146:13:146:13 | access to parameter b | Conditions.cs:146:13:146:13 | access to parameter b | true | +| Conditions.cs:147:13:147:48 | call to method WriteLine | Conditions.cs:147:13:147:48 | call to method WriteLine | normal | +| Conditions.cs:147:13:147:49 | ...; | Conditions.cs:147:13:147:48 | call to method WriteLine | normal | +| Conditions.cs:147:38:147:47 | $"..." | Conditions.cs:147:38:147:47 | $"..." | normal | +| Conditions.cs:147:40:147:43 | "a = " | Conditions.cs:147:40:147:43 | "a = " | normal | +| Conditions.cs:147:45:147:45 | access to local variable s | Conditions.cs:147:45:147:45 | access to local variable s | normal | +| Conditions.cs:149:13:149:48 | call to method WriteLine | Conditions.cs:149:13:149:48 | call to method WriteLine | normal | +| Conditions.cs:149:13:149:49 | ...; | Conditions.cs:149:13:149:48 | call to method WriteLine | normal | +| Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:149:38:149:47 | $"..." | normal | +| Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:149:40:149:43 | "b = " | normal | +| Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:149:45:149:45 | access to local variable s | normal | | ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:10:9:10:15 | return ...; | return | | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | normal | | ExitMethods.cs:9:9:9:25 | ...; | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | normal | @@ -2487,11 +2511,11 @@ | Switch.cs:26:17:26:23 | return ...; | Switch.cs:26:17:26:23 | return ...; | return | | Switch.cs:27:13:27:39 | case ...: | Switch.cs:27:18:27:25 | Double d | no-match | | Switch.cs:27:13:27:39 | case ...: | Switch.cs:27:32:27:38 | call to method Throw | throw(Exception) | -| Switch.cs:27:13:27:39 | case ...: | Switch.cs:28:17:28:21 | Label: | normal | +| Switch.cs:27:13:27:39 | case ...: | Switch.cs:28:13:28:17 | Label: | normal | | Switch.cs:27:18:27:25 | Double d | Switch.cs:27:18:27:25 | Double d | match | | Switch.cs:27:18:27:25 | Double d | Switch.cs:27:18:27:25 | Double d | no-match | | Switch.cs:27:32:27:38 | call to method Throw | Switch.cs:27:32:27:38 | call to method Throw | throw(Exception) | -| Switch.cs:28:17:28:21 | Label: | Switch.cs:28:17:28:21 | Label: | normal | +| Switch.cs:28:13:28:17 | Label: | Switch.cs:28:13:28:17 | Label: | normal | | Switch.cs:29:17:29:23 | return ...; | Switch.cs:29:17:29:23 | return ...; | return | | Switch.cs:30:13:30:20 | default: | Switch.cs:31:17:31:27 | goto ...; | goto(Label) | | Switch.cs:31:17:31:27 | goto ...; | Switch.cs:31:17:31:27 | goto ...; | goto(Label) | @@ -2526,138 +2550,138 @@ | Switch.cs:50:30:50:38 | ... != ... | Switch.cs:50:30:50:38 | ... != ... | true | | Switch.cs:50:35:50:38 | null | Switch.cs:50:35:50:38 | null | normal | | Switch.cs:51:17:51:22 | break; | Switch.cs:51:17:51:22 | break; | break | -| Switch.cs:56:5:64:5 | {...} | Switch.cs:60:15:60:20 | break; | normal (break) | -| Switch.cs:56:5:64:5 | {...} | Switch.cs:62:15:62:20 | break; | normal (break) | -| Switch.cs:57:9:63:9 | switch (...) {...} | Switch.cs:60:15:60:20 | break; | normal (break) | -| Switch.cs:57:9:63:9 | switch (...) {...} | Switch.cs:62:15:62:20 | break; | normal (break) | +| Switch.cs:56:5:64:5 | {...} | Switch.cs:60:17:60:22 | break; | normal (break) | +| Switch.cs:56:5:64:5 | {...} | Switch.cs:62:17:62:22 | break; | normal (break) | +| Switch.cs:57:9:63:9 | switch (...) {...} | Switch.cs:60:17:60:22 | break; | normal (break) | +| Switch.cs:57:9:63:9 | switch (...) {...} | Switch.cs:62:17:62:22 | break; | normal (break) | | Switch.cs:57:17:57:17 | 1 | Switch.cs:57:17:57:17 | 1 | normal | | Switch.cs:57:17:57:21 | ... + ... | Switch.cs:57:17:57:21 | ... + ... | normal | | Switch.cs:57:21:57:21 | 2 | Switch.cs:57:21:57:21 | 2 | normal | -| Switch.cs:59:13:59:20 | case ...: | Switch.cs:59:18:59:18 | 2 | no-match | -| Switch.cs:59:13:59:20 | case ...: | Switch.cs:60:15:60:20 | break; | break | +| Switch.cs:59:13:59:19 | case ...: | Switch.cs:59:18:59:18 | 2 | no-match | +| Switch.cs:59:13:59:19 | case ...: | Switch.cs:60:17:60:22 | break; | break | | Switch.cs:59:18:59:18 | 2 | Switch.cs:59:18:59:18 | 2 | no-match | -| Switch.cs:60:15:60:20 | break; | Switch.cs:60:15:60:20 | break; | break | -| Switch.cs:61:13:61:20 | case ...: | Switch.cs:62:15:62:20 | break; | break | +| Switch.cs:60:17:60:22 | break; | Switch.cs:60:17:60:22 | break; | break | +| Switch.cs:61:13:61:19 | case ...: | Switch.cs:62:17:62:22 | break; | break | | Switch.cs:61:18:61:18 | 3 | Switch.cs:61:18:61:18 | 3 | match | -| Switch.cs:62:15:62:20 | break; | Switch.cs:62:15:62:20 | break; | break | -| Switch.cs:67:5:75:5 | {...} | Switch.cs:71:15:71:20 | break; | normal (break) | +| Switch.cs:62:17:62:22 | break; | Switch.cs:62:17:62:22 | break; | break | +| Switch.cs:67:5:75:5 | {...} | Switch.cs:71:17:71:22 | break; | normal (break) | | Switch.cs:67:5:75:5 | {...} | Switch.cs:72:18:72:19 | "" | no-match | -| Switch.cs:67:5:75:5 | {...} | Switch.cs:73:15:73:20 | break; | normal (break) | -| Switch.cs:68:9:74:9 | switch (...) {...} | Switch.cs:71:15:71:20 | break; | normal (break) | +| Switch.cs:67:5:75:5 | {...} | Switch.cs:73:17:73:22 | break; | normal (break) | +| Switch.cs:68:9:74:9 | switch (...) {...} | Switch.cs:71:17:71:22 | break; | normal (break) | | Switch.cs:68:9:74:9 | switch (...) {...} | Switch.cs:72:18:72:19 | "" | no-match | -| Switch.cs:68:9:74:9 | switch (...) {...} | Switch.cs:73:15:73:20 | break; | normal (break) | +| Switch.cs:68:9:74:9 | switch (...) {...} | Switch.cs:73:17:73:22 | break; | normal (break) | | Switch.cs:68:17:68:25 | (...) ... | Switch.cs:68:17:68:25 | (...) ... | normal | | Switch.cs:68:25:68:25 | access to parameter s | Switch.cs:68:25:68:25 | access to parameter s | normal | -| Switch.cs:70:13:70:24 | case ...: | Switch.cs:70:18:70:20 | access to type Int32 | no-match | -| Switch.cs:70:13:70:24 | case ...: | Switch.cs:71:15:71:20 | break; | break | +| Switch.cs:70:13:70:23 | case ...: | Switch.cs:70:18:70:20 | access to type Int32 | no-match | +| Switch.cs:70:13:70:23 | case ...: | Switch.cs:71:17:71:22 | break; | break | | Switch.cs:70:18:70:20 | access to type Int32 | Switch.cs:70:18:70:20 | access to type Int32 | no-match | -| Switch.cs:71:15:71:20 | break; | Switch.cs:71:15:71:20 | break; | break | -| Switch.cs:72:13:72:21 | case ...: | Switch.cs:72:18:72:19 | "" | no-match | -| Switch.cs:72:13:72:21 | case ...: | Switch.cs:73:15:73:20 | break; | break | +| Switch.cs:71:17:71:22 | break; | Switch.cs:71:17:71:22 | break; | break | +| Switch.cs:72:13:72:20 | case ...: | Switch.cs:72:18:72:19 | "" | no-match | +| Switch.cs:72:13:72:20 | case ...: | Switch.cs:73:17:73:22 | break; | break | | Switch.cs:72:18:72:19 | "" | Switch.cs:72:18:72:19 | "" | match | | Switch.cs:72:18:72:19 | "" | Switch.cs:72:18:72:19 | "" | no-match | -| Switch.cs:73:15:73:20 | break; | Switch.cs:73:15:73:20 | break; | break | -| Switch.cs:78:5:89:5 | {...} | Switch.cs:82:15:82:26 | return ...; | return | -| Switch.cs:78:5:89:5 | {...} | Switch.cs:86:15:86:26 | return ...; | return | +| Switch.cs:73:17:73:22 | break; | Switch.cs:73:17:73:22 | break; | break | +| Switch.cs:78:5:89:5 | {...} | Switch.cs:82:17:82:28 | return ...; | return | +| Switch.cs:78:5:89:5 | {...} | Switch.cs:86:17:86:28 | return ...; | return | | Switch.cs:78:5:89:5 | {...} | Switch.cs:88:9:88:21 | return ...; | return | -| Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:82:15:82:26 | return ...; | return | +| Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:82:17:82:28 | return ...; | return | | Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:83:18:83:18 | 2 | no-match | -| Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:85:17:85:22 | break; | normal (break) | -| Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:86:15:86:26 | return ...; | return | +| Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:85:21:85:26 | break; | normal (break) | +| Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:86:17:86:28 | return ...; | return | | Switch.cs:79:17:79:17 | access to parameter i | Switch.cs:79:17:79:17 | access to parameter i | normal | -| Switch.cs:81:13:81:20 | case ...: | Switch.cs:81:18:81:18 | 1 | no-match | -| Switch.cs:81:13:81:20 | case ...: | Switch.cs:82:15:82:26 | return ...; | return | +| Switch.cs:81:13:81:19 | case ...: | Switch.cs:81:18:81:18 | 1 | no-match | +| Switch.cs:81:13:81:19 | case ...: | Switch.cs:82:17:82:28 | return ...; | return | | Switch.cs:81:18:81:18 | 1 | Switch.cs:81:18:81:18 | 1 | match | | Switch.cs:81:18:81:18 | 1 | Switch.cs:81:18:81:18 | 1 | no-match | -| Switch.cs:82:15:82:26 | return ...; | Switch.cs:82:15:82:26 | return ...; | return | -| Switch.cs:82:22:82:25 | true | Switch.cs:82:22:82:25 | true | normal | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:83:18:83:18 | 2 | no-match | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:84:19:84:23 | ... > ... | false | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:85:17:85:22 | break; | break | +| Switch.cs:82:17:82:28 | return ...; | Switch.cs:82:17:82:28 | return ...; | return | +| Switch.cs:82:24:82:27 | true | Switch.cs:82:24:82:27 | true | normal | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:83:18:83:18 | 2 | no-match | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:84:21:84:25 | ... > ... | false | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:85:21:85:26 | break; | break | | Switch.cs:83:18:83:18 | 2 | Switch.cs:83:18:83:18 | 2 | match | | Switch.cs:83:18:83:18 | 2 | Switch.cs:83:18:83:18 | 2 | no-match | -| Switch.cs:84:15:85:22 | if (...) ... | Switch.cs:84:19:84:23 | ... > ... | false | -| Switch.cs:84:15:85:22 | if (...) ... | Switch.cs:85:17:85:22 | break; | break | -| Switch.cs:84:19:84:19 | access to parameter j | Switch.cs:84:19:84:19 | access to parameter j | normal | -| Switch.cs:84:19:84:23 | ... > ... | Switch.cs:84:19:84:23 | ... > ... | false | -| Switch.cs:84:19:84:23 | ... > ... | Switch.cs:84:19:84:23 | ... > ... | true | -| Switch.cs:84:23:84:23 | 2 | Switch.cs:84:23:84:23 | 2 | normal | -| Switch.cs:85:17:85:22 | break; | Switch.cs:85:17:85:22 | break; | break | -| Switch.cs:86:15:86:26 | return ...; | Switch.cs:86:15:86:26 | return ...; | return | -| Switch.cs:86:22:86:25 | true | Switch.cs:86:22:86:25 | true | normal | +| Switch.cs:84:17:85:26 | if (...) ... | Switch.cs:84:21:84:25 | ... > ... | false | +| Switch.cs:84:17:85:26 | if (...) ... | Switch.cs:85:21:85:26 | break; | break | +| Switch.cs:84:21:84:21 | access to parameter j | Switch.cs:84:21:84:21 | access to parameter j | normal | +| Switch.cs:84:21:84:25 | ... > ... | Switch.cs:84:21:84:25 | ... > ... | false | +| Switch.cs:84:21:84:25 | ... > ... | Switch.cs:84:21:84:25 | ... > ... | true | +| Switch.cs:84:25:84:25 | 2 | Switch.cs:84:25:84:25 | 2 | normal | +| Switch.cs:85:21:85:26 | break; | Switch.cs:85:21:85:26 | break; | break | +| Switch.cs:86:17:86:28 | return ...; | Switch.cs:86:17:86:28 | return ...; | return | +| Switch.cs:86:24:86:27 | true | Switch.cs:86:24:86:27 | true | normal | | Switch.cs:88:9:88:21 | return ...; | Switch.cs:88:9:88:21 | return ...; | return | | Switch.cs:88:16:88:20 | false | Switch.cs:88:16:88:20 | false | normal | -| Switch.cs:92:5:99:5 | {...} | Switch.cs:96:15:96:26 | return ...; | return | +| Switch.cs:92:5:99:5 | {...} | Switch.cs:96:17:96:28 | return ...; | return | | Switch.cs:92:5:99:5 | {...} | Switch.cs:98:9:98:21 | return ...; | return | | Switch.cs:93:9:97:9 | switch (...) {...} | Switch.cs:95:18:95:20 | access to type Int32 | no-match | -| Switch.cs:93:9:97:9 | switch (...) {...} | Switch.cs:96:15:96:26 | return ...; | return | +| Switch.cs:93:9:97:9 | switch (...) {...} | Switch.cs:96:17:96:28 | return ...; | return | | Switch.cs:93:17:93:17 | access to parameter o | Switch.cs:93:17:93:17 | access to parameter o | normal | -| Switch.cs:95:13:95:24 | case ...: | Switch.cs:95:18:95:20 | access to type Int32 | no-match | -| Switch.cs:95:13:95:24 | case ...: | Switch.cs:96:15:96:26 | return ...; | return | +| Switch.cs:95:13:95:23 | case ...: | Switch.cs:95:18:95:20 | access to type Int32 | no-match | +| Switch.cs:95:13:95:23 | case ...: | Switch.cs:96:17:96:28 | return ...; | return | | Switch.cs:95:18:95:20 | access to type Int32 | Switch.cs:95:18:95:20 | access to type Int32 | match | | Switch.cs:95:18:95:20 | access to type Int32 | Switch.cs:95:18:95:20 | access to type Int32 | no-match | -| Switch.cs:96:15:96:26 | return ...; | Switch.cs:96:15:96:26 | return ...; | return | -| Switch.cs:96:22:96:25 | true | Switch.cs:96:22:96:25 | true | normal | +| Switch.cs:96:17:96:28 | return ...; | Switch.cs:96:17:96:28 | return ...; | return | +| Switch.cs:96:24:96:27 | true | Switch.cs:96:24:96:27 | true | normal | | Switch.cs:98:9:98:21 | return ...; | Switch.cs:98:9:98:21 | return ...; | return | | Switch.cs:98:16:98:20 | false | Switch.cs:98:16:98:20 | false | normal | -| Switch.cs:102:5:109:5 | {...} | Switch.cs:105:22:105:30 | return ...; | return | -| Switch.cs:102:5:109:5 | {...} | Switch.cs:106:22:106:30 | return ...; | return | +| Switch.cs:102:5:109:5 | {...} | Switch.cs:105:21:105:29 | return ...; | return | +| Switch.cs:102:5:109:5 | {...} | Switch.cs:106:21:106:29 | return ...; | return | | Switch.cs:102:5:109:5 | {...} | Switch.cs:108:9:108:18 | return ...; | return | -| Switch.cs:103:9:107:9 | switch (...) {...} | Switch.cs:105:22:105:30 | return ...; | return | +| Switch.cs:103:9:107:9 | switch (...) {...} | Switch.cs:105:21:105:29 | return ...; | return | | Switch.cs:103:9:107:9 | switch (...) {...} | Switch.cs:106:18:106:18 | 1 | no-match | -| Switch.cs:103:9:107:9 | switch (...) {...} | Switch.cs:106:22:106:30 | return ...; | return | +| Switch.cs:103:9:107:9 | switch (...) {...} | Switch.cs:106:21:106:29 | return ...; | return | | Switch.cs:103:17:103:17 | access to parameter s | Switch.cs:103:17:103:17 | access to parameter s | non-null | | Switch.cs:103:17:103:17 | access to parameter s | Switch.cs:103:17:103:17 | access to parameter s | null | | Switch.cs:103:19:103:25 | access to property Length | Switch.cs:103:17:103:17 | access to parameter s | null | | Switch.cs:103:19:103:25 | access to property Length | Switch.cs:103:19:103:25 | access to property Length | normal | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:105:18:105:18 | 0 | no-match | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:105:22:105:30 | return ...; | return | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:105:18:105:18 | 0 | no-match | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:105:21:105:29 | return ...; | return | | Switch.cs:105:18:105:18 | 0 | Switch.cs:105:18:105:18 | 0 | match | | Switch.cs:105:18:105:18 | 0 | Switch.cs:105:18:105:18 | 0 | no-match | -| Switch.cs:105:22:105:30 | return ...; | Switch.cs:105:22:105:30 | return ...; | return | -| Switch.cs:105:29:105:29 | 0 | Switch.cs:105:29:105:29 | 0 | normal | -| Switch.cs:106:13:106:20 | case ...: | Switch.cs:106:18:106:18 | 1 | no-match | -| Switch.cs:106:13:106:20 | case ...: | Switch.cs:106:22:106:30 | return ...; | return | +| Switch.cs:105:21:105:29 | return ...; | Switch.cs:105:21:105:29 | return ...; | return | +| Switch.cs:105:28:105:28 | 0 | Switch.cs:105:28:105:28 | 0 | normal | +| Switch.cs:106:13:106:19 | case ...: | Switch.cs:106:18:106:18 | 1 | no-match | +| Switch.cs:106:13:106:19 | case ...: | Switch.cs:106:21:106:29 | return ...; | return | | Switch.cs:106:18:106:18 | 1 | Switch.cs:106:18:106:18 | 1 | match | | Switch.cs:106:18:106:18 | 1 | Switch.cs:106:18:106:18 | 1 | no-match | -| Switch.cs:106:22:106:30 | return ...; | Switch.cs:106:22:106:30 | return ...; | return | -| Switch.cs:106:29:106:29 | 1 | Switch.cs:106:29:106:29 | 1 | normal | +| Switch.cs:106:21:106:29 | return ...; | Switch.cs:106:21:106:29 | return ...; | return | +| Switch.cs:106:28:106:28 | 1 | Switch.cs:106:28:106:28 | 1 | normal | | Switch.cs:108:9:108:18 | return ...; | Switch.cs:108:9:108:18 | return ...; | return | | Switch.cs:108:16:108:17 | -... | Switch.cs:108:16:108:17 | -... | normal | | Switch.cs:108:17:108:17 | 1 | Switch.cs:108:17:108:17 | 1 | normal | | Switch.cs:111:28:111:48 | throw ... | Switch.cs:111:28:111:48 | throw ... | throw(Exception) | | Switch.cs:111:34:111:48 | object creation of type Exception | Switch.cs:111:34:111:48 | object creation of type Exception | normal | -| Switch.cs:114:5:121:5 | {...} | Switch.cs:117:36:117:44 | return ...; | return | -| Switch.cs:114:5:121:5 | {...} | Switch.cs:118:35:118:43 | return ...; | return | +| Switch.cs:114:5:121:5 | {...} | Switch.cs:117:37:117:45 | return ...; | return | +| Switch.cs:114:5:121:5 | {...} | Switch.cs:118:36:118:44 | return ...; | return | | Switch.cs:114:5:121:5 | {...} | Switch.cs:120:9:120:18 | return ...; | return | -| Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:117:36:117:44 | return ...; | return | +| Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:117:37:117:45 | return ...; | return | | Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:118:18:118:18 | 2 | no-match | -| Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:118:25:118:31 | ... == ... | false | -| Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:118:35:118:43 | return ...; | return | +| Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:118:25:118:33 | ... == ... | false | +| Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:118:36:118:44 | return ...; | return | | Switch.cs:115:17:115:17 | access to parameter s | Switch.cs:115:17:115:17 | access to parameter s | normal | | Switch.cs:115:17:115:24 | access to property Length | Switch.cs:115:17:115:24 | access to property Length | normal | -| Switch.cs:117:13:117:34 | case ...: | Switch.cs:117:18:117:18 | 3 | no-match | -| Switch.cs:117:13:117:34 | case ...: | Switch.cs:117:25:117:32 | ... == ... | false | -| Switch.cs:117:13:117:34 | case ...: | Switch.cs:117:36:117:44 | return ...; | return | +| Switch.cs:117:13:117:35 | case ...: | Switch.cs:117:18:117:18 | 3 | no-match | +| Switch.cs:117:13:117:35 | case ...: | Switch.cs:117:25:117:34 | ... == ... | false | +| Switch.cs:117:13:117:35 | case ...: | Switch.cs:117:37:117:45 | return ...; | return | | Switch.cs:117:18:117:18 | 3 | Switch.cs:117:18:117:18 | 3 | match | | Switch.cs:117:18:117:18 | 3 | Switch.cs:117:18:117:18 | 3 | no-match | | Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:25:117:25 | access to parameter s | normal | -| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:117:25:117:32 | ... == ... | false | -| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:117:25:117:32 | ... == ... | true | -| Switch.cs:117:28:117:32 | "foo" | Switch.cs:117:28:117:32 | "foo" | normal | -| Switch.cs:117:36:117:44 | return ...; | Switch.cs:117:36:117:44 | return ...; | return | -| Switch.cs:117:43:117:43 | 1 | Switch.cs:117:43:117:43 | 1 | normal | -| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:18:118:18 | 2 | no-match | -| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:25:118:31 | ... == ... | false | -| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:35:118:43 | return ...; | return | +| Switch.cs:117:25:117:34 | ... == ... | Switch.cs:117:25:117:34 | ... == ... | false | +| Switch.cs:117:25:117:34 | ... == ... | Switch.cs:117:25:117:34 | ... == ... | true | +| Switch.cs:117:30:117:34 | "foo" | Switch.cs:117:30:117:34 | "foo" | normal | +| Switch.cs:117:37:117:45 | return ...; | Switch.cs:117:37:117:45 | return ...; | return | +| Switch.cs:117:44:117:44 | 1 | Switch.cs:117:44:117:44 | 1 | normal | +| Switch.cs:118:13:118:34 | case ...: | Switch.cs:118:18:118:18 | 2 | no-match | +| Switch.cs:118:13:118:34 | case ...: | Switch.cs:118:25:118:33 | ... == ... | false | +| Switch.cs:118:13:118:34 | case ...: | Switch.cs:118:36:118:44 | return ...; | return | | Switch.cs:118:18:118:18 | 2 | Switch.cs:118:18:118:18 | 2 | match | | Switch.cs:118:18:118:18 | 2 | Switch.cs:118:18:118:18 | 2 | no-match | | Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:25:118:25 | access to parameter s | normal | -| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:118:25:118:31 | ... == ... | false | -| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:118:25:118:31 | ... == ... | true | -| Switch.cs:118:28:118:31 | "fu" | Switch.cs:118:28:118:31 | "fu" | normal | -| Switch.cs:118:35:118:43 | return ...; | Switch.cs:118:35:118:43 | return ...; | return | -| Switch.cs:118:42:118:42 | 2 | Switch.cs:118:42:118:42 | 2 | normal | +| Switch.cs:118:25:118:33 | ... == ... | Switch.cs:118:25:118:33 | ... == ... | false | +| Switch.cs:118:25:118:33 | ... == ... | Switch.cs:118:25:118:33 | ... == ... | true | +| Switch.cs:118:30:118:33 | "fu" | Switch.cs:118:30:118:33 | "fu" | normal | +| Switch.cs:118:36:118:44 | return ...; | Switch.cs:118:36:118:44 | return ...; | return | +| Switch.cs:118:43:118:43 | 2 | Switch.cs:118:43:118:43 | 2 | normal | | Switch.cs:120:9:120:18 | return ...; | Switch.cs:120:9:120:18 | return ...; | return | | Switch.cs:120:16:120:17 | -... | Switch.cs:120:16:120:17 | -... | normal | | Switch.cs:120:17:120:17 | 1 | Switch.cs:120:17:120:17 | 1 | normal | @@ -2747,6 +2771,41 @@ | Switch.cs:150:18:150:18 | 2 | Switch.cs:150:18:150:18 | 2 | no-match | | Switch.cs:150:21:150:29 | return ...; | Switch.cs:150:21:150:29 | return ...; | return | | Switch.cs:150:28:150:28 | 2 | Switch.cs:150:28:150:28 | 2 | normal | +| Switch.cs:155:5:161:5 | {...} | Switch.cs:156:41:156:45 | false | throw(InvalidOperationException) [no-match] | +| Switch.cs:155:5:161:5 | {...} | Switch.cs:158:13:158:48 | call to method WriteLine | normal | +| Switch.cs:155:5:161:5 | {...} | Switch.cs:160:13:160:48 | call to method WriteLine | normal | +| Switch.cs:156:9:156:55 | ... ...; | Switch.cs:156:13:156:54 | String s = ... | normal | +| Switch.cs:156:9:156:55 | ... ...; | Switch.cs:156:41:156:45 | false | throw(InvalidOperationException) [no-match] | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:156:13:156:54 | String s = ... | normal | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:156:41:156:45 | false | throw(InvalidOperationException) [no-match] | +| Switch.cs:156:17:156:17 | access to parameter b | Switch.cs:156:17:156:17 | access to parameter b | normal | +| Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:156:36:156:38 | "a" | normal | +| Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:156:41:156:45 | false | throw(InvalidOperationException) [no-match] | +| Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:156:50:156:52 | "b" | normal | +| Switch.cs:156:28:156:31 | true | Switch.cs:156:28:156:31 | true | match | +| Switch.cs:156:28:156:31 | true | Switch.cs:156:28:156:31 | true | no-match | +| Switch.cs:156:28:156:38 | ... => ... | Switch.cs:156:28:156:31 | true | no-match | +| Switch.cs:156:28:156:38 | ... => ... | Switch.cs:156:36:156:38 | "a" | normal | +| Switch.cs:156:36:156:38 | "a" | Switch.cs:156:36:156:38 | "a" | normal | +| Switch.cs:156:41:156:45 | false | Switch.cs:156:41:156:45 | false | match | +| Switch.cs:156:41:156:45 | false | Switch.cs:156:41:156:45 | false | no-match | +| Switch.cs:156:41:156:52 | ... => ... | Switch.cs:156:41:156:45 | false | no-match | +| Switch.cs:156:41:156:52 | ... => ... | Switch.cs:156:50:156:52 | "b" | normal | +| Switch.cs:156:50:156:52 | "b" | Switch.cs:156:50:156:52 | "b" | normal | +| Switch.cs:157:9:160:49 | if (...) ... | Switch.cs:158:13:158:48 | call to method WriteLine | normal | +| Switch.cs:157:9:160:49 | if (...) ... | Switch.cs:160:13:160:48 | call to method WriteLine | normal | +| Switch.cs:157:13:157:13 | access to parameter b | Switch.cs:157:13:157:13 | access to parameter b | false | +| Switch.cs:157:13:157:13 | access to parameter b | Switch.cs:157:13:157:13 | access to parameter b | true | +| Switch.cs:158:13:158:48 | call to method WriteLine | Switch.cs:158:13:158:48 | call to method WriteLine | normal | +| Switch.cs:158:13:158:49 | ...; | Switch.cs:158:13:158:48 | call to method WriteLine | normal | +| Switch.cs:158:38:158:47 | $"..." | Switch.cs:158:38:158:47 | $"..." | normal | +| Switch.cs:158:40:158:43 | "a = " | Switch.cs:158:40:158:43 | "a = " | normal | +| Switch.cs:158:45:158:45 | access to local variable s | Switch.cs:158:45:158:45 | access to local variable s | normal | +| Switch.cs:160:13:160:48 | call to method WriteLine | Switch.cs:160:13:160:48 | call to method WriteLine | normal | +| Switch.cs:160:13:160:49 | ...; | Switch.cs:160:13:160:48 | call to method WriteLine | normal | +| Switch.cs:160:38:160:47 | $"..." | Switch.cs:160:38:160:47 | $"..." | normal | +| Switch.cs:160:40:160:43 | "b = " | Switch.cs:160:40:160:43 | "b = " | normal | +| Switch.cs:160:45:160:45 | access to local variable s | Switch.cs:160:45:160:45 | access to local variable s | normal | | TypeAccesses.cs:4:5:9:5 | {...} | TypeAccesses.cs:8:13:8:27 | Type t = ... | normal | | TypeAccesses.cs:5:9:5:26 | ... ...; | TypeAccesses.cs:5:13:5:25 | String s = ... | normal | | TypeAccesses.cs:5:13:5:25 | String s = ... | TypeAccesses.cs:5:13:5:25 | String s = ... | normal | diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 7feee30c18b..3a8d4b2646c 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -793,9 +793,9 @@ | Conditions.cs:79:17:79:25 | ... = ... | Conditions.cs:74:9:80:9 | foreach (... ... in ...) ... | semmle.label | successor | | Conditions.cs:79:17:79:26 | ...; | Conditions.cs:79:21:79:25 | false | semmle.label | successor | | Conditions.cs:79:21:79:25 | false | Conditions.cs:79:17:79:25 | ... = ... | semmle.label | successor | -| Conditions.cs:81:9:82:16 | if (...) ... | Conditions.cs:81:12:81:12 | access to local variable b | semmle.label | successor | -| Conditions.cs:81:12:81:12 | access to local variable b | Conditions.cs:82:13:82:16 | ...; | semmle.label | true | -| Conditions.cs:81:12:81:12 | access to local variable b | Conditions.cs:83:16:83:16 | access to local variable x | semmle.label | false | +| Conditions.cs:81:9:82:16 | if (...) ... | Conditions.cs:81:13:81:13 | access to local variable b | semmle.label | successor | +| Conditions.cs:81:13:81:13 | access to local variable b | Conditions.cs:82:13:82:16 | ...; | semmle.label | true | +| Conditions.cs:81:13:81:13 | access to local variable b | Conditions.cs:83:16:83:16 | access to local variable x | semmle.label | false | | Conditions.cs:82:13:82:13 | access to local variable x | Conditions.cs:82:13:82:15 | ...++ | semmle.label | successor | | Conditions.cs:82:13:82:15 | ...++ | Conditions.cs:83:16:83:16 | access to local variable x | semmle.label | successor | | Conditions.cs:82:13:82:16 | ...; | Conditions.cs:82:13:82:13 | access to local variable x | semmle.label | successor | @@ -883,16 +883,16 @@ | Conditions.cs:115:9:115:24 | ... ...; | Conditions.cs:115:20:115:23 | null | semmle.label | successor | | Conditions.cs:115:16:115:23 | String s = ... | Conditions.cs:116:9:123:9 | for (...;...;...) ... | semmle.label | successor | | Conditions.cs:115:20:115:23 | null | Conditions.cs:115:16:115:23 | String s = ... | semmle.label | successor | -| Conditions.cs:116:9:123:9 | for (...;...;...) ... | Conditions.cs:116:21:116:21 | 0 | semmle.label | successor | -| Conditions.cs:116:17:116:21 | Int32 i = ... | Conditions.cs:116:24:116:24 | access to local variable i | semmle.label | successor | -| Conditions.cs:116:21:116:21 | 0 | Conditions.cs:116:17:116:21 | Int32 i = ... | semmle.label | successor | -| Conditions.cs:116:24:116:24 | access to local variable i | Conditions.cs:116:28:116:31 | access to parameter args | semmle.label | successor | -| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:113:10:113:11 | exit M9 | semmle.label | false | -| Conditions.cs:116:24:116:38 | ... < ... | Conditions.cs:117:9:123:9 | {...} | semmle.label | true | -| Conditions.cs:116:28:116:31 | access to parameter args | Conditions.cs:116:28:116:38 | access to property Length | semmle.label | successor | -| Conditions.cs:116:28:116:38 | access to property Length | Conditions.cs:116:24:116:38 | ... < ... | semmle.label | successor | -| Conditions.cs:116:41:116:41 | access to local variable i | Conditions.cs:116:41:116:43 | ...++ | semmle.label | successor | -| Conditions.cs:116:41:116:43 | ...++ | Conditions.cs:116:24:116:24 | access to local variable i | semmle.label | successor | +| Conditions.cs:116:9:123:9 | for (...;...;...) ... | Conditions.cs:116:22:116:22 | 0 | semmle.label | successor | +| Conditions.cs:116:18:116:22 | Int32 i = ... | Conditions.cs:116:25:116:25 | access to local variable i | semmle.label | successor | +| Conditions.cs:116:22:116:22 | 0 | Conditions.cs:116:18:116:22 | Int32 i = ... | semmle.label | successor | +| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:116:29:116:32 | access to parameter args | semmle.label | successor | +| Conditions.cs:116:25:116:39 | ... < ... | Conditions.cs:113:10:113:11 | exit M9 | semmle.label | false | +| Conditions.cs:116:25:116:39 | ... < ... | Conditions.cs:117:9:123:9 | {...} | semmle.label | true | +| Conditions.cs:116:29:116:32 | access to parameter args | Conditions.cs:116:29:116:39 | access to property Length | semmle.label | successor | +| Conditions.cs:116:29:116:39 | access to property Length | Conditions.cs:116:25:116:39 | ... < ... | semmle.label | successor | +| Conditions.cs:116:42:116:42 | access to local variable i | Conditions.cs:116:42:116:44 | ...++ | semmle.label | successor | +| Conditions.cs:116:42:116:44 | ...++ | Conditions.cs:116:25:116:25 | access to local variable i | semmle.label | successor | | Conditions.cs:117:9:123:9 | {...} | Conditions.cs:118:13:118:44 | ... ...; | semmle.label | successor | | Conditions.cs:118:13:118:44 | ... ...; | Conditions.cs:118:24:118:24 | access to local variable i | semmle.label | successor | | Conditions.cs:118:17:118:43 | Boolean last = ... | Conditions.cs:119:13:120:23 | if (...) ... | semmle.label | successor | @@ -911,9 +911,9 @@ | Conditions.cs:120:21:120:22 | [last (line 118): false] "" | Conditions.cs:120:17:120:22 | [last (line 118): false] ... = ... | semmle.label | successor | | Conditions.cs:121:13:122:25 | [last (line 118): false] if (...) ... | Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | semmle.label | successor | | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | Conditions.cs:121:17:121:20 | [last (line 118): true] access to local variable last | semmle.label | successor | -| Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | Conditions.cs:116:41:116:41 | access to local variable i | semmle.label | false | +| Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | Conditions.cs:116:42:116:42 | access to local variable i | semmle.label | false | | Conditions.cs:121:17:121:20 | [last (line 118): true] access to local variable last | Conditions.cs:122:17:122:25 | ...; | semmle.label | true | -| Conditions.cs:122:17:122:24 | ... = ... | Conditions.cs:116:41:116:41 | access to local variable i | semmle.label | successor | +| Conditions.cs:122:17:122:24 | ... = ... | Conditions.cs:116:42:116:42 | access to local variable i | semmle.label | successor | | Conditions.cs:122:17:122:25 | ...; | Conditions.cs:122:21:122:24 | null | semmle.label | successor | | Conditions.cs:122:21:122:24 | null | Conditions.cs:122:17:122:24 | ... = ... | semmle.label | successor | | Conditions.cs:129:10:129:12 | enter M10 | Conditions.cs:130:5:141:5 | {...} | semmle.label | successor | @@ -958,6 +958,30 @@ | Conditions.cs:137:21:137:26 | [Field1 (line 129): true, Field2 (line 129): true] this access | Conditions.cs:137:21:137:26 | [Field1 (line 129): true, Field2 (line 129): true] access to field Field1 | semmle.label | successor | | Conditions.cs:137:21:137:37 | [Field1 (line 129): true, Field2 (line 129): true] call to method ToString | Conditions.cs:131:16:131:19 | [Field1 (line 129): true, Field2 (line 129): true] true | semmle.label | successor | | Conditions.cs:137:21:137:38 | [Field1 (line 129): true, Field2 (line 129): true] ...; | Conditions.cs:137:21:137:26 | [Field1 (line 129): true, Field2 (line 129): true] this access | semmle.label | successor | +| Conditions.cs:143:10:143:12 | enter M11 | Conditions.cs:144:5:150:5 | {...} | semmle.label | successor | +| Conditions.cs:144:5:150:5 | {...} | Conditions.cs:145:9:145:30 | ... ...; | semmle.label | successor | +| Conditions.cs:145:9:145:30 | ... ...; | Conditions.cs:145:17:145:29 | ... ? ... : ... | semmle.label | successor | +| Conditions.cs:145:13:145:29 | [b (line 143): false] String s = ... | Conditions.cs:146:9:149:49 | [b (line 143): false] if (...) ... | semmle.label | successor | +| Conditions.cs:145:13:145:29 | [b (line 143): true] String s = ... | Conditions.cs:146:9:149:49 | [b (line 143): true] if (...) ... | semmle.label | successor | +| Conditions.cs:145:17:145:17 | access to parameter b | Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | semmle.label | true | +| Conditions.cs:145:17:145:17 | access to parameter b | Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | semmle.label | false | +| Conditions.cs:145:17:145:29 | ... ? ... : ... | Conditions.cs:145:17:145:17 | access to parameter b | semmle.label | successor | +| Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | Conditions.cs:145:13:145:29 | [b (line 143): true] String s = ... | semmle.label | successor | +| Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | Conditions.cs:145:13:145:29 | [b (line 143): false] String s = ... | semmle.label | successor | +| Conditions.cs:146:9:149:49 | [b (line 143): false] if (...) ... | Conditions.cs:146:13:146:13 | [b (line 143): false] access to parameter b | semmle.label | successor | +| Conditions.cs:146:9:149:49 | [b (line 143): true] if (...) ... | Conditions.cs:146:13:146:13 | [b (line 143): true] access to parameter b | semmle.label | successor | +| Conditions.cs:146:13:146:13 | [b (line 143): false] access to parameter b | Conditions.cs:149:13:149:49 | ...; | semmle.label | false | +| Conditions.cs:146:13:146:13 | [b (line 143): true] access to parameter b | Conditions.cs:147:13:147:49 | ...; | semmle.label | true | +| Conditions.cs:147:13:147:48 | call to method WriteLine | Conditions.cs:143:10:143:12 | exit M11 | semmle.label | successor | +| Conditions.cs:147:13:147:49 | ...; | Conditions.cs:147:40:147:43 | "a = " | semmle.label | successor | +| Conditions.cs:147:38:147:47 | $"..." | Conditions.cs:147:13:147:48 | call to method WriteLine | semmle.label | successor | +| Conditions.cs:147:40:147:43 | "a = " | Conditions.cs:147:45:147:45 | access to local variable s | semmle.label | successor | +| Conditions.cs:147:45:147:45 | access to local variable s | Conditions.cs:147:38:147:47 | $"..." | semmle.label | successor | +| Conditions.cs:149:13:149:48 | call to method WriteLine | Conditions.cs:143:10:143:12 | exit M11 | semmle.label | successor | +| Conditions.cs:149:13:149:49 | ...; | Conditions.cs:149:40:149:43 | "b = " | semmle.label | successor | +| Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:149:13:149:48 | call to method WriteLine | semmle.label | successor | +| Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:149:45:149:45 | access to local variable s | semmle.label | successor | +| Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:149:38:149:47 | $"..." | semmle.label | successor | | ExitMethods.cs:7:10:7:11 | enter M1 | ExitMethods.cs:8:5:11:5 | {...} | semmle.label | successor | | ExitMethods.cs:8:5:11:5 | {...} | ExitMethods.cs:9:9:9:25 | ...; | semmle.label | successor | | ExitMethods.cs:9:9:9:24 | call to method ErrorMaybe | ExitMethods.cs:10:9:10:15 | return ...; | semmle.label | successor | @@ -2722,10 +2746,10 @@ | Switch.cs:27:18:27:25 | Double d | Switch.cs:27:32:27:38 | call to method Throw | semmle.label | match | | Switch.cs:27:18:27:25 | Double d | Switch.cs:30:13:30:20 | default: | semmle.label | no-match | | Switch.cs:27:32:27:38 | call to method Throw | Switch.cs:10:10:10:11 | exit M2 | semmle.label | exception(Exception) | -| Switch.cs:28:17:28:21 | Label: | Switch.cs:29:17:29:23 | return ...; | semmle.label | successor | +| Switch.cs:28:13:28:17 | Label: | Switch.cs:29:17:29:23 | return ...; | semmle.label | successor | | Switch.cs:29:17:29:23 | return ...; | Switch.cs:10:10:10:11 | exit M2 | semmle.label | return | | Switch.cs:30:13:30:20 | default: | Switch.cs:31:17:31:27 | goto ...; | semmle.label | successor | -| Switch.cs:31:17:31:27 | goto ...; | Switch.cs:28:17:28:21 | Label: | semmle.label | goto(Label) | +| Switch.cs:31:17:31:27 | goto ...; | Switch.cs:28:13:28:17 | Label: | semmle.label | goto(Label) | | Switch.cs:35:10:35:11 | enter M3 | Switch.cs:36:5:42:5 | {...} | semmle.label | successor | | Switch.cs:36:5:42:5 | {...} | Switch.cs:37:9:41:9 | switch (...) {...} | semmle.label | successor | | Switch.cs:37:9:41:9 | switch (...) {...} | Switch.cs:37:17:37:23 | call to method Throw | semmle.label | successor | @@ -2750,73 +2774,73 @@ | Switch.cs:56:5:64:5 | {...} | Switch.cs:57:9:63:9 | switch (...) {...} | semmle.label | successor | | Switch.cs:57:9:63:9 | switch (...) {...} | Switch.cs:57:17:57:17 | 1 | semmle.label | successor | | Switch.cs:57:17:57:17 | 1 | Switch.cs:57:21:57:21 | 2 | semmle.label | successor | -| Switch.cs:57:17:57:21 | ... + ... | Switch.cs:59:13:59:20 | case ...: | semmle.label | successor | +| Switch.cs:57:17:57:21 | ... + ... | Switch.cs:59:13:59:19 | case ...: | semmle.label | successor | | Switch.cs:57:21:57:21 | 2 | Switch.cs:57:17:57:21 | ... + ... | semmle.label | successor | -| Switch.cs:59:13:59:20 | case ...: | Switch.cs:59:18:59:18 | 2 | semmle.label | successor | -| Switch.cs:59:18:59:18 | 2 | Switch.cs:61:13:61:20 | case ...: | semmle.label | no-match | -| Switch.cs:61:13:61:20 | case ...: | Switch.cs:61:18:61:18 | 3 | semmle.label | successor | -| Switch.cs:61:18:61:18 | 3 | Switch.cs:62:15:62:20 | break; | semmle.label | match | -| Switch.cs:62:15:62:20 | break; | Switch.cs:55:10:55:11 | exit M5 | semmle.label | break | +| Switch.cs:59:13:59:19 | case ...: | Switch.cs:59:18:59:18 | 2 | semmle.label | successor | +| Switch.cs:59:18:59:18 | 2 | Switch.cs:61:13:61:19 | case ...: | semmle.label | no-match | +| Switch.cs:61:13:61:19 | case ...: | Switch.cs:61:18:61:18 | 3 | semmle.label | successor | +| Switch.cs:61:18:61:18 | 3 | Switch.cs:62:17:62:22 | break; | semmle.label | match | +| Switch.cs:62:17:62:22 | break; | Switch.cs:55:10:55:11 | exit M5 | semmle.label | break | | Switch.cs:66:10:66:11 | enter M6 | Switch.cs:67:5:75:5 | {...} | semmle.label | successor | | Switch.cs:67:5:75:5 | {...} | Switch.cs:68:9:74:9 | switch (...) {...} | semmle.label | successor | | Switch.cs:68:9:74:9 | switch (...) {...} | Switch.cs:68:25:68:25 | access to parameter s | semmle.label | successor | -| Switch.cs:68:17:68:25 | (...) ... | Switch.cs:70:13:70:24 | case ...: | semmle.label | successor | +| Switch.cs:68:17:68:25 | (...) ... | Switch.cs:70:13:70:23 | case ...: | semmle.label | successor | | Switch.cs:68:25:68:25 | access to parameter s | Switch.cs:68:17:68:25 | (...) ... | semmle.label | successor | -| Switch.cs:70:13:70:24 | case ...: | Switch.cs:70:18:70:20 | access to type Int32 | semmle.label | successor | -| Switch.cs:70:18:70:20 | access to type Int32 | Switch.cs:72:13:72:21 | case ...: | semmle.label | no-match | -| Switch.cs:72:13:72:21 | case ...: | Switch.cs:72:18:72:19 | "" | semmle.label | successor | +| Switch.cs:70:13:70:23 | case ...: | Switch.cs:70:18:70:20 | access to type Int32 | semmle.label | successor | +| Switch.cs:70:18:70:20 | access to type Int32 | Switch.cs:72:13:72:20 | case ...: | semmle.label | no-match | +| Switch.cs:72:13:72:20 | case ...: | Switch.cs:72:18:72:19 | "" | semmle.label | successor | | Switch.cs:72:18:72:19 | "" | Switch.cs:66:10:66:11 | exit M6 | semmle.label | no-match | -| Switch.cs:72:18:72:19 | "" | Switch.cs:73:15:73:20 | break; | semmle.label | match | -| Switch.cs:73:15:73:20 | break; | Switch.cs:66:10:66:11 | exit M6 | semmle.label | break | +| Switch.cs:72:18:72:19 | "" | Switch.cs:73:17:73:22 | break; | semmle.label | match | +| Switch.cs:73:17:73:22 | break; | Switch.cs:66:10:66:11 | exit M6 | semmle.label | break | | Switch.cs:77:10:77:11 | enter M7 | Switch.cs:78:5:89:5 | {...} | semmle.label | successor | | Switch.cs:78:5:89:5 | {...} | Switch.cs:79:9:87:9 | switch (...) {...} | semmle.label | successor | | Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:79:17:79:17 | access to parameter i | semmle.label | successor | -| Switch.cs:79:17:79:17 | access to parameter i | Switch.cs:81:13:81:20 | case ...: | semmle.label | successor | -| Switch.cs:81:13:81:20 | case ...: | Switch.cs:81:18:81:18 | 1 | semmle.label | successor | -| Switch.cs:81:18:81:18 | 1 | Switch.cs:82:22:82:25 | true | semmle.label | match | -| Switch.cs:81:18:81:18 | 1 | Switch.cs:83:13:83:20 | case ...: | semmle.label | no-match | -| Switch.cs:82:15:82:26 | return ...; | Switch.cs:77:10:77:11 | exit M7 | semmle.label | return | -| Switch.cs:82:22:82:25 | true | Switch.cs:82:15:82:26 | return ...; | semmle.label | successor | -| Switch.cs:83:13:83:20 | case ...: | Switch.cs:83:18:83:18 | 2 | semmle.label | successor | -| Switch.cs:83:18:83:18 | 2 | Switch.cs:84:15:85:22 | if (...) ... | semmle.label | match | +| Switch.cs:79:17:79:17 | access to parameter i | Switch.cs:81:13:81:19 | case ...: | semmle.label | successor | +| Switch.cs:81:13:81:19 | case ...: | Switch.cs:81:18:81:18 | 1 | semmle.label | successor | +| Switch.cs:81:18:81:18 | 1 | Switch.cs:82:24:82:27 | true | semmle.label | match | +| Switch.cs:81:18:81:18 | 1 | Switch.cs:83:13:83:19 | case ...: | semmle.label | no-match | +| Switch.cs:82:17:82:28 | return ...; | Switch.cs:77:10:77:11 | exit M7 | semmle.label | return | +| Switch.cs:82:24:82:27 | true | Switch.cs:82:17:82:28 | return ...; | semmle.label | successor | +| Switch.cs:83:13:83:19 | case ...: | Switch.cs:83:18:83:18 | 2 | semmle.label | successor | +| Switch.cs:83:18:83:18 | 2 | Switch.cs:84:17:85:26 | if (...) ... | semmle.label | match | | Switch.cs:83:18:83:18 | 2 | Switch.cs:88:16:88:20 | false | semmle.label | no-match | -| Switch.cs:84:15:85:22 | if (...) ... | Switch.cs:84:19:84:19 | access to parameter j | semmle.label | successor | -| Switch.cs:84:19:84:19 | access to parameter j | Switch.cs:84:23:84:23 | 2 | semmle.label | successor | -| Switch.cs:84:19:84:23 | ... > ... | Switch.cs:85:17:85:22 | break; | semmle.label | true | -| Switch.cs:84:19:84:23 | ... > ... | Switch.cs:86:22:86:25 | true | semmle.label | false | -| Switch.cs:84:23:84:23 | 2 | Switch.cs:84:19:84:23 | ... > ... | semmle.label | successor | -| Switch.cs:85:17:85:22 | break; | Switch.cs:88:16:88:20 | false | semmle.label | break | -| Switch.cs:86:15:86:26 | return ...; | Switch.cs:77:10:77:11 | exit M7 | semmle.label | return | -| Switch.cs:86:22:86:25 | true | Switch.cs:86:15:86:26 | return ...; | semmle.label | successor | +| Switch.cs:84:17:85:26 | if (...) ... | Switch.cs:84:21:84:21 | access to parameter j | semmle.label | successor | +| Switch.cs:84:21:84:21 | access to parameter j | Switch.cs:84:25:84:25 | 2 | semmle.label | successor | +| Switch.cs:84:21:84:25 | ... > ... | Switch.cs:85:21:85:26 | break; | semmle.label | true | +| Switch.cs:84:21:84:25 | ... > ... | Switch.cs:86:24:86:27 | true | semmle.label | false | +| Switch.cs:84:25:84:25 | 2 | Switch.cs:84:21:84:25 | ... > ... | semmle.label | successor | +| Switch.cs:85:21:85:26 | break; | Switch.cs:88:16:88:20 | false | semmle.label | break | +| Switch.cs:86:17:86:28 | return ...; | Switch.cs:77:10:77:11 | exit M7 | semmle.label | return | +| Switch.cs:86:24:86:27 | true | Switch.cs:86:17:86:28 | return ...; | semmle.label | successor | | Switch.cs:88:9:88:21 | return ...; | Switch.cs:77:10:77:11 | exit M7 | semmle.label | return | | Switch.cs:88:16:88:20 | false | Switch.cs:88:9:88:21 | return ...; | semmle.label | successor | | Switch.cs:91:10:91:11 | enter M8 | Switch.cs:92:5:99:5 | {...} | semmle.label | successor | | Switch.cs:92:5:99:5 | {...} | Switch.cs:93:9:97:9 | switch (...) {...} | semmle.label | successor | | Switch.cs:93:9:97:9 | switch (...) {...} | Switch.cs:93:17:93:17 | access to parameter o | semmle.label | successor | -| Switch.cs:93:17:93:17 | access to parameter o | Switch.cs:95:13:95:24 | case ...: | semmle.label | successor | -| Switch.cs:95:13:95:24 | case ...: | Switch.cs:95:18:95:20 | access to type Int32 | semmle.label | successor | -| Switch.cs:95:18:95:20 | access to type Int32 | Switch.cs:96:22:96:25 | true | semmle.label | match | +| Switch.cs:93:17:93:17 | access to parameter o | Switch.cs:95:13:95:23 | case ...: | semmle.label | successor | +| Switch.cs:95:13:95:23 | case ...: | Switch.cs:95:18:95:20 | access to type Int32 | semmle.label | successor | +| Switch.cs:95:18:95:20 | access to type Int32 | Switch.cs:96:24:96:27 | true | semmle.label | match | | Switch.cs:95:18:95:20 | access to type Int32 | Switch.cs:98:16:98:20 | false | semmle.label | no-match | -| Switch.cs:96:15:96:26 | return ...; | Switch.cs:91:10:91:11 | exit M8 | semmle.label | return | -| Switch.cs:96:22:96:25 | true | Switch.cs:96:15:96:26 | return ...; | semmle.label | successor | +| Switch.cs:96:17:96:28 | return ...; | Switch.cs:91:10:91:11 | exit M8 | semmle.label | return | +| Switch.cs:96:24:96:27 | true | Switch.cs:96:17:96:28 | return ...; | semmle.label | successor | | Switch.cs:98:9:98:21 | return ...; | Switch.cs:91:10:91:11 | exit M8 | semmle.label | return | | Switch.cs:98:16:98:20 | false | Switch.cs:98:9:98:21 | return ...; | semmle.label | successor | | Switch.cs:101:9:101:10 | enter M9 | Switch.cs:102:5:109:5 | {...} | semmle.label | successor | | Switch.cs:102:5:109:5 | {...} | Switch.cs:103:9:107:9 | switch (...) {...} | semmle.label | successor | | Switch.cs:103:9:107:9 | switch (...) {...} | Switch.cs:103:17:103:17 | access to parameter s | semmle.label | successor | | Switch.cs:103:17:103:17 | access to parameter s | Switch.cs:103:19:103:25 | access to property Length | semmle.label | non-null | -| Switch.cs:103:17:103:17 | access to parameter s | Switch.cs:105:13:105:20 | case ...: | semmle.label | null | -| Switch.cs:103:19:103:25 | access to property Length | Switch.cs:105:13:105:20 | case ...: | semmle.label | successor | -| Switch.cs:105:13:105:20 | case ...: | Switch.cs:105:18:105:18 | 0 | semmle.label | successor | -| Switch.cs:105:18:105:18 | 0 | Switch.cs:105:29:105:29 | 0 | semmle.label | match | -| Switch.cs:105:18:105:18 | 0 | Switch.cs:106:13:106:20 | case ...: | semmle.label | no-match | -| Switch.cs:105:22:105:30 | return ...; | Switch.cs:101:9:101:10 | exit M9 | semmle.label | return | -| Switch.cs:105:29:105:29 | 0 | Switch.cs:105:22:105:30 | return ...; | semmle.label | successor | -| Switch.cs:106:13:106:20 | case ...: | Switch.cs:106:18:106:18 | 1 | semmle.label | successor | -| Switch.cs:106:18:106:18 | 1 | Switch.cs:106:29:106:29 | 1 | semmle.label | match | +| Switch.cs:103:17:103:17 | access to parameter s | Switch.cs:105:13:105:19 | case ...: | semmle.label | null | +| Switch.cs:103:19:103:25 | access to property Length | Switch.cs:105:13:105:19 | case ...: | semmle.label | successor | +| Switch.cs:105:13:105:19 | case ...: | Switch.cs:105:18:105:18 | 0 | semmle.label | successor | +| Switch.cs:105:18:105:18 | 0 | Switch.cs:105:28:105:28 | 0 | semmle.label | match | +| Switch.cs:105:18:105:18 | 0 | Switch.cs:106:13:106:19 | case ...: | semmle.label | no-match | +| Switch.cs:105:21:105:29 | return ...; | Switch.cs:101:9:101:10 | exit M9 | semmle.label | return | +| Switch.cs:105:28:105:28 | 0 | Switch.cs:105:21:105:29 | return ...; | semmle.label | successor | +| Switch.cs:106:13:106:19 | case ...: | Switch.cs:106:18:106:18 | 1 | semmle.label | successor | +| Switch.cs:106:18:106:18 | 1 | Switch.cs:106:28:106:28 | 1 | semmle.label | match | | Switch.cs:106:18:106:18 | 1 | Switch.cs:108:17:108:17 | 1 | semmle.label | no-match | -| Switch.cs:106:22:106:30 | return ...; | Switch.cs:101:9:101:10 | exit M9 | semmle.label | return | -| Switch.cs:106:29:106:29 | 1 | Switch.cs:106:22:106:30 | return ...; | semmle.label | successor | +| Switch.cs:106:21:106:29 | return ...; | Switch.cs:101:9:101:10 | exit M9 | semmle.label | return | +| Switch.cs:106:28:106:28 | 1 | Switch.cs:106:21:106:29 | return ...; | semmle.label | successor | | Switch.cs:108:9:108:18 | return ...; | Switch.cs:101:9:101:10 | exit M9 | semmle.label | return | | Switch.cs:108:16:108:17 | -... | Switch.cs:108:9:108:18 | return ...; | semmle.label | successor | | Switch.cs:108:17:108:17 | 1 | Switch.cs:108:16:108:17 | -... | semmle.label | successor | @@ -2827,25 +2851,25 @@ | Switch.cs:114:5:121:5 | {...} | Switch.cs:115:9:119:9 | switch (...) {...} | semmle.label | successor | | Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:115:17:115:17 | access to parameter s | semmle.label | successor | | Switch.cs:115:17:115:17 | access to parameter s | Switch.cs:115:17:115:24 | access to property Length | semmle.label | successor | -| Switch.cs:115:17:115:24 | access to property Length | Switch.cs:117:13:117:34 | case ...: | semmle.label | successor | -| Switch.cs:117:13:117:34 | case ...: | Switch.cs:117:18:117:18 | 3 | semmle.label | successor | +| Switch.cs:115:17:115:24 | access to property Length | Switch.cs:117:13:117:35 | case ...: | semmle.label | successor | +| Switch.cs:117:13:117:35 | case ...: | Switch.cs:117:18:117:18 | 3 | semmle.label | successor | | Switch.cs:117:18:117:18 | 3 | Switch.cs:117:25:117:25 | access to parameter s | semmle.label | match | -| Switch.cs:117:18:117:18 | 3 | Switch.cs:118:13:118:33 | case ...: | semmle.label | no-match | -| Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:28:117:32 | "foo" | semmle.label | successor | -| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:117:43:117:43 | 1 | semmle.label | true | -| Switch.cs:117:25:117:32 | ... == ... | Switch.cs:118:13:118:33 | case ...: | semmle.label | false | -| Switch.cs:117:28:117:32 | "foo" | Switch.cs:117:25:117:32 | ... == ... | semmle.label | successor | -| Switch.cs:117:36:117:44 | return ...; | Switch.cs:113:9:113:11 | exit M10 | semmle.label | return | -| Switch.cs:117:43:117:43 | 1 | Switch.cs:117:36:117:44 | return ...; | semmle.label | successor | -| Switch.cs:118:13:118:33 | case ...: | Switch.cs:118:18:118:18 | 2 | semmle.label | successor | +| Switch.cs:117:18:117:18 | 3 | Switch.cs:118:13:118:34 | case ...: | semmle.label | no-match | +| Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:30:117:34 | "foo" | semmle.label | successor | +| Switch.cs:117:25:117:34 | ... == ... | Switch.cs:117:44:117:44 | 1 | semmle.label | true | +| Switch.cs:117:25:117:34 | ... == ... | Switch.cs:118:13:118:34 | case ...: | semmle.label | false | +| Switch.cs:117:30:117:34 | "foo" | Switch.cs:117:25:117:34 | ... == ... | semmle.label | successor | +| Switch.cs:117:37:117:45 | return ...; | Switch.cs:113:9:113:11 | exit M10 | semmle.label | return | +| Switch.cs:117:44:117:44 | 1 | Switch.cs:117:37:117:45 | return ...; | semmle.label | successor | +| Switch.cs:118:13:118:34 | case ...: | Switch.cs:118:18:118:18 | 2 | semmle.label | successor | | Switch.cs:118:18:118:18 | 2 | Switch.cs:118:25:118:25 | access to parameter s | semmle.label | match | | Switch.cs:118:18:118:18 | 2 | Switch.cs:120:17:120:17 | 1 | semmle.label | no-match | -| Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:28:118:31 | "fu" | semmle.label | successor | -| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:118:42:118:42 | 2 | semmle.label | true | -| Switch.cs:118:25:118:31 | ... == ... | Switch.cs:120:17:120:17 | 1 | semmle.label | false | -| Switch.cs:118:28:118:31 | "fu" | Switch.cs:118:25:118:31 | ... == ... | semmle.label | successor | -| Switch.cs:118:35:118:43 | return ...; | Switch.cs:113:9:113:11 | exit M10 | semmle.label | return | -| Switch.cs:118:42:118:42 | 2 | Switch.cs:118:35:118:43 | return ...; | semmle.label | successor | +| Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:30:118:33 | "fu" | semmle.label | successor | +| Switch.cs:118:25:118:33 | ... == ... | Switch.cs:118:43:118:43 | 2 | semmle.label | true | +| Switch.cs:118:25:118:33 | ... == ... | Switch.cs:120:17:120:17 | 1 | semmle.label | false | +| Switch.cs:118:30:118:33 | "fu" | Switch.cs:118:25:118:33 | ... == ... | semmle.label | successor | +| Switch.cs:118:36:118:44 | return ...; | Switch.cs:113:9:113:11 | exit M10 | semmle.label | return | +| Switch.cs:118:43:118:43 | 2 | Switch.cs:118:36:118:44 | return ...; | semmle.label | successor | | Switch.cs:120:9:120:18 | return ...; | Switch.cs:113:9:113:11 | exit M10 | semmle.label | return | | Switch.cs:120:16:120:17 | -... | Switch.cs:120:9:120:18 | return ...; | semmle.label | successor | | Switch.cs:120:17:120:17 | 1 | Switch.cs:120:16:120:17 | -... | semmle.label | successor | @@ -2913,6 +2937,33 @@ | Switch.cs:150:18:150:18 | 2 | Switch.cs:150:28:150:28 | 2 | semmle.label | match | | Switch.cs:150:21:150:29 | return ...; | Switch.cs:144:9:144:11 | exit M14 | semmle.label | return | | Switch.cs:150:28:150:28 | 2 | Switch.cs:150:21:150:29 | return ...; | semmle.label | successor | +| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:155:5:161:5 | {...} | semmle.label | successor | +| Switch.cs:155:5:161:5 | {...} | Switch.cs:156:9:156:55 | ... ...; | semmle.label | successor | +| Switch.cs:156:9:156:55 | ... ...; | Switch.cs:156:17:156:54 | ... switch { ... } | semmle.label | successor | +| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:157:9:160:49 | if (...) ... | semmle.label | successor | +| Switch.cs:156:17:156:17 | access to parameter b | Switch.cs:156:28:156:38 | ... => ... | semmle.label | successor | +| Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:156:17:156:17 | access to parameter b | semmle.label | successor | +| Switch.cs:156:28:156:31 | true | Switch.cs:156:36:156:38 | "a" | semmle.label | match | +| Switch.cs:156:28:156:31 | true | Switch.cs:156:41:156:52 | ... => ... | semmle.label | no-match | +| Switch.cs:156:28:156:38 | ... => ... | Switch.cs:156:28:156:31 | true | semmle.label | successor | +| Switch.cs:156:36:156:38 | "a" | Switch.cs:156:13:156:54 | String s = ... | semmle.label | successor | +| Switch.cs:156:41:156:45 | false | Switch.cs:154:10:154:12 | exit M15 | semmle.label | exception(InvalidOperationException) | +| Switch.cs:156:41:156:45 | false | Switch.cs:156:50:156:52 | "b" | semmle.label | match | +| Switch.cs:156:41:156:52 | ... => ... | Switch.cs:156:41:156:45 | false | semmle.label | successor | +| Switch.cs:156:50:156:52 | "b" | Switch.cs:156:13:156:54 | String s = ... | semmle.label | successor | +| Switch.cs:157:9:160:49 | if (...) ... | Switch.cs:157:13:157:13 | access to parameter b | semmle.label | successor | +| Switch.cs:157:13:157:13 | access to parameter b | Switch.cs:158:13:158:49 | ...; | semmle.label | true | +| Switch.cs:157:13:157:13 | access to parameter b | Switch.cs:160:13:160:49 | ...; | semmle.label | false | +| Switch.cs:158:13:158:48 | call to method WriteLine | Switch.cs:154:10:154:12 | exit M15 | semmle.label | successor | +| Switch.cs:158:13:158:49 | ...; | Switch.cs:158:40:158:43 | "a = " | semmle.label | successor | +| Switch.cs:158:38:158:47 | $"..." | Switch.cs:158:13:158:48 | call to method WriteLine | semmle.label | successor | +| Switch.cs:158:40:158:43 | "a = " | Switch.cs:158:45:158:45 | access to local variable s | semmle.label | successor | +| Switch.cs:158:45:158:45 | access to local variable s | Switch.cs:158:38:158:47 | $"..." | semmle.label | successor | +| Switch.cs:160:13:160:48 | call to method WriteLine | Switch.cs:154:10:154:12 | exit M15 | semmle.label | successor | +| Switch.cs:160:13:160:49 | ...; | Switch.cs:160:40:160:43 | "b = " | semmle.label | successor | +| Switch.cs:160:38:160:47 | $"..." | Switch.cs:160:13:160:48 | call to method WriteLine | semmle.label | successor | +| Switch.cs:160:40:160:43 | "b = " | Switch.cs:160:45:160:45 | access to local variable s | semmle.label | successor | +| Switch.cs:160:45:160:45 | access to local variable s | Switch.cs:160:38:160:47 | $"..." | semmle.label | successor | | TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:4:5:9:5 | {...} | semmle.label | successor | | TypeAccesses.cs:4:5:9:5 | {...} | TypeAccesses.cs:5:9:5:26 | ... ...; | semmle.label | successor | | TypeAccesses.cs:5:9:5:26 | ... ...; | TypeAccesses.cs:5:25:5:25 | access to parameter o | semmle.label | successor | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected index 90685fc60a2..69d6f6f8701 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Nodes.expected @@ -160,6 +160,14 @@ booleanNode | Conditions.cs:137:21:137:37 | [Field1 (line 129): true, Field2 (line 129): true] call to method ToString | Field2 (line 129): true | | Conditions.cs:137:21:137:38 | [Field1 (line 129): true, Field2 (line 129): true] ...; | Field1 (line 129): true | | Conditions.cs:137:21:137:38 | [Field1 (line 129): true, Field2 (line 129): true] ...; | Field2 (line 129): true | +| Conditions.cs:145:13:145:29 | [b (line 143): false] String s = ... | b (line 143): false | +| Conditions.cs:145:13:145:29 | [b (line 143): true] String s = ... | b (line 143): true | +| Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | b (line 143): true | +| Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | b (line 143): false | +| Conditions.cs:146:9:149:49 | [b (line 143): false] if (...) ... | b (line 143): false | +| Conditions.cs:146:9:149:49 | [b (line 143): true] if (...) ... | b (line 143): true | +| Conditions.cs:146:13:146:13 | [b (line 143): false] access to parameter b | b (line 143): false | +| Conditions.cs:146:13:146:13 | [b (line 143): true] access to parameter b | b (line 143): true | | Finally.cs:180:21:180:43 | [b1 (line 176): true] throw ...; | b1 (line 176): true | | Finally.cs:180:27:180:42 | [b1 (line 176): true] object creation of type ExceptionA | b1 (line 176): true | | Finally.cs:183:9:192:9 | [b1 (line 176): false] {...} | b1 (line 176): false | @@ -678,6 +686,7 @@ entryPoint | Conditions.cs:102:12:102:13 | M8 | Conditions.cs:103:5:111:5 | {...} | | Conditions.cs:113:10:113:11 | M9 | Conditions.cs:114:5:124:5 | {...} | | Conditions.cs:129:10:129:12 | M10 | Conditions.cs:130:5:141:5 | {...} | +| Conditions.cs:143:10:143:12 | M11 | Conditions.cs:144:5:150:5 | {...} | | ExitMethods.cs:7:10:7:11 | M1 | ExitMethods.cs:8:5:11:5 | {...} | | ExitMethods.cs:13:10:13:11 | M2 | ExitMethods.cs:14:5:17:5 | {...} | | ExitMethods.cs:19:10:19:11 | M3 | ExitMethods.cs:20:5:23:5 | {...} | @@ -821,6 +830,7 @@ entryPoint | Switch.cs:129:12:129:14 | M12 | Switch.cs:130:5:132:5 | {...} | | Switch.cs:134:9:134:11 | M13 | Switch.cs:135:5:142:5 | {...} | | Switch.cs:144:9:144:11 | M14 | Switch.cs:145:5:152:5 | {...} | +| Switch.cs:154:10:154:12 | M15 | Switch.cs:155:5:161:5 | {...} | | TypeAccesses.cs:3:10:3:10 | M | TypeAccesses.cs:4:5:9:5 | {...} | | VarDecls.cs:5:18:5:19 | M1 | VarDecls.cs:6:5:11:5 | {...} | | VarDecls.cs:13:12:13:13 | M2 | VarDecls.cs:14:5:17:5 | {...} | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Switch.cs b/csharp/ql/test/library-tests/controlflow/graph/Switch.cs index 6b670908224..45912ead10e 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Switch.cs +++ b/csharp/ql/test/library-tests/controlflow/graph/Switch.cs @@ -25,7 +25,7 @@ class Switch Console.WriteLine(s); return; case double d when Throw(): - Label: + Label: return; default: goto Label; @@ -56,10 +56,10 @@ class Switch { switch (1 + 2) { - case 2 : - break; - case 3 : - break; + case 2: + break; + case 3: + break; } } @@ -67,10 +67,10 @@ class Switch { switch ((object)s) { - case int _ : - break; - case "" : - break; + case int _: + break; + case "": + break; } } @@ -78,12 +78,12 @@ class Switch { switch (i) { - case 1 : - return true; - case 2 : - if (j > 2) - break; - return true; + case 1: + return true; + case 2: + if (j > 2) + break; + return true; } return false; } @@ -92,8 +92,8 @@ class Switch { switch (o) { - case int _ : - return true; + case int _: + return true; } return false; } @@ -102,8 +102,8 @@ class Switch { switch (s?.Length) { - case 0 : return 0; - case 1 : return 1; + case 0: return 0; + case 1: return 1; } return -1; } @@ -114,8 +114,8 @@ class Switch { switch (s.Length) { - case 3 when s=="foo" : return 1; - case 2 when s=="fu" : return 2; + case 3 when s == "foo": return 1; + case 2 when s == "fu": return 2; } return -1; } @@ -150,4 +150,13 @@ class Switch case 2: return 2; } } + + void M15(bool b) + { + var s = b switch { true => "a", false => "b" }; + if (b) + System.Console.WriteLine($"a = {s}"); + else + System.Console.WriteLine($"b = {s}"); + } } diff --git a/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected b/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected index a1180149878..ef2635cdabf 100644 --- a/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected @@ -58,3 +58,5 @@ | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | | Splitting.cs:34:19:34:19 | access to local variable x | +| Splitting.cs:41:19:41:19 | access to local variable s | +| Splitting.cs:43:19:43:19 | access to local variable s | diff --git a/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected b/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected index 32251581ce6..c14837bf6d5 100644 --- a/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected +++ b/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected @@ -240,6 +240,8 @@ edges | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:34:19:34:19 | access to local variable x | | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | +| Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | Splitting.cs:41:19:41:19 | access to local variable s | +| Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | Splitting.cs:43:19:43:19 | access to local variable s | nodes | Capture.cs:7:20:7:26 | tainted : String | semmle.label | tainted : String | | Capture.cs:12:19:12:24 | access to local variable sink27 | semmle.label | access to local variable sink27 | @@ -443,12 +445,17 @@ nodes | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | semmle.label | [b (line 24): false] access to local variable x | | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | semmle.label | [b (line 24): true] access to local variable x | | Splitting.cs:34:19:34:19 | access to local variable x | semmle.label | access to local variable x | +| Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | semmle.label | [b (line 37): true] "taint source" : String | +| Splitting.cs:41:19:41:19 | access to local variable s | semmle.label | access to local variable s | +| Splitting.cs:43:19:43:19 | access to local variable s | semmle.label | access to local variable s | #select | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | [b (line 24): false] access to local variable x | | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | [b (line 24): true] access to local variable x | | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | [b (line 3): false] access to local variable x | | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | [b (line 3): true] access to local variable x | | GlobalDataFlow.cs:19:15:19:29 | access to field SinkField0 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:19:15:19:29 | access to field SinkField0 | access to field SinkField0 | +| Splitting.cs:41:19:41:19 | access to local variable s | Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | Splitting.cs:41:19:41:19 | access to local variable s | access to local variable s | +| Splitting.cs:43:19:43:19 | access to local variable s | Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | Splitting.cs:43:19:43:19 | access to local variable s | access to local variable s | | GlobalDataFlow.cs:72:15:72:19 | access to local variable sink0 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:72:15:72:19 | access to local variable sink0 | access to local variable sink0 | | GlobalDataFlow.cs:74:15:74:19 | access to local variable sink1 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:74:15:74:19 | access to local variable sink1 | access to local variable sink1 | | GlobalDataFlow.cs:191:15:191:20 | access to local variable sink10 | GlobalDataFlow.cs:338:16:338:29 | "taint source" : String | GlobalDataFlow.cs:191:15:191:20 | access to local variable sink10 | access to local variable sink10 | diff --git a/csharp/ql/test/library-tests/dataflow/global/Splitting.cs b/csharp/ql/test/library-tests/dataflow/global/Splitting.cs index 8749c4c44c7..e1e1534052c 100644 --- a/csharp/ql/test/library-tests/dataflow/global/Splitting.cs +++ b/csharp/ql/test/library-tests/dataflow/global/Splitting.cs @@ -33,4 +33,22 @@ class Splitting if (b) Check(x); } + + void M3(bool b) + { + var s = b ? "taint source" : "not tainted"; + if (b) + Check(s); // flow + else + Check(s); // no flow [FALSE POSITIVE] + } + + void M4(bool b) + { + var s = b switch { true => "taint source", false => "not tainted" }; + if (b) + Check(s); // flow [MISSING] + else + Check(s); // no flow + } } diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected b/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected index fd045c5e8d5..c6580ab0f96 100644 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected +++ b/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected @@ -62,3 +62,5 @@ | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | | Splitting.cs:34:19:34:19 | access to local variable x | +| Splitting.cs:41:19:41:19 | access to local variable s | +| Splitting.cs:43:19:43:19 | access to local variable s | diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected index 32a2e9749e7..f958149af33 100644 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected +++ b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected @@ -247,6 +247,8 @@ edges | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:34:19:34:19 | access to local variable x | | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | +| Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | Splitting.cs:41:19:41:19 | access to local variable s | +| Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | Splitting.cs:43:19:43:19 | access to local variable s | nodes | Capture.cs:7:20:7:26 | tainted : String | semmle.label | tainted : String | | Capture.cs:12:19:12:24 | access to local variable sink27 | semmle.label | access to local variable sink27 | @@ -457,6 +459,9 @@ nodes | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | semmle.label | [b (line 24): false] access to local variable x | | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | semmle.label | [b (line 24): true] access to local variable x | | Splitting.cs:34:19:34:19 | access to local variable x | semmle.label | access to local variable x | +| Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | semmle.label | [b (line 37): true] "taint source" : String | +| Splitting.cs:41:19:41:19 | access to local variable s | semmle.label | access to local variable s | +| Splitting.cs:43:19:43:19 | access to local variable s | semmle.label | access to local variable s | #select | Capture.cs:12:19:12:24 | access to local variable sink27 | Capture.cs:7:20:7:26 | tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 | access to local variable sink27 | | Capture.cs:21:23:21:28 | access to local variable sink28 | Capture.cs:7:20:7:26 | tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 | access to local variable sink28 | @@ -522,3 +527,5 @@ nodes | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | [b (line 24): false] access to local variable x | | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | [b (line 24): true] access to local variable x | | Splitting.cs:34:19:34:19 | access to local variable x | Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:34:19:34:19 | access to local variable x | access to local variable x | +| Splitting.cs:41:19:41:19 | access to local variable s | Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | Splitting.cs:41:19:41:19 | access to local variable s | access to local variable s | +| Splitting.cs:43:19:43:19 | access to local variable s | Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | Splitting.cs:43:19:43:19 | access to local variable s | access to local variable s | From 31816af11efdbc58c8266cea7e35fc8f8aaa8383 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 7 Oct 2020 17:02:01 +0200 Subject: [PATCH 286/411] C#: Add missing data-flow for switch expressions --- .../code/csharp/dataflow/internal/DataFlowPrivate.qll | 4 ++++ .../test/library-tests/dataflow/global/DataFlow.expected | 2 ++ .../library-tests/dataflow/global/DataFlowPath.expected | 7 +++++++ csharp/ql/test/library-tests/dataflow/global/Splitting.cs | 4 ++-- .../library-tests/dataflow/global/TaintTracking.expected | 2 ++ .../dataflow/global/TaintTrackingPath.expected | 7 +++++++ 6 files changed, 24 insertions(+), 2 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index a2a1cd9e9fe..7c7eadf16d6 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -171,6 +171,10 @@ module LocalFlow { e1 = e2.(ArrayCreation).getInitializer() and scope = e2 and isSuccessor = false + or + e1 = e2.(SwitchExpr).getACase().getBody() and + scope = e2 and + isSuccessor = false ) } diff --git a/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected b/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected index ef2635cdabf..6c3ddef4547 100644 --- a/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected @@ -60,3 +60,5 @@ | Splitting.cs:34:19:34:19 | access to local variable x | | Splitting.cs:41:19:41:19 | access to local variable s | | Splitting.cs:43:19:43:19 | access to local variable s | +| Splitting.cs:50:19:50:19 | access to local variable s | +| Splitting.cs:52:19:52:19 | access to local variable s | diff --git a/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected b/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected index c14837bf6d5..68fdc98c16b 100644 --- a/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected +++ b/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected @@ -242,6 +242,8 @@ edges | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | | Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | Splitting.cs:41:19:41:19 | access to local variable s | | Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | Splitting.cs:43:19:43:19 | access to local variable s | +| Splitting.cs:48:36:48:49 | "taint source" : String | Splitting.cs:50:19:50:19 | access to local variable s | +| Splitting.cs:48:36:48:49 | "taint source" : String | Splitting.cs:52:19:52:19 | access to local variable s | nodes | Capture.cs:7:20:7:26 | tainted : String | semmle.label | tainted : String | | Capture.cs:12:19:12:24 | access to local variable sink27 | semmle.label | access to local variable sink27 | @@ -448,6 +450,9 @@ nodes | Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | semmle.label | [b (line 37): true] "taint source" : String | | Splitting.cs:41:19:41:19 | access to local variable s | semmle.label | access to local variable s | | Splitting.cs:43:19:43:19 | access to local variable s | semmle.label | access to local variable s | +| Splitting.cs:48:36:48:49 | "taint source" : String | semmle.label | "taint source" : String | +| Splitting.cs:50:19:50:19 | access to local variable s | semmle.label | access to local variable s | +| Splitting.cs:52:19:52:19 | access to local variable s | semmle.label | access to local variable s | #select | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | [b (line 24): false] access to local variable x | | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | [b (line 24): true] access to local variable x | @@ -456,6 +461,8 @@ nodes | GlobalDataFlow.cs:19:15:19:29 | access to field SinkField0 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:19:15:19:29 | access to field SinkField0 | access to field SinkField0 | | Splitting.cs:41:19:41:19 | access to local variable s | Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | Splitting.cs:41:19:41:19 | access to local variable s | access to local variable s | | Splitting.cs:43:19:43:19 | access to local variable s | Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | Splitting.cs:43:19:43:19 | access to local variable s | access to local variable s | +| Splitting.cs:50:19:50:19 | access to local variable s | Splitting.cs:48:36:48:49 | "taint source" : String | Splitting.cs:50:19:50:19 | access to local variable s | access to local variable s | +| Splitting.cs:52:19:52:19 | access to local variable s | Splitting.cs:48:36:48:49 | "taint source" : String | Splitting.cs:52:19:52:19 | access to local variable s | access to local variable s | | GlobalDataFlow.cs:72:15:72:19 | access to local variable sink0 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:72:15:72:19 | access to local variable sink0 | access to local variable sink0 | | GlobalDataFlow.cs:74:15:74:19 | access to local variable sink1 | GlobalDataFlow.cs:18:27:18:40 | "taint source" : String | GlobalDataFlow.cs:74:15:74:19 | access to local variable sink1 | access to local variable sink1 | | GlobalDataFlow.cs:191:15:191:20 | access to local variable sink10 | GlobalDataFlow.cs:338:16:338:29 | "taint source" : String | GlobalDataFlow.cs:191:15:191:20 | access to local variable sink10 | access to local variable sink10 | diff --git a/csharp/ql/test/library-tests/dataflow/global/Splitting.cs b/csharp/ql/test/library-tests/dataflow/global/Splitting.cs index e1e1534052c..30b9a1b9d71 100644 --- a/csharp/ql/test/library-tests/dataflow/global/Splitting.cs +++ b/csharp/ql/test/library-tests/dataflow/global/Splitting.cs @@ -47,8 +47,8 @@ class Splitting { var s = b switch { true => "taint source", false => "not tainted" }; if (b) - Check(s); // flow [MISSING] + Check(s); // flow else - Check(s); // no flow + Check(s); // no flow [FALSE POSITIVE] } } diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected b/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected index c6580ab0f96..fbd507ea781 100644 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected +++ b/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected @@ -64,3 +64,5 @@ | Splitting.cs:34:19:34:19 | access to local variable x | | Splitting.cs:41:19:41:19 | access to local variable s | | Splitting.cs:43:19:43:19 | access to local variable s | +| Splitting.cs:50:19:50:19 | access to local variable s | +| Splitting.cs:52:19:52:19 | access to local variable s | diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected index f958149af33..5f4a898112b 100644 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected +++ b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected @@ -249,6 +249,8 @@ edges | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | | Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | Splitting.cs:41:19:41:19 | access to local variable s | | Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | Splitting.cs:43:19:43:19 | access to local variable s | +| Splitting.cs:48:36:48:49 | "taint source" : String | Splitting.cs:50:19:50:19 | access to local variable s | +| Splitting.cs:48:36:48:49 | "taint source" : String | Splitting.cs:52:19:52:19 | access to local variable s | nodes | Capture.cs:7:20:7:26 | tainted : String | semmle.label | tainted : String | | Capture.cs:12:19:12:24 | access to local variable sink27 | semmle.label | access to local variable sink27 | @@ -462,6 +464,9 @@ nodes | Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | semmle.label | [b (line 37): true] "taint source" : String | | Splitting.cs:41:19:41:19 | access to local variable s | semmle.label | access to local variable s | | Splitting.cs:43:19:43:19 | access to local variable s | semmle.label | access to local variable s | +| Splitting.cs:48:36:48:49 | "taint source" : String | semmle.label | "taint source" : String | +| Splitting.cs:50:19:50:19 | access to local variable s | semmle.label | access to local variable s | +| Splitting.cs:52:19:52:19 | access to local variable s | semmle.label | access to local variable s | #select | Capture.cs:12:19:12:24 | access to local variable sink27 | Capture.cs:7:20:7:26 | tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 | access to local variable sink27 | | Capture.cs:21:23:21:28 | access to local variable sink28 | Capture.cs:7:20:7:26 | tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 | access to local variable sink28 | @@ -529,3 +534,5 @@ nodes | Splitting.cs:34:19:34:19 | access to local variable x | Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:34:19:34:19 | access to local variable x | access to local variable x | | Splitting.cs:41:19:41:19 | access to local variable s | Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | Splitting.cs:41:19:41:19 | access to local variable s | access to local variable s | | Splitting.cs:43:19:43:19 | access to local variable s | Splitting.cs:39:21:39:34 | [b (line 37): true] "taint source" : String | Splitting.cs:43:19:43:19 | access to local variable s | access to local variable s | +| Splitting.cs:50:19:50:19 | access to local variable s | Splitting.cs:48:36:48:49 | "taint source" : String | Splitting.cs:50:19:50:19 | access to local variable s | access to local variable s | +| Splitting.cs:52:19:52:19 | access to local variable s | Splitting.cs:48:36:48:49 | "taint source" : String | Splitting.cs:52:19:52:19 | access to local variable s | access to local variable s | From 439f0a030edce761d6eabbc40d5f0413d7b11565 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 7 Oct 2020 16:14:35 +0100 Subject: [PATCH 287/411] tidy up custom css --- .../global-sphinx-files/_static/custom.css_t | 383 +++--------------- 1 file changed, 64 insertions(+), 319 deletions(-) diff --git a/docs/language/global-sphinx-files/_static/custom.css_t b/docs/language/global-sphinx-files/_static/custom.css_t index 09d8e87f64c..00386a8157f 100644 --- a/docs/language/global-sphinx-files/_static/custom.css_t +++ b/docs/language/global-sphinx-files/_static/custom.css_t @@ -1,151 +1,19 @@ /* - * Sphinx stylesheet to add some customizations to the default Alabaster theme. + * This Sphinx stylesheet adds some customizations to the default Alabaster theme. * * The source for the default stylesheet can be found at * https://github.com/bitprophet/alabaster/blob/master/alabaster/static/alabaster.css_t * + * For the classes provided by the primer, see https://unpkg.com/@primer/css/dist/primer.css */ -/* -- HEADER ------------------------------------------------------------------------------- */ - -div.header { - background-color: #140f46; - top:0; - position: fixed; - width: 100%; - padding: 0 30px 30px 30px; -} - -#siteBanner { - width: 100%; - height: 80px; - margin: 0; - opacity: 0.95; - z-index: 1; - transform: translate3d(0px, 0px, 0px); - position: relative; -} - -#siteBanner input { - border-width: 0; - /*color: rgb(244, 244, 244); - background-color: #140f46; - font-size: 0.9rem;*/ - letter-spacing: 0.1rem; - /*width: 12rem;*/ -} - -#siteBanner input:focus, -#siteBanner textarea:focus, -#siteBanner select:focus{ - outline: none; -} - -div.logocontainer { - height: 72px; - width: 350px; - position: absolute; - top: 50%; - transform: translateY(-50%); - -ms-transform: translateY(-50%); - -webkit-transform: translateY(-50%); -} - -div.linkcontainer { - width: 70%; - position: absolute; - top: 50%; - transform: translateY(-50%); - -ms-transform: translateY(-50%); - -webkit-transform: translateY(-50%); - right: 15px; -} - -div.linkbar { - float:right; -} - -.linkbar a { - color: black; - font-size: 20px; - margin-left: 20px; - text-decoration: none; -} - -.linkbar a:hover { - text-decoration: underline; -} +/* -- FOOTER ------------------------------------------------------------------------------- */ div.footer { width: 100%; } -/* CODEQL DOCUMENTATION AND SEARCHBOX BANNER ---------------------------------------------------------- */ - -#title-banner { - background: #140f46; - height: 50px; - position: relative; -} - -#title-banner a { - color: white; - font-size: 32px; - text-decoration: none; - position: absolute; - top: 50%; - transform: translateY(-50%); - -ms-transform: translateY(-50%); - -webkit-transform: translateY(-50%); - left: 32px; -} - -#searchbox-title-banner { - position: absolute; - top: 50%; - transform: translateY(-50%); - -ms-transform: translateY(-50%); - -webkit-transform: translateY(-50%); - right: 32px; -} - -#searchbox-navbar { - display: none; -} - -#textfield { - position: relative; - float: left; -} - -#searchbutton { - position: relative; - float: left; -} - -/* -- WRAPPER CONTAINING NAVBAR AND MAIN BOX --------------------------------------------------*/ - -div.wrapper { - margin-bottom: 0px; - height: 637px; -} - -/* -- DOCUMENT ------------------------------------------------------------------------------- */ - -div.document { - width: 95%; - padding: 0; - margin: 0 0 30px 0; -} - -div.documentwrapper { - width: 90%; - margin: 20px 20px 20px 20px; - padding-bottom: 50px; -} -div.mainBox { - margin-left: calc(30% + 25px); /* Allow 25px for the width of the ToC scrollbar */ -} +/* -- PRIVACY NOTICE ----------------------------------------------------------------------- */ div.privacy { text-align: right; @@ -153,6 +21,16 @@ div.privacy { padding-bottom: 20px; } +code { + font-size: 0.9em !important; /* makes code snippets in headings the correct size */ +} + +/* -- MAIN BODY ---------------------------------------------------------------------------- */ + +div.body { + max-width: 100%; +} + div.body li { margin: 0 0 0.5em 0; /* Increase spacing between list items */ } @@ -163,36 +41,25 @@ div.body li { height: 100vh; } -div.navBox { - width:29%; - padding-left: 25px; - height: calc(100% - 108px); - z-index: 100; - background-color: #FFFFFF; - padding-top: 30px; - color: black; - float: left; -} - -.navBox li { +.SideNav li { margin: 10px 0 10px 0px; } -.navBox ul, .navBox ol, .navBox li { +.SideNav ul, .SideNav ol, .SideNav li { list-style-type: none; } -.navBox ul li a { +.SideNav ul li a { border-bottom: none; color: black; } -.navBox ul li a:hover { +.SideNav ul li a:hover { font-weight: bold; border-bottom: none; } -.navBox a.current { +.SideNav a.current { font-weight: bold; text-decoration: underline; } @@ -203,6 +70,8 @@ div.related ul { padding: 0; } +/* -- LINKS --------------------------------------------------------------------------------------*/ + a.reference { border-bottom: none; } @@ -211,158 +80,7 @@ a.reference:hover { text-decoration: none; } -/* -- SIDEBAR TOC ----------------------------------------------------------------------------------*/ - -#toc h1 { - font-size: 20px; - font-weight: bold; - margin-left: 28px; -} - -/* -- SMALL SCREEN ------------------------------------------------------------------------------- */ - -@media screen and (max-width: 875px){ - /* Override strange behaviour caused by default styles */ - body { - padding: 0; - } - - div.footer { - display: block; - } - - #siteBanner { - position: relative; - } - - div.logocontainer { - width: 200px; - } - - .linkcontainer a:not(:first-child) { /* Only display Learn CodeQL link on small screen */ - display: none; - } - - #title-banner a { - font-size: 5vw; - } - - #searchbox-title-banner { /* Move searchbox from title banner to sidebar on small screen */ - display: none; - } - - #searchbox-navbar { - display: block; - float: left; - margin-right: 20px; - } - - div.navBox { - position: relative; - width: 95%; - border-color: #2f1695; - padding-top: 10px; - } - - #toc h1 { /* Slightly reposition the heading on small screens */ - margin-left: 18px; - } - - div.wrapper { - flex-direction: column; - height: 100%; - width: 100%; - padding-top: 0px; - } - div.mainBox { - margin: 0 10px 0 10px; - position: relative; - height: 100%; - width: 95%; - } - div.documentwrapper { - padding-left: 20px; - width:100%; - box-shadow: none; - margin: 0; - padding-left:0; - } - - - ul { - margin: 10px 20px 10px 20px; - } - - div.privacy { - padding-right: 0%; - } - -} - -/* -- PRINT VIEW ----------------------------------------------------------------------------*/ - -@media print { - div.navBox { - display: none; - } - - #siteBanner { - display: none; - } - - div.wrapper { - /*margin-top:-100px;*/ - flex-direction: column; - height: 100%; - width: 100%; - padding-top: 0px; - } - div.mainBox { - margin: 0 10px 0 10px; - position: relative; - height: 100%; - width: 100%; - } - div.documentwrapper { - padding-left: 20px; - width:100%; - box-shadow: none; - margin: 0; - padding-left:0; - } - - body { - margin: 0; - padding: 0; - overflow: inherit; - width:95%; - } - - div.body { - min-width: unset; - } - div.linkbar { - display: none; - - } - .small-bar { - display: inherit; - } - - ul { - margin: 10px 20px 10px 20px; - } - - div.privacy { - display: none; - } -} - -/* -- MAIN BODY ---------------------------------------------------------------------------- */ - -div.body { - max-width: 100%; /* overrule 800px in basic.css */ -} +/* -- ADMONITIONS ---------------------------------------------------------------------------- */ /* * Override default styling for "admonitions". @@ -403,6 +121,8 @@ pre { white-space: pre-wrap; } +/* -- QL SYNTAX HIGHLIGHTING -------------------------------------------------- */ + /* * Use more appropriate colors for syntax highlighting * @@ -418,30 +138,20 @@ pre { .highlight .kt { color: #7a65cd; font-weight: bold } /* built-in type keywords */ .highlight .kr { color: #333; font-style: italic } /* annotations */ + +/* -- SEARCH PAGE ---------------------------------------------------------------------------- */ + div.context { /* hide rst search snippets */ display: none; } -/* -- INDEX -------------------------------------------------------------------------------- */ +/* -- INDEX ---------------------------------------------------------------------------------------- */ table.indextable li > a { text-decoration: unset; } - -/* -- FOOTER ------------------------------------------------------------------------------- */ - -/* Adjust anchor targets to allow for the fixed banner */ -div.documentwrapper a[name], -div.documentwrapper :target::before, -div.footnote-group a[name], -div.footnote-group :target::before - { - content: ""; - display: block; - height: 78px; /* Height of banner */ - margin-top: -78px; /* Prevent this showing as a gap */ -} +/* -- ANCHOR LINKS ------------------------------------------------------------------------------- */ /* make anchor highlighting more sensible */ @@ -508,4 +218,39 @@ blockquote.pull-quote > :last-child { .toggle .name.open:after { content: " â–¼"; +} + +/* -- PRINT VIEW ----------------------------------------------------------------------------*/ + +@media print { + + div.SideNav { + display: none; + } + + body { + margin: 0; + padding: 0; + overflow: inherit; + width:95%; + } + + div.privacy { + display: none; + } +} + +/* -- SMALL SCREEN ------------------------------------------------------------------------------- */ + +@media screen and (max-width: 875px) { + + /* Overrides strange behaviour caused by default styles */ + + body { + padding: 0; + } + + div.footer { + display: block; + } } \ No newline at end of file From b04962b5b929367618aa9d815558ba718b3e5d7a Mon Sep 17 00:00:00 2001 From: james Date: Wed, 7 Oct 2020 16:14:58 +0100 Subject: [PATCH 288/411] small changes to conf.py --- docs/language/global-sphinx-files/global-conf.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/language/global-sphinx-files/global-conf.py b/docs/language/global-sphinx-files/global-conf.py index f09b600c0b7..dfd742da753 100644 --- a/docs/language/global-sphinx-files/global-conf.py +++ b/docs/language/global-sphinx-files/global-conf.py @@ -38,7 +38,7 @@ extensions = [ ] # The encoding of source files. -#source_encoding = 'utf-8-sig' +source_encoding = 'utf-8-sig' # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' @@ -86,10 +86,9 @@ html_theme_options = {'font_size': '16px', 'body_text': '#333', 'link': '#2F1695', 'link_hover': '#2F1695', - 'font_family': 'Lato, sans-serif', - 'head_font_family': 'Moderat, sans-serif', 'show_powered_by': False, 'nosidebar':True, + 'head_font_family': '-apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"', } # Add any paths that contain templates here, relative to this directory. From 9fc6ae82d3229399a4500ade5380e3fc8aab1f33 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 7 Oct 2020 16:15:25 +0100 Subject: [PATCH 289/411] update template for sphinx codeql docs --- .../_templates/layout.html | 206 +++++++++--------- 1 file changed, 103 insertions(+), 103 deletions(-) diff --git a/docs/language/global-sphinx-files/_templates/layout.html b/docs/language/global-sphinx-files/_templates/layout.html index 3fbaf4a0d25..c7631443ca1 100644 --- a/docs/language/global-sphinx-files/_templates/layout.html +++ b/docs/language/global-sphinx-files/_templates/layout.html @@ -1,10 +1,9 @@ {# - Override alabaster/layout.html template to add a header - with the Semmle logo. - This header (including the SVG logo) is copied from the Semmle - documentation home page at help.semmle.com. - - It also adds some JavaScript (in the footer) to allow collapsible sections. + Override alabaster/layout.html template to customize the template + used to generate the CodeQL documentation. + + The classes used in this template are provided by the GitHub Primer https://primer.style/css/. + The CSS for the primer can be found at https://unpkg.com/@primer/css/dist/primer.css The source for the default Alabaster stylesheet can be found at: https://github.com/bitprophet/alabaster/blob/master/alabaster/layout.html @@ -12,121 +11,122 @@ {%- extends "alabaster/layout.html" %} +{%- macro customrelbar() %} + +{%- endmacro %} + {%- block extrahead %} - - - - {{ super() }} - - {% if theme_touch_icon %} - - {% endif %} - {% if theme_canonical_url %} - - {% endif %} - + +CodeQL docs + + + + {% endblock %} {%- block content %} - - - -
    -
    -
    - -
    - {{ project }} - - -
    +
  • Learn CodeQL
  • +
  • CodeQL tools +
  • + + +
  • QL language reference +
  • CodeQL libraries +
  • CodeQL + queries +
  • + +
  • CodeQL repository + + + +
  • +
    -
    - -
    From 1f1be3bf9a76893179e42e419985ae54f8db2457 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 9 Oct 2020 10:04:22 +0100 Subject: [PATCH 322/411] C++: Block try_emplace arg 0. --- .../code/cpp/models/implementations/StdMap.qll | 7 +++---- .../dataflow/taint-tests/localTaint.expected | 12 ------------ 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll index a55bd9f08fc..813e0fc3bb1 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdMap.qll @@ -81,11 +81,10 @@ class StdMapTryEmplace extends TaintFunction { // flow from any parameter apart from the key to qualifier and return value // (here we assume taint flow from any constructor parameter to the constructed object) // (where the return value is a pair, this should really flow just to the first part of it) - exists(int arg | arg = [0 .. getNumberOfParameters() - 1] | + exists(int arg | arg = [1 .. getNumberOfParameters() - 1] | ( - getUnspecifiedType() instanceof Iterator and arg != 1 - or - not getUnspecifiedType() instanceof Iterator and arg != 0 + not getUnspecifiedType() instanceof Iterator or + arg != 1 ) and input.isParameterDeref(arg) ) and 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 629b5e5f394..44120541820 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -1199,8 +1199,6 @@ | map.cpp:248:23:248:25 | ref arg m27 | map.cpp:250:23:250:25 | m27 | | | map.cpp:248:23:248:25 | ref arg m27 | map.cpp:251:7:251:9 | m27 | | | map.cpp:248:23:248:25 | ref arg m27 | map.cpp:252:1:252:1 | m27 | | -| map.cpp:248:23:248:33 | call to iterator | map.cpp:248:7:248:9 | ref arg m27 | TAINT | -| map.cpp:248:23:248:33 | call to iterator | map.cpp:248:11:248:21 | call to try_emplace | TAINT | | map.cpp:248:27:248:31 | call to begin | map.cpp:248:23:248:33 | call to iterator | TAINT | | map.cpp:248:43:248:47 | def | map.cpp:248:7:248:9 | ref arg m27 | TAINT | | map.cpp:248:43:248:47 | def | map.cpp:248:11:248:21 | call to try_emplace | TAINT | @@ -1211,8 +1209,6 @@ | map.cpp:250:23:250:25 | ref arg m27 | map.cpp:250:7:250:9 | m27 | | | map.cpp:250:23:250:25 | ref arg m27 | map.cpp:251:7:251:9 | m27 | | | map.cpp:250:23:250:25 | ref arg m27 | map.cpp:252:1:252:1 | m27 | | -| map.cpp:250:23:250:33 | call to iterator | map.cpp:250:7:250:9 | ref arg m27 | TAINT | -| map.cpp:250:23:250:33 | call to iterator | map.cpp:250:11:250:21 | call to try_emplace | TAINT | | map.cpp:250:27:250:31 | call to begin | map.cpp:250:23:250:33 | call to iterator | TAINT | | map.cpp:250:43:250:48 | call to source | map.cpp:250:7:250:9 | ref arg m27 | TAINT | | map.cpp:250:43:250:48 | call to source | map.cpp:250:11:250:21 | call to try_emplace | TAINT | @@ -1872,8 +1868,6 @@ | map.cpp:399:23:399:25 | ref arg m27 | map.cpp:401:23:401:25 | m27 | | | map.cpp:399:23:399:25 | ref arg m27 | map.cpp:402:7:402:9 | m27 | | | map.cpp:399:23:399:25 | ref arg m27 | map.cpp:422:1:422:1 | m27 | | -| map.cpp:399:23:399:33 | call to iterator | map.cpp:399:7:399:9 | ref arg m27 | TAINT | -| map.cpp:399:23:399:33 | call to iterator | map.cpp:399:11:399:21 | call to try_emplace | TAINT | | map.cpp:399:27:399:31 | call to begin | map.cpp:399:23:399:33 | call to iterator | TAINT | | map.cpp:399:43:399:47 | def | map.cpp:399:7:399:9 | ref arg m27 | TAINT | | map.cpp:399:43:399:47 | def | map.cpp:399:11:399:21 | call to try_emplace | TAINT | @@ -1884,8 +1878,6 @@ | map.cpp:401:23:401:25 | ref arg m27 | map.cpp:401:7:401:9 | m27 | | | map.cpp:401:23:401:25 | ref arg m27 | map.cpp:402:7:402:9 | m27 | | | map.cpp:401:23:401:25 | ref arg m27 | map.cpp:422:1:422:1 | m27 | | -| map.cpp:401:23:401:33 | call to iterator | map.cpp:401:7:401:9 | ref arg m27 | TAINT | -| map.cpp:401:23:401:33 | call to iterator | map.cpp:401:11:401:21 | call to try_emplace | TAINT | | map.cpp:401:27:401:31 | call to begin | map.cpp:401:23:401:33 | call to iterator | TAINT | | map.cpp:401:43:401:48 | call to source | map.cpp:401:7:401:9 | ref arg m27 | TAINT | | map.cpp:401:43:401:48 | call to source | map.cpp:401:11:401:21 | call to try_emplace | TAINT | @@ -1902,8 +1894,6 @@ | map.cpp:403:23:403:25 | ref arg m28 | map.cpp:405:23:405:25 | m28 | | | map.cpp:403:23:403:25 | ref arg m28 | map.cpp:406:7:406:9 | m28 | | | map.cpp:403:23:403:25 | ref arg m28 | map.cpp:422:1:422:1 | m28 | | -| map.cpp:403:23:403:33 | call to iterator | map.cpp:403:7:403:9 | ref arg m28 | TAINT | -| map.cpp:403:23:403:33 | call to iterator | map.cpp:403:11:403:21 | call to try_emplace | TAINT | | map.cpp:403:27:403:31 | call to begin | map.cpp:403:23:403:33 | call to iterator | TAINT | | map.cpp:403:43:403:47 | def | map.cpp:403:7:403:9 | ref arg m28 | TAINT | | map.cpp:403:43:403:47 | def | map.cpp:403:11:403:21 | call to try_emplace | TAINT | @@ -1914,8 +1904,6 @@ | map.cpp:405:23:405:25 | ref arg m28 | map.cpp:405:7:405:9 | m28 | | | map.cpp:405:23:405:25 | ref arg m28 | map.cpp:406:7:406:9 | m28 | | | map.cpp:405:23:405:25 | ref arg m28 | map.cpp:422:1:422:1 | m28 | | -| map.cpp:405:23:405:33 | call to iterator | map.cpp:405:7:405:9 | ref arg m28 | TAINT | -| map.cpp:405:23:405:33 | call to iterator | map.cpp:405:11:405:21 | call to try_emplace | TAINT | | map.cpp:405:27:405:31 | call to begin | map.cpp:405:23:405:33 | call to iterator | TAINT | | map.cpp:405:46:405:50 | def | map.cpp:405:7:405:9 | ref arg m28 | TAINT | | map.cpp:405:46:405:50 | def | map.cpp:405:11:405:21 | call to try_emplace | TAINT | From 6d78c7b46e97b023169548f7d212bb06868baa2f Mon Sep 17 00:00:00 2001 From: james Date: Fri, 9 Oct 2020 10:04:39 +0100 Subject: [PATCH 323/411] fix path to primer.css in template --- docs/language/global-sphinx-files/_templates/layout.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/global-sphinx-files/_templates/layout.html b/docs/language/global-sphinx-files/_templates/layout.html index 1b7b7cb11af..5e848e0c02d 100644 --- a/docs/language/global-sphinx-files/_templates/layout.html +++ b/docs/language/global-sphinx-files/_templates/layout.html @@ -31,7 +31,7 @@ CodeQL docs - + {% endblock %} From 1c043447e8be5802c3c0b9910e8ce4786125bc49 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Fri, 9 Oct 2020 14:29:52 +0200 Subject: [PATCH 324/411] Dataflow: Introduce consistency check for flow targeting PostUpdateNodes. --- .../code/cpp/dataflow/internal/DataFlowImplConsistency.qll | 5 +++++ .../cpp/ir/dataflow/internal/DataFlowImplConsistency.qll | 5 +++++ .../csharp/dataflow/internal/DataFlowImplConsistency.qll | 5 +++++ .../code/java/dataflow/internal/DataFlowImplConsistency.qll | 5 +++++ .../dataflow/internal/DataFlowImplConsistency.qll | 5 +++++ 5 files changed, 25 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll index 920855517c9..4e1cd281488 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll @@ -167,4 +167,9 @@ module Consistency { not isImmutableOrUnobservable(n) and msg = "ArgumentNode is missing PostUpdateNode." } + + query predicate postWithInFlow(PostUpdateNode n, string msg) { + simpleLocalFlowStep(_, n) and + msg = "PostUpdateNode should not be the target of local flow." + } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll index 920855517c9..4e1cd281488 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll @@ -167,4 +167,9 @@ module Consistency { not isImmutableOrUnobservable(n) and msg = "ArgumentNode is missing PostUpdateNode." } + + query predicate postWithInFlow(PostUpdateNode n, string msg) { + simpleLocalFlowStep(_, n) and + msg = "PostUpdateNode should not be the target of local flow." + } } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll index 920855517c9..4e1cd281488 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll @@ -167,4 +167,9 @@ module Consistency { not isImmutableOrUnobservable(n) and msg = "ArgumentNode is missing PostUpdateNode." } + + query predicate postWithInFlow(PostUpdateNode n, string msg) { + simpleLocalFlowStep(_, n) and + msg = "PostUpdateNode should not be the target of local flow." + } } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll index 920855517c9..4e1cd281488 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll @@ -167,4 +167,9 @@ module Consistency { not isImmutableOrUnobservable(n) and msg = "ArgumentNode is missing PostUpdateNode." } + + query predicate postWithInFlow(PostUpdateNode n, string msg) { + simpleLocalFlowStep(_, n) and + msg = "PostUpdateNode should not be the target of local flow." + } } diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowImplConsistency.qll b/python/ql/src/experimental/dataflow/internal/DataFlowImplConsistency.qll index 920855517c9..4e1cd281488 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowImplConsistency.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowImplConsistency.qll @@ -167,4 +167,9 @@ module Consistency { not isImmutableOrUnobservable(n) and msg = "ArgumentNode is missing PostUpdateNode." } + + query predicate postWithInFlow(PostUpdateNode n, string msg) { + simpleLocalFlowStep(_, n) and + msg = "PostUpdateNode should not be the target of local flow." + } } From f6f8bbd1d8657395de8eb65ab0f3704b294ccb01 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 9 Oct 2020 14:46:31 +0200 Subject: [PATCH 325/411] Update javascript/ql/src/semmle/javascript/frameworks/ServerLess.qll Co-authored-by: Esben Sparre Andreasen --- javascript/ql/src/semmle/javascript/frameworks/ServerLess.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/ServerLess.qll b/javascript/ql/src/semmle/javascript/frameworks/ServerLess.qll index 80a831bc0f3..a4998a240c4 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/ServerLess.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/ServerLess.qll @@ -78,7 +78,7 @@ private module ServerLess { * Gets a function that is a serverless request handler. * * For example: if an AWS serverless resource contains the following properties (in the "template.yml" file): - * ``` + * ```yaml * Handler: mylibrary.handler * Runtime: nodejs12.x * CodeUri: backend/src/ From 2fb19f0b117b422d1047af50a0cc969175dd25b9 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 9 Oct 2020 14:50:16 +0200 Subject: [PATCH 326/411] refactor into a single regular expression with two capture groups --- .../ql/src/semmle/javascript/frameworks/ServerLess.qll | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/ServerLess.qll b/javascript/ql/src/semmle/javascript/frameworks/ServerLess.qll index a4998a240c4..15dd6a3da59 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/ServerLess.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/ServerLess.qll @@ -63,10 +63,12 @@ private module ServerLess { private predicate hasServerlessHandler(File file, string func) { exists(File ymlFile, string handler, string codeURI, string fileName | hasServerlessHandler(ymlFile, handler, codeURI) and - // Captures everything right of the dot in `handler`. E.g. if `handler` is "index.foo" then `func` is "foo". - func = handler.regexpCapture(".*\\.(.*)", 1) and - // Captures everything left of the dot in `handler`. E.g. if `handler` is "index.foo" then `fileName` is "index". - fileName = handler.regexpCapture("([^.]+).*", 1) + // Splits a `handler` into two components. The `fileName` to the left of the dot, and the `func` to the right. + // E.g. if `handler` is "index.foo", then `fileName` is "index" and `func` is "foo". + exists(string pattern | pattern = "(.*)\\.(.*)" | + fileName = handler.regexpCapture(pattern, 1) and + func = handler.regexpCapture(pattern, 2) + ) | file.getAbsolutePath() = ymlFile.getParentContainer().getAbsolutePath() + "/" + From a0cbeb6093536da08f6e18781f44965dcb5ed1b9 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 9 Oct 2020 14:54:34 +0200 Subject: [PATCH 327/411] add change note --- change-notes/1.26/analysis-javascript.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/change-notes/1.26/analysis-javascript.md b/change-notes/1.26/analysis-javascript.md index f035156652f..01d35a12c2d 100644 --- a/change-notes/1.26/analysis-javascript.md +++ b/change-notes/1.26/analysis-javascript.md @@ -3,6 +3,8 @@ ## General improvements * Support for the following frameworks and libraries has been improved: + - [AWS Serverless](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html) + - [Alibaba Serverless](https://www.alibabacloud.com/help/doc-detail/156876.htm) - [bluebird](https://www.npmjs.com/package/bluebird) - [express](https://www.npmjs.com/package/express) - [fast-json-stable-stringify](https://www.npmjs.com/package/fast-json-stable-stringify) From 42ee136306e3c462768cc6bdef9e31339ceca2d1 Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Fri, 9 Oct 2020 14:33:45 +0100 Subject: [PATCH 328/411] Update layout.html --- docs/language/global-sphinx-files/_templates/layout.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/language/global-sphinx-files/_templates/layout.html b/docs/language/global-sphinx-files/_templates/layout.html index 5e848e0c02d..029b7c851b2 100644 --- a/docs/language/global-sphinx-files/_templates/layout.html +++ b/docs/language/global-sphinx-files/_templates/layout.html @@ -81,7 +81,7 @@
  • QL language reference
  • CodeQL libraries -
  • CodeQL +
  • CodeQL queries