Add access checks to Method and Field reflection.
Art side of this change. Has a corresponding libcore change.
Bug: 13620925
Change-Id: Ie67f802a2a400e8212b489b9a261b7028422d8ba
diff --git a/test/064-field-access/src/Main.java b/test/064-field-access/src/Main.java
index 3b9a475..c9b93ba 100644
--- a/test/064-field-access/src/Main.java
+++ b/test/064-field-access/src/Main.java
@@ -16,6 +16,7 @@
import other.PublicClass;
import java.lang.reflect.Field;
+import java.lang.reflect.Method;
/*
* Test field access through reflection.
@@ -192,6 +193,11 @@
/* package */ static float samePackagePackageFloatStaticField = 63.0f;
/* package */ static double samePackagePackageDoubleStaticField = 64.0;
/* package */ static Object samePackagePackageObjectStaticField = "65";
+
+ public void samePublicMethod() { }
+ protected void sameProtectedMethod() { }
+ private void samePrivateMethod() { }
+ /* package */ void samePackageMethod() { }
}
/*
@@ -510,23 +516,32 @@
for (int round = 0; round < 3; round++) {
Object validInst;
Field[] fields;
+ Method[] methods;
boolean same_package = false;
+ boolean protected_class = false;
switch (round) {
case 0:
validInst = new SamePackage();
fields = SamePackage.class.getDeclaredFields();
check(fields.length == 72);
+ methods = SamePackage.class.getDeclaredMethods();
+ check(methods.length == 4);
same_package = true;
break;
case 1:
validInst = new PublicClass();
fields = PublicClass.class.getDeclaredFields();
check(fields.length == 72);
+ methods = PublicClass.class.getDeclaredMethods();
+ check(methods.length == 4);
break;
default:
validInst = new PublicClass();
fields = PublicClass.class.getSuperclass().getDeclaredFields();
check(fields.length == 72);
+ methods = PublicClass.class.getSuperclass().getDeclaredMethods();
+ check(methods.length == 4);
+ protected_class = true;
break;
}
for (Field f : fields) {
@@ -540,16 +555,15 @@
// Check access or lack of to field.
Class<?> subClassAccessExceptionClass = null;
if (f.getName().contains("Private") ||
- (!same_package && f.getName().contains("Package"))) {
- // ART deliberately doesn't throw IllegalAccessException.
- // subClassAccessExceptionClass = IllegalAccessException.class;
+ (!same_package && f.getName().contains("Package")) ||
+ (!same_package && f.getName().contains("Protected"))) {
+ subClassAccessExceptionClass = IllegalAccessException.class;
}
Class<?> mainClassAccessExceptionClass = null;
if (f.getName().contains("Private") ||
(!same_package && f.getName().contains("Package")) ||
(!same_package && f.getName().contains("Protected"))) {
- // ART deliberately doesn't throw IllegalAccessException.
- // mainClassAccessExceptionClass = IllegalAccessException.class;
+ mainClassAccessExceptionClass = IllegalAccessException.class;
}
this.getValue(f, validInst, typeChar, subClassAccessExceptionClass);
@@ -588,6 +602,16 @@
}
}
}
+
+ for (Method m : methods) {
+ Class<?> subClassAccessExceptionClass = null;
+ if (protected_class || m.getName().contains("Private") ||
+ (!same_package && m.getName().contains("Package")) ||
+ (!same_package && m.getName().contains("Protected"))) {
+ subClassAccessExceptionClass = IllegalAccessException.class;
+ }
+ this.invoke(m, validInst, subClassAccessExceptionClass);
+ }
}
System.out.println("good");
}
@@ -598,7 +622,6 @@
*/
public Object getValue(Field field, Object obj, char type,
Class expectedException) {
-
Object result = null;
try {
switch (type) {
@@ -657,4 +680,29 @@
return result;
}
+
+ public Object invoke(Method method, Object obj, Class expectedException) {
+ Object result = null;
+ try {
+ result = method.invoke(obj);
+ /* success; expected? */
+ if (expectedException != null) {
+ System.err.println("ERROR: call succeeded for method " + method + "', was expecting " +
+ expectedException);
+ Thread.dumpStack();
+ }
+ } catch (Exception ex) {
+ if (expectedException == null) {
+ System.err.println("ERROR: call failed unexpectedly: " + ex.getClass());
+ ex.printStackTrace();
+ } else {
+ if (!expectedException.equals(ex.getClass())) {
+ System.err.println("ERROR: incorrect exception: wanted " + expectedException.getName() +
+ ", got " + ex.getClass());
+ ex.printStackTrace();
+ }
+ }
+ }
+ return result;
+ }
}
diff --git a/test/064-field-access/src/other/ProtectedClass.java b/test/064-field-access/src/other/ProtectedClass.java
index 779aa1d..756c97f 100644
--- a/test/064-field-access/src/other/ProtectedClass.java
+++ b/test/064-field-access/src/other/ProtectedClass.java
@@ -97,4 +97,10 @@
/* package */ static float otherProtectedClassPackageFloatStaticField = 63.0f;
/* package */ static double otherProtectedClassPackageDoubleStaticField = 64.0;
/* package */ static Object otherProtectedClassPackageObjectStaticField = "65";
+
+ public void otherPublicMethod() { }
+ protected void otherProtectedMethod() { }
+ private void otherPrivateMethod() { }
+ /* package */ void otherPackageMethod() { }
+
}
diff --git a/test/064-field-access/src/other/PublicClass.java b/test/064-field-access/src/other/PublicClass.java
index 1653973..dbcb4fd 100644
--- a/test/064-field-access/src/other/PublicClass.java
+++ b/test/064-field-access/src/other/PublicClass.java
@@ -97,4 +97,9 @@
/* package */ static float otherPublicClassPackageFloatStaticField = -63.0f;
/* package */ static double otherPublicClassPackageDoubleStaticField = -64.0;
/* package */ static Object otherPublicClassPackageObjectStaticField = "-65";
+
+ public void otherPublicMethod() { }
+ protected void otherProtectedMethod() { }
+ private void otherPrivateMethod() { }
+ /* package */ void otherPackageMethod() { }
}