diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll index 312d7767ac2..8a1b977f55a 100644 --- a/java/ql/lib/semmle/code/java/Expr.qll +++ b/java/ql/lib/semmle/code/java/Expr.qll @@ -1670,13 +1670,25 @@ abstract class InstanceAccess extends Expr { /** Holds if this instance access is to an enclosing instance of type `t`. */ predicate isEnclosingInstanceAccess(RefType t) { t = this.getQualifier().getType().(RefType).getSourceDeclaration() and - t != this.getEnclosingCallable().getDeclaringType() + t != this.getEnclosingCallable().getDeclaringType() and + not this.isSuperInterfaceAccess() or - not exists(this.getQualifier()) and + (not exists(this.getQualifier()) or this.isSuperInterfaceAccess()) and exists(LambdaExpr lam | lam.asMethod() = this.getEnclosingCallable() | t = lam.getAnonymousClass().getEnclosingType() ) } + + // A default method on an interface, `I`, may be invoked using `I.super.m()`. + // This always refers to the implemented interfaces of `this`. This form of + // qualified `super` cannot be combined with accessing an enclosing instance. + // JLS 15.11.2. "Accessing Superclass Members using super" + // JLS 15.12. "Method Invocation Expressions" + // JLS 15.12.1. "Compile-Time Step 1: Determine Type to Search" + private predicate isSuperInterfaceAccess() { + this instanceof SuperAccess and + this.getQualifier().getType().(RefType).getSourceDeclaration() instanceof Interface + } } /**