Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 95cb014

Browse files
tamasvajkigfoo
authored andcommitted
Fix data flow through ExtensionMethodAccess
1 parent 38ab7ac commit 95cb014

5 files changed

Lines changed: 47 additions & 6 deletions

File tree

java/ql/lib/semmle/code/java/ControlFlowGraph.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ private module ControlFlowGraphImpl {
558558
or
559559
exists(ExtensionMethodAccess e | e = this |
560560
// the actual qualifier of the expression method access
561-
index = -1 and result.(Expr).isNthChildOf(this, index) and not result instanceof TypeAccess
561+
index = -1 and result = e.getImplicitQualifier() and not result instanceof TypeAccess
562562
or
563563
// the extension receiver
564564
index = 0 and result = e.getQualifier()

java/ql/lib/semmle/code/java/Expr.qll

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1990,6 +1990,12 @@ class MethodAccess extends Expr, Call, @methodaccess {
19901990
class ExtensionMethodAccess extends MethodAccess {
19911991
ExtensionMethodAccess() { this.getMethod() instanceof ExtensionMethod }
19921992

1993+
/**
1994+
* Gets the implicit qualifier of this extension method access. This expression
1995+
* is the qualifier of this method access in bytecode.
1996+
*/
1997+
Expr getImplicitQualifier() { result.isNthChildOf(this, -1) }
1998+
19931999
// The syntactic qualifier of an extension method is its receiver (arg 0),
19942000
// whereas the actual arguments begin at index 1.
19952001
override Expr getQualifier() { result.isNthChildOf(this, 0) }
@@ -2240,8 +2246,11 @@ private module Qualifier {
22402246

22412247
/** Gets the qualifier of this member access, if any. */
22422248
Expr getQualifier() {
2243-
result = this.(FieldAccess).getQualifier() or
2244-
result = this.(MethodAccess).getQualifier()
2249+
result = this.(FieldAccess).getQualifier()
2250+
or
2251+
result = this.(MethodAccess).getQualifier() and not this instanceof ExtensionMethodAccess
2252+
or
2253+
result = this.(ExtensionMethodAccess).getImplicitQualifier()
22452254
}
22462255
}
22472256

java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,16 @@ newtype TNode =
4949

5050
private predicate explicitInstanceArgument(Call call, Expr instarg) {
5151
call instanceof MethodAccess and
52-
instarg = call.getQualifier() and
52+
instarg = getQualifier(call) and
5353
not call.getCallee().isStatic()
5454
}
5555

56+
private Expr getQualifier(MethodAccess ma) {
57+
not ma instanceof ExtensionMethodAccess and result = ma.getQualifier()
58+
or
59+
result = ma.(ExtensionMethodAccess).getImplicitQualifier()
60+
}
61+
5662
private predicate implicitInstanceArgument(Call call, InstanceAccessExt ia) {
5763
ia.isImplicitMethodQualifier(call) or
5864
ia.isImplicitThisConstructorArgument(call)
@@ -360,6 +366,9 @@ module Private {
360366
ArgumentNode() {
361367
exists(Argument arg | this.asExpr() = arg | not arg.isVararg())
362368
or
369+
// In JVM bytecode the qualifier of an extension method call is the 0th argument
370+
exists(ExtensionMethodAccess ema | this.asExpr() = ema.getQualifier())
371+
or
363372
this instanceof ImplicitVarargsArray
364373
or
365374
this = getInstanceArgument(_)
@@ -373,7 +382,20 @@ module Private {
373382
*/
374383
predicate argumentOf(DataFlowCall call, int pos) {
375384
exists(Argument arg | this.asExpr() = arg |
376-
call.asCall() = arg.getCall() and pos = arg.getPosition()
385+
call.asCall() = arg.getCall() and
386+
(
387+
pos = arg.getPosition() and not call.asCall() instanceof ExtensionMethodAccess
388+
or
389+
// Shift the positions of an extension method call by 1 to make space for the qualifier at index 0.
390+
pos = arg.getPosition() + 1 and call.asCall() instanceof ExtensionMethodAccess
391+
)
392+
)
393+
or
394+
// In JVM bytecode the qualifier of an extension method call is the 0th argument
395+
exists(ExtensionMethodAccess ema |
396+
call.asCall() = ema and
397+
pos = 0 and
398+
this.asExpr() = ema.getQualifier()
377399
)
378400
or
379401
call.asCall() = this.(ImplicitVarargsArray).getCall() and

java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,14 @@ private module Dispatch {
273273
not e instanceof FunctionalExpr and result = e.getType()
274274
}
275275

276+
private Expr getQualifier(MethodAccess ma) {
277+
not ma instanceof ExtensionMethodAccess and result = ma.getQualifier()
278+
or
279+
result = ma.(ExtensionMethodAccess).getImplicitQualifier()
280+
}
281+
276282
private predicate hasQualifierType(VirtualMethodAccess ma, RefType t, boolean exact) {
277-
exists(Expr src | src = variableTrack(ma.getQualifier()) |
283+
exists(Expr src | src = variableTrack(getQualifier(ma)) |
278284
// If we have a qualifier, then we track it through variable assignments
279285
// and take the type of the assigned value.
280286
exists(RefType srctype | srctype = getPreciseType(src) |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
| test.kt:20:29:20:31 | new C(...) | test.kt:23:22:23:28 | self1(...) |
2+
| test.kt:20:29:20:31 | new C(...) | test.kt:26:22:26:28 | self2(...) |
23
| test.kt:20:29:20:31 | new C(...) | test.kt:29:18:29:29 | fn1(...) |
4+
| test.kt:20:29:20:31 | new C(...) | test.kt:32:18:32:29 | fn2(...) |
5+
| test.kt:20:29:20:31 | new C(...) | test.kt:35:18:35:31 | call1(...) |
6+
| test.kt:20:29:20:31 | new C(...) | test.kt:38:22:38:28 | call2(...) |

0 commit comments

Comments
 (0)