United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6495506 Cast inserted by generics can cause IllegalAccessError
JDK-6495506 : Cast inserted by generics can cause IllegalAccessError

Details
Type:
Bug
Submit Date:
2006-11-20
Status:
Closed
Updated Date:
2012-03-05
Project Name:
JDK
Resolved Date:
2011-03-08
Component:
tools
OS:
linux
Sub-Component:
javac
CPU:
x86
Priority:
P4
Resolution:
Fixed
Affected Versions:
6
Fixed Versions:

Related Reports
Backport:
Relates:

Sub Tasks

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.
                                     
2006-11-21
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;
         }
     }
                                     
2006-11-21
EVALUATION

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



Hardware and Software, Engineered to Work Together