From 20661a3c5639dc3e2f9c22c3201f48596c392894 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 17 Sep 2024 10:42:21 +0200 Subject: [PATCH 1/2] Java: Fix support for variable capture inside object initializers. --- .../dataflow/internal/DataFlowPrivate.qll | 9 ++++- .../library-tests/dataflow/capture/B.java | 11 +++++++ .../dataflow/capture/inlinetest.expected | 33 +++++++++++++++++++ .../codeql/dataflow/VariableCapture.qll | 8 +++-- 4 files changed, 57 insertions(+), 4 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index 84b31f14e98..784d248d8dc 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -147,7 +147,14 @@ private module CaptureInput implements VariableCapture::InputSig { } class Callable extends J::Callable { - predicate isConstructor() { this instanceof Constructor } + predicate isConstructor() { + // InstanceInitializers are called from constructors and are equally likely + // to capture variables for the purpose of field initialization, so we treat + // them as constructors for the heuristic identification of whether to allow + // this-to-this summaries. + this instanceof Constructor or + this instanceof InstanceInitializer + } } } diff --git a/java/ql/test/library-tests/dataflow/capture/B.java b/java/ql/test/library-tests/dataflow/capture/B.java index 8909358b8a4..25a51d0a985 100644 --- a/java/ql/test/library-tests/dataflow/capture/B.java +++ b/java/ql/test/library-tests/dataflow/capture/B.java @@ -248,4 +248,15 @@ public class B { sink(l.get(0)); // $ hasValueFlow=src sink(l2.get(0)); // $ hasValueFlow=src } + + void testInstanceInitializer() { + String s = source("init"); + class MyLocal3 { + String f = s; + void run() { + sink(this.f); // $ hasValueFlow=init + } + } + new MyLocal3().run(); + } } diff --git a/java/ql/test/library-tests/dataflow/capture/inlinetest.expected b/java/ql/test/library-tests/dataflow/capture/inlinetest.expected index 5c08b6d3c31..e62b9194704 100644 --- a/java/ql/test/library-tests/dataflow/capture/inlinetest.expected +++ b/java/ql/test/library-tests/dataflow/capture/inlinetest.expected @@ -254,6 +254,21 @@ edges | B.java:247:5:247:18 | new MyLocal2(...) [pre constructor] : MyLocal2 [String s] : String | B.java:247:5:247:18 | new MyLocal2(...) : MyLocal2 [List l, ] : String | provenance | MaD:2 | | B.java:248:10:248:10 | l : ArrayList [] : String | B.java:248:10:248:17 | get(...) | provenance | MaD:3 | | B.java:249:10:249:11 | l2 : ArrayList [] : String | B.java:249:10:249:18 | get(...) | provenance | MaD:3 | +| B.java:253:16:253:29 | source(...) : String | B.java:260:5:260:18 | String s : String | provenance | | +| B.java:254:11:254:18 | parameter this : MyLocal3 [String s] : String | B.java:254:11:254:18 | this <.method> : MyLocal3 [String s] : String | provenance | | +| B.java:254:11:254:18 | parameter this : MyLocal3 [String s] : String | B.java:255:18:255:18 | this : MyLocal3 [String s] : String | provenance | | +| B.java:254:11:254:18 | this <.method> : MyLocal3 [String s] : String | B.java:254:11:254:18 | parameter this : MyLocal3 [String s] : String | provenance | | +| B.java:254:11:254:18 | this <.method> : MyLocal3 [String s] : String | B.java:254:11:254:18 | this <.method> [post update] : MyLocal3 [f] : String | provenance | | +| B.java:254:11:254:18 | this <.method> [post update] : MyLocal3 [f] : String | B.java:254:11:254:18 | parameter this [Return] : MyLocal3 [f] : String | provenance | | +| B.java:255:7:255:19 | this <.field> [post update] : MyLocal3 [f] : String | B.java:254:11:254:18 | parameter this [Return] : MyLocal3 [f] : String | provenance | | +| B.java:255:18:255:18 | s : String | B.java:255:7:255:19 | this <.field> [post update] : MyLocal3 [f] : String | provenance | | +| B.java:255:18:255:18 | this : MyLocal3 [String s] : String | B.java:255:18:255:18 | s : String | provenance | | +| B.java:256:12:256:14 | parameter this : MyLocal3 [f] : String | B.java:257:14:257:17 | this : MyLocal3 [f] : String | provenance | | +| B.java:257:14:257:17 | this : MyLocal3 [f] : String | B.java:257:14:257:19 | this.f | provenance | | +| B.java:260:5:260:18 | String s : String | B.java:260:5:260:18 | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | provenance | | +| B.java:260:5:260:18 | new MyLocal3(...) : MyLocal3 [f] : String | B.java:256:12:256:14 | parameter this : MyLocal3 [f] : String | provenance | | +| B.java:260:5:260:18 | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | B.java:254:11:254:18 | parameter this : MyLocal3 [String s] : String | provenance | | +| B.java:260:5:260:18 | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | B.java:260:5:260:18 | new MyLocal3(...) : MyLocal3 [f] : String | provenance | | nodes | B.java:11:5:11:6 | l1 [post update] : ArrayList [] : String | semmle.label | l1 [post update] : ArrayList [] : String | | B.java:11:12:11:22 | source(...) : String | semmle.label | source(...) : String | @@ -511,6 +526,22 @@ nodes | B.java:248:10:248:17 | get(...) | semmle.label | get(...) | | B.java:249:10:249:11 | l2 : ArrayList [] : String | semmle.label | l2 : ArrayList [] : String | | B.java:249:10:249:18 | get(...) | semmle.label | get(...) | +| B.java:253:16:253:29 | source(...) : String | semmle.label | source(...) : String | +| B.java:254:11:254:18 | parameter this : MyLocal3 [String s] : String | semmle.label | parameter this : MyLocal3 [String s] : String | +| B.java:254:11:254:18 | parameter this : MyLocal3 [String s] : String | semmle.label | parameter this : MyLocal3 [String s] : String | +| B.java:254:11:254:18 | parameter this [Return] : MyLocal3 [f] : String | semmle.label | parameter this [Return] : MyLocal3 [f] : String | +| B.java:254:11:254:18 | parameter this [Return] : MyLocal3 [f] : String | semmle.label | parameter this [Return] : MyLocal3 [f] : String | +| B.java:254:11:254:18 | this <.method> : MyLocal3 [String s] : String | semmle.label | this <.method> : MyLocal3 [String s] : String | +| B.java:254:11:254:18 | this <.method> [post update] : MyLocal3 [f] : String | semmle.label | this <.method> [post update] : MyLocal3 [f] : String | +| B.java:255:7:255:19 | this <.field> [post update] : MyLocal3 [f] : String | semmle.label | this <.field> [post update] : MyLocal3 [f] : String | +| B.java:255:18:255:18 | s : String | semmle.label | s : String | +| B.java:255:18:255:18 | this : MyLocal3 [String s] : String | semmle.label | this : MyLocal3 [String s] : String | +| B.java:256:12:256:14 | parameter this : MyLocal3 [f] : String | semmle.label | parameter this : MyLocal3 [f] : String | +| B.java:257:14:257:17 | this : MyLocal3 [f] : String | semmle.label | this : MyLocal3 [f] : String | +| B.java:257:14:257:19 | this.f | semmle.label | this.f | +| B.java:260:5:260:18 | String s : String | semmle.label | String s : String | +| B.java:260:5:260:18 | new MyLocal3(...) : MyLocal3 [f] : String | semmle.label | new MyLocal3(...) : MyLocal3 [f] : String | +| B.java:260:5:260:18 | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | semmle.label | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | subpaths | B.java:13:5:13:6 | l1 : ArrayList [] : String | B.java:13:16:13:16 | e : String | B.java:13:16:13:29 | parameter this [Return] : new Consumer(...) { ... } [List l2, ] : String | B.java:13:16:13:29 | ...->... [post update] : new Consumer(...) { ... } [List l2, ] : String | | B.java:30:14:30:24 | source(...) : String | B.java:22:26:22:26 | x : String | B.java:22:26:22:71 | parameter this [Return] : new Consumer(...) { ... } [B other, bf1] : String | B.java:30:5:30:5 | f [post update] : new Consumer(...) { ... } [B other, bf1] : String | @@ -530,4 +561,6 @@ subpaths | B.java:178:10:178:11 | m2 : MyLocal [List l, ] : String | B.java:169:14:169:16 | parameter this : MyLocal [List l, ] : String | B.java:170:16:170:23 | get(...) : String | B.java:178:10:178:17 | get(...) | | B.java:247:5:247:18 | new MyLocal2(...) : MyLocal2 [List l, ] : String | B.java:240:12:240:14 | parameter this : MyLocal2 [List l, ] : String | B.java:240:12:240:14 | parameter this [Return] : MyLocal2 [List l2, ] : String | B.java:247:5:247:18 | new MyLocal2(...) [post update] : MyLocal2 [List l2, ] : String | | B.java:247:5:247:18 | new MyLocal2(...) [pre constructor] : MyLocal2 [String s] : String | B.java:235:7:235:14 | parameter this : MyLocal2 [String s] : String | B.java:235:7:235:14 | parameter this [Return] : MyLocal2 [List l, ] : String | B.java:247:5:247:18 | new MyLocal2(...) : MyLocal2 [List l, ] : String | +| B.java:254:11:254:18 | this <.method> : MyLocal3 [String s] : String | B.java:254:11:254:18 | parameter this : MyLocal3 [String s] : String | B.java:254:11:254:18 | parameter this [Return] : MyLocal3 [f] : String | B.java:254:11:254:18 | this <.method> [post update] : MyLocal3 [f] : String | +| B.java:260:5:260:18 | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | B.java:254:11:254:18 | parameter this : MyLocal3 [String s] : String | B.java:254:11:254:18 | parameter this [Return] : MyLocal3 [f] : String | B.java:260:5:260:18 | new MyLocal3(...) : MyLocal3 [f] : String | testFailures diff --git a/shared/dataflow/codeql/dataflow/VariableCapture.qll b/shared/dataflow/codeql/dataflow/VariableCapture.qll index 89f2f4f5f9d..8aa1804792b 100644 --- a/shared/dataflow/codeql/dataflow/VariableCapture.qll +++ b/shared/dataflow/codeql/dataflow/VariableCapture.qll @@ -585,11 +585,13 @@ module Flow Input> implements OutputSig 2 <= strictcount(CapturedVariable v | captureAccess(v, c)) or // Constructors that capture a variable may assign it to a field, which also - // entails a this-to-this summary. - captureAccess(_, c) and c.isConstructor() + // entails a this-to-this summary. If there are multiple constructors, then + // they might call each other, so if one constructor captures a variable we + // allow this-to-this summaries for all of them. + exists(ClosureExpr ce | ce.hasBody(c) and c.isConstructor() and hasConstructorCapture(ce, _)) } - /** Holds if the constructor, if any, for the closure defined by `ce` captures `v`. */ + /** Holds if a constructor, if any, for the closure defined by `ce` captures `v`. */ private predicate hasConstructorCapture(ClosureExpr ce, CapturedVariable v) { exists(Callable c | ce.hasBody(c) and c.isConstructor() and captureAccess(v, c)) } From a1a885efebaf95dd3cdfe4a996533b8c8cbfe09e Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 17 Sep 2024 11:38:53 +0200 Subject: [PATCH 2/2] Java: Expand test. --- .../library-tests/dataflow/capture/B.java | 20 +++ .../dataflow/capture/inlinetest.expected | 119 +++++++++++++----- 2 files changed, 106 insertions(+), 33 deletions(-) diff --git a/java/ql/test/library-tests/dataflow/capture/B.java b/java/ql/test/library-tests/dataflow/capture/B.java index 25a51d0a985..6fc406c1a21 100644 --- a/java/ql/test/library-tests/dataflow/capture/B.java +++ b/java/ql/test/library-tests/dataflow/capture/B.java @@ -250,6 +250,7 @@ public class B { } void testInstanceInitializer() { + // Tests capture in the instance initializer ("") String s = source("init"); class MyLocal3 { String f = s; @@ -259,4 +260,23 @@ public class B { } new MyLocal3().run(); } + + void testConstructorIndirection() { + // Tests capture in nested constructor call + String s = source("init"); + class MyLocal4 { + String f; + MyLocal4() { + this(42); + } + MyLocal4(int i) { + f = s; + } + String get() { + return this.f; + } + } + sink(new MyLocal4().get()); // $ hasValueFlow=init + sink(new MyLocal4(1).get()); // $ hasValueFlow=init + } } diff --git a/java/ql/test/library-tests/dataflow/capture/inlinetest.expected b/java/ql/test/library-tests/dataflow/capture/inlinetest.expected index e62b9194704..efd347890dd 100644 --- a/java/ql/test/library-tests/dataflow/capture/inlinetest.expected +++ b/java/ql/test/library-tests/dataflow/capture/inlinetest.expected @@ -254,21 +254,46 @@ edges | B.java:247:5:247:18 | new MyLocal2(...) [pre constructor] : MyLocal2 [String s] : String | B.java:247:5:247:18 | new MyLocal2(...) : MyLocal2 [List l, ] : String | provenance | MaD:2 | | B.java:248:10:248:10 | l : ArrayList [] : String | B.java:248:10:248:17 | get(...) | provenance | MaD:3 | | B.java:249:10:249:11 | l2 : ArrayList [] : String | B.java:249:10:249:18 | get(...) | provenance | MaD:3 | -| B.java:253:16:253:29 | source(...) : String | B.java:260:5:260:18 | String s : String | provenance | | -| B.java:254:11:254:18 | parameter this : MyLocal3 [String s] : String | B.java:254:11:254:18 | this <.method> : MyLocal3 [String s] : String | provenance | | -| B.java:254:11:254:18 | parameter this : MyLocal3 [String s] : String | B.java:255:18:255:18 | this : MyLocal3 [String s] : String | provenance | | -| B.java:254:11:254:18 | this <.method> : MyLocal3 [String s] : String | B.java:254:11:254:18 | parameter this : MyLocal3 [String s] : String | provenance | | -| B.java:254:11:254:18 | this <.method> : MyLocal3 [String s] : String | B.java:254:11:254:18 | this <.method> [post update] : MyLocal3 [f] : String | provenance | | -| B.java:254:11:254:18 | this <.method> [post update] : MyLocal3 [f] : String | B.java:254:11:254:18 | parameter this [Return] : MyLocal3 [f] : String | provenance | | -| B.java:255:7:255:19 | this <.field> [post update] : MyLocal3 [f] : String | B.java:254:11:254:18 | parameter this [Return] : MyLocal3 [f] : String | provenance | | -| B.java:255:18:255:18 | s : String | B.java:255:7:255:19 | this <.field> [post update] : MyLocal3 [f] : String | provenance | | -| B.java:255:18:255:18 | this : MyLocal3 [String s] : String | B.java:255:18:255:18 | s : String | provenance | | -| B.java:256:12:256:14 | parameter this : MyLocal3 [f] : String | B.java:257:14:257:17 | this : MyLocal3 [f] : String | provenance | | -| B.java:257:14:257:17 | this : MyLocal3 [f] : String | B.java:257:14:257:19 | this.f | provenance | | -| B.java:260:5:260:18 | String s : String | B.java:260:5:260:18 | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | provenance | | -| B.java:260:5:260:18 | new MyLocal3(...) : MyLocal3 [f] : String | B.java:256:12:256:14 | parameter this : MyLocal3 [f] : String | provenance | | -| B.java:260:5:260:18 | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | B.java:254:11:254:18 | parameter this : MyLocal3 [String s] : String | provenance | | -| B.java:260:5:260:18 | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | B.java:260:5:260:18 | new MyLocal3(...) : MyLocal3 [f] : String | provenance | | +| B.java:254:16:254:29 | source(...) : String | B.java:261:5:261:18 | String s : String | provenance | | +| B.java:255:11:255:18 | parameter this : MyLocal3 [String s] : String | B.java:255:11:255:18 | this <.method> : MyLocal3 [String s] : String | provenance | | +| B.java:255:11:255:18 | parameter this : MyLocal3 [String s] : String | B.java:256:18:256:18 | this : MyLocal3 [String s] : String | provenance | | +| B.java:255:11:255:18 | this <.method> : MyLocal3 [String s] : String | B.java:255:11:255:18 | parameter this : MyLocal3 [String s] : String | provenance | | +| B.java:255:11:255:18 | this <.method> : MyLocal3 [String s] : String | B.java:255:11:255:18 | this <.method> [post update] : MyLocal3 [f] : String | provenance | | +| B.java:255:11:255:18 | this <.method> [post update] : MyLocal3 [f] : String | B.java:255:11:255:18 | parameter this [Return] : MyLocal3 [f] : String | provenance | | +| B.java:256:7:256:19 | this <.field> [post update] : MyLocal3 [f] : String | B.java:255:11:255:18 | parameter this [Return] : MyLocal3 [f] : String | provenance | | +| B.java:256:18:256:18 | s : String | B.java:256:7:256:19 | this <.field> [post update] : MyLocal3 [f] : String | provenance | | +| B.java:256:18:256:18 | this : MyLocal3 [String s] : String | B.java:256:18:256:18 | s : String | provenance | | +| B.java:257:12:257:14 | parameter this : MyLocal3 [f] : String | B.java:258:14:258:17 | this : MyLocal3 [f] : String | provenance | | +| B.java:258:14:258:17 | this : MyLocal3 [f] : String | B.java:258:14:258:19 | this.f | provenance | | +| B.java:261:5:261:18 | String s : String | B.java:261:5:261:18 | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | provenance | | +| B.java:261:5:261:18 | new MyLocal3(...) : MyLocal3 [f] : String | B.java:257:12:257:14 | parameter this : MyLocal3 [f] : String | provenance | | +| B.java:261:5:261:18 | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | B.java:255:11:255:18 | parameter this : MyLocal3 [String s] : String | provenance | | +| B.java:261:5:261:18 | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | B.java:261:5:261:18 | new MyLocal3(...) : MyLocal3 [f] : String | provenance | | +| B.java:266:16:266:29 | source(...) : String | B.java:279:10:279:23 | String s : String | provenance | | +| B.java:266:16:266:29 | source(...) : String | B.java:280:10:280:24 | String s : String | provenance | | +| B.java:269:7:269:14 | parameter this : MyLocal4 [String s] : String | B.java:270:9:270:17 | this : MyLocal4 [String s] : String | provenance | | +| B.java:270:9:270:17 | this : MyLocal4 [String s] : String | B.java:270:9:270:17 | this [post update] : MyLocal4 [f] : String | provenance | | +| B.java:270:9:270:17 | this : MyLocal4 [String s] : String | B.java:272:7:272:14 | parameter this : MyLocal4 [String s] : String | provenance | | +| B.java:270:9:270:17 | this [post update] : MyLocal4 [f] : String | B.java:269:7:269:14 | parameter this [Return] : MyLocal4 [f] : String | provenance | | +| B.java:272:7:272:14 | parameter this : MyLocal4 [String s] : String | B.java:273:13:273:13 | this : MyLocal4 [String s] : String | provenance | | +| B.java:273:9:273:9 | this <.field> [post update] : MyLocal4 [f] : String | B.java:272:7:272:14 | parameter this [Return] : MyLocal4 [f] : String | provenance | | +| B.java:273:13:273:13 | s : String | B.java:273:9:273:9 | this <.field> [post update] : MyLocal4 [f] : String | provenance | | +| B.java:273:13:273:13 | this : MyLocal4 [String s] : String | B.java:273:13:273:13 | s : String | provenance | | +| B.java:275:14:275:16 | parameter this : MyLocal4 [f] : String | B.java:276:16:276:19 | this : MyLocal4 [f] : String | provenance | | +| B.java:276:16:276:19 | this : MyLocal4 [f] : String | B.java:276:16:276:21 | this.f : String | provenance | | +| B.java:279:10:279:23 | String s : String | B.java:279:10:279:23 | new MyLocal4(...) : MyLocal4 [String s] : String | provenance | | +| B.java:279:10:279:23 | String s : String | B.java:279:10:279:23 | new MyLocal4(...) [pre constructor] : MyLocal4 [String s] : String | provenance | | +| B.java:279:10:279:23 | String s : String | B.java:280:10:280:24 | String s : String | provenance | | +| B.java:279:10:279:23 | new MyLocal4(...) : MyLocal4 [String s] : String | B.java:279:10:279:23 | String s : String | provenance | | +| B.java:279:10:279:23 | new MyLocal4(...) : MyLocal4 [f] : String | B.java:275:14:275:16 | parameter this : MyLocal4 [f] : String | provenance | | +| B.java:279:10:279:23 | new MyLocal4(...) : MyLocal4 [f] : String | B.java:279:10:279:29 | get(...) | provenance | | +| B.java:279:10:279:23 | new MyLocal4(...) [pre constructor] : MyLocal4 [String s] : String | B.java:269:7:269:14 | parameter this : MyLocal4 [String s] : String | provenance | | +| B.java:279:10:279:23 | new MyLocal4(...) [pre constructor] : MyLocal4 [String s] : String | B.java:279:10:279:23 | new MyLocal4(...) : MyLocal4 [f] : String | provenance | | +| B.java:280:10:280:24 | String s : String | B.java:280:10:280:24 | new MyLocal4(...) [pre constructor] : MyLocal4 [String s] : String | provenance | | +| B.java:280:10:280:24 | new MyLocal4(...) : MyLocal4 [f] : String | B.java:275:14:275:16 | parameter this : MyLocal4 [f] : String | provenance | | +| B.java:280:10:280:24 | new MyLocal4(...) : MyLocal4 [f] : String | B.java:280:10:280:30 | get(...) | provenance | | +| B.java:280:10:280:24 | new MyLocal4(...) [pre constructor] : MyLocal4 [String s] : String | B.java:272:7:272:14 | parameter this : MyLocal4 [String s] : String | provenance | | +| B.java:280:10:280:24 | new MyLocal4(...) [pre constructor] : MyLocal4 [String s] : String | B.java:280:10:280:24 | new MyLocal4(...) : MyLocal4 [f] : String | provenance | | nodes | B.java:11:5:11:6 | l1 [post update] : ArrayList [] : String | semmle.label | l1 [post update] : ArrayList [] : String | | B.java:11:12:11:22 | source(...) : String | semmle.label | source(...) : String | @@ -526,22 +551,45 @@ nodes | B.java:248:10:248:17 | get(...) | semmle.label | get(...) | | B.java:249:10:249:11 | l2 : ArrayList [] : String | semmle.label | l2 : ArrayList [] : String | | B.java:249:10:249:18 | get(...) | semmle.label | get(...) | -| B.java:253:16:253:29 | source(...) : String | semmle.label | source(...) : String | -| B.java:254:11:254:18 | parameter this : MyLocal3 [String s] : String | semmle.label | parameter this : MyLocal3 [String s] : String | -| B.java:254:11:254:18 | parameter this : MyLocal3 [String s] : String | semmle.label | parameter this : MyLocal3 [String s] : String | -| B.java:254:11:254:18 | parameter this [Return] : MyLocal3 [f] : String | semmle.label | parameter this [Return] : MyLocal3 [f] : String | -| B.java:254:11:254:18 | parameter this [Return] : MyLocal3 [f] : String | semmle.label | parameter this [Return] : MyLocal3 [f] : String | -| B.java:254:11:254:18 | this <.method> : MyLocal3 [String s] : String | semmle.label | this <.method> : MyLocal3 [String s] : String | -| B.java:254:11:254:18 | this <.method> [post update] : MyLocal3 [f] : String | semmle.label | this <.method> [post update] : MyLocal3 [f] : String | -| B.java:255:7:255:19 | this <.field> [post update] : MyLocal3 [f] : String | semmle.label | this <.field> [post update] : MyLocal3 [f] : String | -| B.java:255:18:255:18 | s : String | semmle.label | s : String | -| B.java:255:18:255:18 | this : MyLocal3 [String s] : String | semmle.label | this : MyLocal3 [String s] : String | -| B.java:256:12:256:14 | parameter this : MyLocal3 [f] : String | semmle.label | parameter this : MyLocal3 [f] : String | -| B.java:257:14:257:17 | this : MyLocal3 [f] : String | semmle.label | this : MyLocal3 [f] : String | -| B.java:257:14:257:19 | this.f | semmle.label | this.f | -| B.java:260:5:260:18 | String s : String | semmle.label | String s : String | -| B.java:260:5:260:18 | new MyLocal3(...) : MyLocal3 [f] : String | semmle.label | new MyLocal3(...) : MyLocal3 [f] : String | -| B.java:260:5:260:18 | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | semmle.label | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | +| B.java:254:16:254:29 | source(...) : String | semmle.label | source(...) : String | +| B.java:255:11:255:18 | parameter this : MyLocal3 [String s] : String | semmle.label | parameter this : MyLocal3 [String s] : String | +| B.java:255:11:255:18 | parameter this : MyLocal3 [String s] : String | semmle.label | parameter this : MyLocal3 [String s] : String | +| B.java:255:11:255:18 | parameter this [Return] : MyLocal3 [f] : String | semmle.label | parameter this [Return] : MyLocal3 [f] : String | +| B.java:255:11:255:18 | parameter this [Return] : MyLocal3 [f] : String | semmle.label | parameter this [Return] : MyLocal3 [f] : String | +| B.java:255:11:255:18 | this <.method> : MyLocal3 [String s] : String | semmle.label | this <.method> : MyLocal3 [String s] : String | +| B.java:255:11:255:18 | this <.method> [post update] : MyLocal3 [f] : String | semmle.label | this <.method> [post update] : MyLocal3 [f] : String | +| B.java:256:7:256:19 | this <.field> [post update] : MyLocal3 [f] : String | semmle.label | this <.field> [post update] : MyLocal3 [f] : String | +| B.java:256:18:256:18 | s : String | semmle.label | s : String | +| B.java:256:18:256:18 | this : MyLocal3 [String s] : String | semmle.label | this : MyLocal3 [String s] : String | +| B.java:257:12:257:14 | parameter this : MyLocal3 [f] : String | semmle.label | parameter this : MyLocal3 [f] : String | +| B.java:258:14:258:17 | this : MyLocal3 [f] : String | semmle.label | this : MyLocal3 [f] : String | +| B.java:258:14:258:19 | this.f | semmle.label | this.f | +| B.java:261:5:261:18 | String s : String | semmle.label | String s : String | +| B.java:261:5:261:18 | new MyLocal3(...) : MyLocal3 [f] : String | semmle.label | new MyLocal3(...) : MyLocal3 [f] : String | +| B.java:261:5:261:18 | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | semmle.label | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | +| B.java:266:16:266:29 | source(...) : String | semmle.label | source(...) : String | +| B.java:269:7:269:14 | parameter this : MyLocal4 [String s] : String | semmle.label | parameter this : MyLocal4 [String s] : String | +| B.java:269:7:269:14 | parameter this [Return] : MyLocal4 [f] : String | semmle.label | parameter this [Return] : MyLocal4 [f] : String | +| B.java:270:9:270:17 | this : MyLocal4 [String s] : String | semmle.label | this : MyLocal4 [String s] : String | +| B.java:270:9:270:17 | this [post update] : MyLocal4 [f] : String | semmle.label | this [post update] : MyLocal4 [f] : String | +| B.java:272:7:272:14 | parameter this : MyLocal4 [String s] : String | semmle.label | parameter this : MyLocal4 [String s] : String | +| B.java:272:7:272:14 | parameter this [Return] : MyLocal4 [f] : String | semmle.label | parameter this [Return] : MyLocal4 [f] : String | +| B.java:273:9:273:9 | this <.field> [post update] : MyLocal4 [f] : String | semmle.label | this <.field> [post update] : MyLocal4 [f] : String | +| B.java:273:13:273:13 | s : String | semmle.label | s : String | +| B.java:273:13:273:13 | this : MyLocal4 [String s] : String | semmle.label | this : MyLocal4 [String s] : String | +| B.java:275:14:275:16 | parameter this : MyLocal4 [f] : String | semmle.label | parameter this : MyLocal4 [f] : String | +| B.java:276:16:276:19 | this : MyLocal4 [f] : String | semmle.label | this : MyLocal4 [f] : String | +| B.java:276:16:276:21 | this.f : String | semmle.label | this.f : String | +| B.java:279:10:279:23 | String s : String | semmle.label | String s : String | +| B.java:279:10:279:23 | String s : String | semmle.label | String s : String | +| B.java:279:10:279:23 | new MyLocal4(...) : MyLocal4 [String s] : String | semmle.label | new MyLocal4(...) : MyLocal4 [String s] : String | +| B.java:279:10:279:23 | new MyLocal4(...) : MyLocal4 [f] : String | semmle.label | new MyLocal4(...) : MyLocal4 [f] : String | +| B.java:279:10:279:23 | new MyLocal4(...) [pre constructor] : MyLocal4 [String s] : String | semmle.label | new MyLocal4(...) [pre constructor] : MyLocal4 [String s] : String | +| B.java:279:10:279:29 | get(...) | semmle.label | get(...) | +| B.java:280:10:280:24 | String s : String | semmle.label | String s : String | +| B.java:280:10:280:24 | new MyLocal4(...) : MyLocal4 [f] : String | semmle.label | new MyLocal4(...) : MyLocal4 [f] : String | +| B.java:280:10:280:24 | new MyLocal4(...) [pre constructor] : MyLocal4 [String s] : String | semmle.label | new MyLocal4(...) [pre constructor] : MyLocal4 [String s] : String | +| B.java:280:10:280:30 | get(...) | semmle.label | get(...) | subpaths | B.java:13:5:13:6 | l1 : ArrayList [] : String | B.java:13:16:13:16 | e : String | B.java:13:16:13:29 | parameter this [Return] : new Consumer(...) { ... } [List l2, ] : String | B.java:13:16:13:29 | ...->... [post update] : new Consumer(...) { ... } [List l2, ] : String | | B.java:30:14:30:24 | source(...) : String | B.java:22:26:22:26 | x : String | B.java:22:26:22:71 | parameter this [Return] : new Consumer(...) { ... } [B other, bf1] : String | B.java:30:5:30:5 | f [post update] : new Consumer(...) { ... } [B other, bf1] : String | @@ -561,6 +609,11 @@ subpaths | B.java:178:10:178:11 | m2 : MyLocal [List l, ] : String | B.java:169:14:169:16 | parameter this : MyLocal [List l, ] : String | B.java:170:16:170:23 | get(...) : String | B.java:178:10:178:17 | get(...) | | B.java:247:5:247:18 | new MyLocal2(...) : MyLocal2 [List l, ] : String | B.java:240:12:240:14 | parameter this : MyLocal2 [List l, ] : String | B.java:240:12:240:14 | parameter this [Return] : MyLocal2 [List l2, ] : String | B.java:247:5:247:18 | new MyLocal2(...) [post update] : MyLocal2 [List l2, ] : String | | B.java:247:5:247:18 | new MyLocal2(...) [pre constructor] : MyLocal2 [String s] : String | B.java:235:7:235:14 | parameter this : MyLocal2 [String s] : String | B.java:235:7:235:14 | parameter this [Return] : MyLocal2 [List l, ] : String | B.java:247:5:247:18 | new MyLocal2(...) : MyLocal2 [List l, ] : String | -| B.java:254:11:254:18 | this <.method> : MyLocal3 [String s] : String | B.java:254:11:254:18 | parameter this : MyLocal3 [String s] : String | B.java:254:11:254:18 | parameter this [Return] : MyLocal3 [f] : String | B.java:254:11:254:18 | this <.method> [post update] : MyLocal3 [f] : String | -| B.java:260:5:260:18 | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | B.java:254:11:254:18 | parameter this : MyLocal3 [String s] : String | B.java:254:11:254:18 | parameter this [Return] : MyLocal3 [f] : String | B.java:260:5:260:18 | new MyLocal3(...) : MyLocal3 [f] : String | +| B.java:255:11:255:18 | this <.method> : MyLocal3 [String s] : String | B.java:255:11:255:18 | parameter this : MyLocal3 [String s] : String | B.java:255:11:255:18 | parameter this [Return] : MyLocal3 [f] : String | B.java:255:11:255:18 | this <.method> [post update] : MyLocal3 [f] : String | +| B.java:261:5:261:18 | new MyLocal3(...) [pre constructor] : MyLocal3 [String s] : String | B.java:255:11:255:18 | parameter this : MyLocal3 [String s] : String | B.java:255:11:255:18 | parameter this [Return] : MyLocal3 [f] : String | B.java:261:5:261:18 | new MyLocal3(...) : MyLocal3 [f] : String | +| B.java:270:9:270:17 | this : MyLocal4 [String s] : String | B.java:272:7:272:14 | parameter this : MyLocal4 [String s] : String | B.java:272:7:272:14 | parameter this [Return] : MyLocal4 [f] : String | B.java:270:9:270:17 | this [post update] : MyLocal4 [f] : String | +| B.java:279:10:279:23 | new MyLocal4(...) : MyLocal4 [f] : String | B.java:275:14:275:16 | parameter this : MyLocal4 [f] : String | B.java:276:16:276:21 | this.f : String | B.java:279:10:279:29 | get(...) | +| B.java:279:10:279:23 | new MyLocal4(...) [pre constructor] : MyLocal4 [String s] : String | B.java:269:7:269:14 | parameter this : MyLocal4 [String s] : String | B.java:269:7:269:14 | parameter this [Return] : MyLocal4 [f] : String | B.java:279:10:279:23 | new MyLocal4(...) : MyLocal4 [f] : String | +| B.java:280:10:280:24 | new MyLocal4(...) : MyLocal4 [f] : String | B.java:275:14:275:16 | parameter this : MyLocal4 [f] : String | B.java:276:16:276:21 | this.f : String | B.java:280:10:280:30 | get(...) | +| B.java:280:10:280:24 | new MyLocal4(...) [pre constructor] : MyLocal4 [String s] : String | B.java:272:7:272:14 | parameter this : MyLocal4 [String s] : String | B.java:272:7:272:14 | parameter this [Return] : MyLocal4 [f] : String | B.java:280:10:280:24 | new MyLocal4(...) : MyLocal4 [f] : String | testFailures