JDK-6495506 : Cast inserted by generics can cause IllegalAccessError
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2006-11-20
  • Updated: 2017-05-16
  • Resolved: 2011-03-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 Other
7 b05Fixed OpenJDK6Resolved
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0-rc"
Java(TM) SE Runtime Environment (build 1.6.0-rc-b91)
Java HotSpot(TM) Client VM (build 1.6.0-rc-b91, mixed mode, sharing)

A DESCRIPTION OF THE PROBLEM :
When a class A has a generic field with a private class P as parameter, and another class Main without access to P uses this field, generics may insert a casts to P in Main, to which it has no access. This results in an IllegalAccessError.
This may actually be a bug in the specification, I'm not sure.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the provided code.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The compiler shouldn't accept such code.
ACTUAL -
java.lang.IllegalAccessError: tried to access class a.A$P from class Main

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
Main.java:
public class Main {
	public static void main(String[] args) {
		a.A myA = new a.A();
		myA.p = myA.vec.get(0);
	}
}

a/A.java:
package a;
import java.util.Vector;
public class A {
	private class P {}
	public P p;
	public Vector<P> vec;
	public A() {
		vec = new Vector<P>();
		vec.add(new P());
	}
}
---------- END SOURCE ----------

Comments
SUGGESTED FIX Webrev of changes: http://sa.sfbay/projects/langtools/bugid_summary.pl?bugid=6495506 See also attachment 6495506.tar.gz.
21-11-2006

EVALUATION A bug, the compiler should not insert casts to inaccessible types.
21-11-2006

SUGGESTED FIX Index: j2se/src/share/classes/com/sun/tools/javac/comp/Resolve.java --- /tmp/geta11070 2006-11-21 15:44:46.000000000 -0800 +++ /tmp/getb11070 2006-11-21 15:44:46.000000000 -0800 @@ -1528,6 +1528,11 @@ * ResolveError classes, indicating error situations when accessing symbols ****************************************************************************/ + public void logAccessError(Env<AttrContext> env, JCTree tree, Type type) { + AccessError error = new AccessError(env, type.getEnclosingType(), type.tsym); + error.report(log, tree.pos(), type.getEnclosingType(), null, null, null); + } + /** Root class for resolve errors. * Instances of this class indicate "Symbol not found". * Instances of subclass indicate other errors. Index: j2se/src/share/classes/com/sun/tools/javac/comp/TransTypes.java --- /tmp/geta11079 2006-11-21 15:45:16.000000000 -0800 +++ /tmp/getb11079 2006-11-21 15:45:16.000000000 -0800 @@ -52,6 +52,8 @@ private Enter enter; private boolean allowEnums; private Types types; + private final Resolve resolve; + /** * Flag to indicate whether or not to generate bridge methods. * For pre-Tiger source there is no need for bridge methods, so it @@ -71,6 +73,7 @@ addBridges = source.addBridges(); types = Types.instance(context); make = TreeMaker.instance(context); + resolve = Resolve.instance(context); } /** A hashtable mapping bridge methods to the methods they override after @@ -87,6 +90,8 @@ int oldpos = make.pos; make.at(tree.pos); if (!types.isSameType(tree.type, target)) { + if (!resolve.isAccessible(env, target.tsym)) + resolve.logAccessError(env, tree, target); tree = make.TypeCast(make.Type(target), tree).setType(target); } make.pos = oldpos; @@ -721,6 +726,8 @@ * main method *************************************************************************/ + private Env<AttrContext> env; + void translateClass(ClassSymbol c) { Type st = types.supertype(c.type); @@ -728,8 +735,12 @@ if (st.tag == CLASS) translateClass((ClassSymbol)st.tsym); - Env<AttrContext> env = enter.typeEnvs.remove(c); - if (env != null) { + Env<AttrContext> myEnv = enter.typeEnvs.remove(c); + if (myEnv == null) + return; + Env<AttrContext> oldEnv = env; + try { + env = myEnv; // class has not been translated yet TreeMaker savedMake = make; @@ -752,6 +763,8 @@ make = savedMake; pt = savedPt; } + } finally { + env = oldEnv; } }
21-11-2006