8067886: Inaccessible nested classes can be incorrectly imported

Check type accessibility at the point of import when importing the type using type-import-on-demand.

Reviewed-by: mcimadamore, jfranck
This commit is contained in:
Jan Lahoda 2015-02-24 16:11:59 +01:00
parent 91722e7903
commit 681758e0fa
6 changed files with 75 additions and 30 deletions

View file

@ -798,6 +798,10 @@ public abstract class Scope {
prependSubScope(new FilterImportScope(types, origin, null, filter, staticImport)); prependSubScope(new FilterImportScope(types, origin, null, filter, staticImport));
} }
public boolean isFilled() {
return subScopes.nonEmpty();
}
} }
public interface ImportFilter { public interface ImportFilter {

View file

@ -3528,7 +3528,7 @@ public class Check {
for (Symbol sym : tsym.members().getSymbolsByName(name)) { for (Symbol sym : tsym.members().getSymbolsByName(name)) {
if (sym.isStatic() && if (sym.isStatic() &&
staticImportAccessible(sym, packge) && importAccessible(sym, packge) &&
sym.isMemberOf(origin, types)) { sym.isMemberOf(origin, types)) {
return true; return true;
} }
@ -3538,17 +3538,23 @@ public class Check {
} }
// is the sym accessible everywhere in packge? // is the sym accessible everywhere in packge?
public boolean staticImportAccessible(Symbol sym, PackageSymbol packge) { public boolean importAccessible(Symbol sym, PackageSymbol packge) {
int flags = (int)(sym.flags() & AccessFlags); try {
switch (flags) { int flags = (int)(sym.flags() & AccessFlags);
default: switch (flags) {
case PUBLIC: default:
return true; case PUBLIC:
case PRIVATE: return true;
case PRIVATE:
return false;
case 0:
case PROTECTED:
return sym.packge() == packge;
}
} catch (ClassFinder.BadClassFile err) {
throw err;
} catch (CompletionFailure ex) {
return false; return false;
case 0:
case PROTECTED:
return sym.packge() == packge;
} }
} }

View file

@ -1667,7 +1667,7 @@ public class LambdaToMethod extends TreeTranslator {
* This class is used to store important information regarding translation of * This class is used to store important information regarding translation of
* lambda expression/method references (see subclasses). * lambda expression/method references (see subclasses).
*/ */
private abstract class TranslationContext<T extends JCFunctionalExpression> { abstract class TranslationContext<T extends JCFunctionalExpression> {
/** the underlying (untranslated) tree */ /** the underlying (untranslated) tree */
final T tree; final T tree;
@ -1746,7 +1746,7 @@ public class LambdaToMethod extends TreeTranslator {
* and the used by the main translation routines in order to adjust references * and the used by the main translation routines in order to adjust references
* to captured locals/members, etc. * to captured locals/members, etc.
*/ */
private class LambdaTranslationContext extends TranslationContext<JCLambda> { class LambdaTranslationContext extends TranslationContext<JCLambda> {
/** variable in the enclosing context to which this lambda is assigned */ /** variable in the enclosing context to which this lambda is assigned */
final Symbol self; final Symbol self;
@ -2040,7 +2040,7 @@ public class LambdaToMethod extends TreeTranslator {
* and the used by the main translation routines in order to adjust method * and the used by the main translation routines in order to adjust method
* references (i.e. in case a bridge is needed) * references (i.e. in case a bridge is needed)
*/ */
private final class ReferenceTranslationContext extends TranslationContext<JCMemberReference> { final class ReferenceTranslationContext extends TranslationContext<JCMemberReference> {
final boolean isSuper; final boolean isSuper;
final Symbol sigPolySym; final Symbol sigPolySym;

View file

@ -160,7 +160,7 @@ public class TypeEnter implements Completer {
// if there remain any unimported toplevels (these must have // if there remain any unimported toplevels (these must have
// no classes at all), process their import statements as well. // no classes at all), process their import statements as well.
for (JCCompilationUnit tree : trees) { for (JCCompilationUnit tree : trees) {
if (tree.starImportScope.isEmpty()) { if (!tree.starImportScope.isFilled()) {
Env<AttrContext> topEnv = enter.topLevelEnv(tree); Env<AttrContext> topEnv = enter.topLevelEnv(tree);
finishImports(tree, () -> { completeClass.resolveImports(tree, topEnv); }); finishImports(tree, () -> { completeClass.resolveImports(tree, topEnv); });
} }
@ -280,12 +280,7 @@ public class TypeEnter implements Completer {
Env<AttrContext> env; Env<AttrContext> env;
ImportFilter staticImportFilter; ImportFilter staticImportFilter;
ImportFilter typeImportFilter = new ImportFilter() { ImportFilter typeImportFilter;
@Override
public boolean accepts(Scope origin, Symbol t) {
return t.kind == TYP;
}
};
@Override @Override
protected void doRunPhase(Env<AttrContext> env) { protected void doRunPhase(Env<AttrContext> env) {
@ -304,26 +299,26 @@ public class TypeEnter implements Completer {
} }
private void resolveImports(JCCompilationUnit tree, Env<AttrContext> env) { private void resolveImports(JCCompilationUnit tree, Env<AttrContext> env) {
if (!tree.starImportScope.isEmpty()) { if (tree.starImportScope.isFilled()) {
// we must have already processed this toplevel // we must have already processed this toplevel
return; return;
} }
ImportFilter prevStaticImportFilter = staticImportFilter; ImportFilter prevStaticImportFilter = staticImportFilter;
ImportFilter prevTypeImportFilter = typeImportFilter;
DiagnosticPosition prevLintPos = deferredLintHandler.immediate(); DiagnosticPosition prevLintPos = deferredLintHandler.immediate();
Lint prevLint = chk.setLint(lint); Lint prevLint = chk.setLint(lint);
Env<AttrContext> prevEnv = this.env; Env<AttrContext> prevEnv = this.env;
try { try {
this.env = env; this.env = env;
final PackageSymbol packge = env.toplevel.packge; final PackageSymbol packge = env.toplevel.packge;
this.staticImportFilter = new ImportFilter() { this.staticImportFilter =
@Override (origin, sym) -> sym.isStatic() &&
public boolean accepts(Scope origin, Symbol sym) { chk.importAccessible(sym, packge) &&
return sym.isStatic() && sym.isMemberOf((TypeSymbol) origin.owner, types);
chk.staticImportAccessible(sym, packge) && this.typeImportFilter =
sym.isMemberOf((TypeSymbol) origin.owner, types); (origin, sym) -> sym.kind == TYP &&
} chk.importAccessible(sym, packge);
};
// Import-on-demand java.lang. // Import-on-demand java.lang.
importAll(tree.pos, syms.enterPackage(names.java_lang), env); importAll(tree.pos, syms.enterPackage(names.java_lang), env);
@ -340,6 +335,7 @@ public class TypeEnter implements Completer {
chk.setLint(prevLint); chk.setLint(prevLint);
deferredLintHandler.setPos(prevLintPos); deferredLintHandler.setPos(prevLintPos);
this.staticImportFilter = prevStaticImportFilter; this.staticImportFilter = prevStaticImportFilter;
this.typeImportFilter = prevTypeImportFilter;
} }
} }

View file

@ -0,0 +1,37 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8067886
* @summary Verify that type import on demand won't put inaccessible types into the Scope
* @compile/fail/ref=ImportInaccessible.out -XDrawDiagnostics ImportInaccessible.java
*/
package p;
import p.ImportInaccessible.Nested.*;
class ImportInaccessible {
static class Nested<X extends Inner> {
private static class Inner{}
}
}

View file

@ -0,0 +1,2 @@
ImportInaccessible.java:34:35: compiler.err.cant.resolve.location: kindname.class, Inner, , , (compiler.misc.location: kindname.class, p.ImportInaccessible, null)
1 error