mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Java: Fix support for variable capture inside object initializers.
This commit is contained in:
@@ -147,7 +147,14 @@ private module CaptureInput implements VariableCapture::InputSig<Location> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Callable extends J::Callable {
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -248,4 +248,15 @@ public class B {
|
|||||||
sink(l.get(0)); // $ hasValueFlow=src
|
sink(l.get(0)); // $ hasValueFlow=src
|
||||||
sink(l2.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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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<String> l, <element>] : String | provenance | MaD:2 |
|
| B.java:247:5:247:18 | new MyLocal2(...) [pre constructor] : MyLocal2 [String s] : String | B.java:247:5:247:18 | new MyLocal2(...) : MyLocal2 [List<String> l, <element>] : String | provenance | MaD:2 |
|
||||||
| B.java:248:10:248:10 | l : ArrayList [<element>] : String | B.java:248:10:248:17 | get(...) | provenance | MaD:3 |
|
| B.java:248:10:248:10 | l : ArrayList [<element>] : String | B.java:248:10:248:17 | get(...) | provenance | MaD:3 |
|
||||||
| B.java:249:10:249:11 | l2 : ArrayList [<element>] : String | B.java:249:10:249:18 | get(...) | provenance | MaD:3 |
|
| B.java:249:10:249:11 | l2 : ArrayList [<element>] : 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
|
nodes
|
||||||
| B.java:11:5:11:6 | l1 [post update] : ArrayList [<element>] : String | semmle.label | l1 [post update] : ArrayList [<element>] : String |
|
| B.java:11:5:11:6 | l1 [post update] : ArrayList [<element>] : String | semmle.label | l1 [post update] : ArrayList [<element>] : String |
|
||||||
| B.java:11:12:11:22 | source(...) : String | semmle.label | source(...) : 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:248:10:248:17 | get(...) | semmle.label | get(...) |
|
||||||
| B.java:249:10:249:11 | l2 : ArrayList [<element>] : String | semmle.label | l2 : ArrayList [<element>] : String |
|
| B.java:249:10:249:11 | l2 : ArrayList [<element>] : String | semmle.label | l2 : ArrayList [<element>] : String |
|
||||||
| B.java:249:10:249:18 | get(...) | semmle.label | get(...) |
|
| 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
|
subpaths
|
||||||
| B.java:13:5:13:6 | l1 : ArrayList [<element>] : String | B.java:13:16:13:16 | e : String | B.java:13:16:13:29 | parameter this [Return] : new Consumer<String>(...) { ... } [List<String> l2, <element>] : String | B.java:13:16:13:29 | ...->... [post update] : new Consumer<String>(...) { ... } [List<String> l2, <element>] : String |
|
| B.java:13:5:13:6 | l1 : ArrayList [<element>] : String | B.java:13:16:13:16 | e : String | B.java:13:16:13:29 | parameter this [Return] : new Consumer<String>(...) { ... } [List<String> l2, <element>] : String | B.java:13:16:13:29 | ...->... [post update] : new Consumer<String>(...) { ... } [List<String> l2, <element>] : 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<String>(...) { ... } [B other, bf1] : String | B.java:30:5:30:5 | f [post update] : new Consumer<String>(...) { ... } [B other, bf1] : 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<String>(...) { ... } [B other, bf1] : String | B.java:30:5:30:5 | f [post update] : new Consumer<String>(...) { ... } [B other, bf1] : String |
|
||||||
@@ -530,4 +561,6 @@ subpaths
|
|||||||
| B.java:178:10:178:11 | m2 : MyLocal [List<String> l, <element>] : String | B.java:169:14:169:16 | parameter this : MyLocal [List<String> l, <element>] : String | B.java:170:16:170:23 | get(...) : String | B.java:178:10:178:17 | get(...) |
|
| B.java:178:10:178:11 | m2 : MyLocal [List<String> l, <element>] : String | B.java:169:14:169:16 | parameter this : MyLocal [List<String> l, <element>] : 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<String> l, <element>] : String | B.java:240:12:240:14 | parameter this : MyLocal2 [List<String> l, <element>] : String | B.java:240:12:240:14 | parameter this [Return] : MyLocal2 [List<String> l2, <element>] : String | B.java:247:5:247:18 | new MyLocal2(...) [post update] : MyLocal2 [List<String> l2, <element>] : String |
|
| B.java:247:5:247:18 | new MyLocal2(...) : MyLocal2 [List<String> l, <element>] : String | B.java:240:12:240:14 | parameter this : MyLocal2 [List<String> l, <element>] : String | B.java:240:12:240:14 | parameter this [Return] : MyLocal2 [List<String> l2, <element>] : String | B.java:247:5:247:18 | new MyLocal2(...) [post update] : MyLocal2 [List<String> l2, <element>] : 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<String> l, <element>] : String | B.java:247:5:247:18 | new MyLocal2(...) : MyLocal2 [List<String> l, <element>] : 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<String> l, <element>] : String | B.java:247:5:247:18 | new MyLocal2(...) : MyLocal2 [List<String> l, <element>] : 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
|
testFailures
|
||||||
|
|||||||
@@ -585,11 +585,13 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
|
|||||||
2 <= strictcount(CapturedVariable v | captureAccess(v, c))
|
2 <= strictcount(CapturedVariable v | captureAccess(v, c))
|
||||||
or
|
or
|
||||||
// Constructors that capture a variable may assign it to a field, which also
|
// Constructors that capture a variable may assign it to a field, which also
|
||||||
// entails a this-to-this summary.
|
// entails a this-to-this summary. If there are multiple constructors, then
|
||||||
captureAccess(_, c) and c.isConstructor()
|
// 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) {
|
private predicate hasConstructorCapture(ClosureExpr ce, CapturedVariable v) {
|
||||||
exists(Callable c | ce.hasBody(c) and c.isConstructor() and captureAccess(v, c))
|
exists(Callable c | ce.hasBody(c) and c.isConstructor() and captureAccess(v, c))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user