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/046-reflect/expected.txt b/test/046-reflect/expected.txt
index fcfaf2f..55b0dbe 100644
--- a/test/046-reflect/expected.txt
+++ b/test/046-reflect/expected.txt
@@ -81,7 +81,8 @@
Field type is int
Access flags are 0x11
cantTouchThis is 77
- cantTouchThis is now 99
+ as expected: set-final throws exception
+ cantTouchThis is still 77
public final int Target.cantTouchThis accessible=false
public final int Target.cantTouchThis accessible=true
cantTouchThis is now 87
diff --git a/test/046-reflect/src/Main.java b/test/046-reflect/src/Main.java
index dfb0d8f..d60fcb4 100644
--- a/test/046-reflect/src/Main.java
+++ b/test/046-reflect/src/Main.java
@@ -335,11 +335,12 @@
System.out.println(" cantTouchThis is " + intVal);
try {
field.setInt(instance, 99);
+ System.out.println("ERROR: set-final did not throw exception");
} catch (IllegalAccessException iae) {
- System.out.println("ERROR: set-final failed");
+ System.out.println(" as expected: set-final throws exception");
}
intVal = field.getInt(instance);
- System.out.println(" cantTouchThis is now " + intVal);
+ System.out.println(" cantTouchThis is still " + intVal);
System.out.println(" " + field + " accessible=" + field.isAccessible());
field.setAccessible(true);
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() { }
}
diff --git a/test/100-reflect2/expected.txt b/test/100-reflect2/expected.txt
index 3d87ebc..bed0689 100644
--- a/test/100-reflect2/expected.txt
+++ b/test/100-reflect2/expected.txt
@@ -22,10 +22,7 @@
30
62
14
-java.lang.IllegalArgumentException: Invalid primitive conversion from int to short
- at java.lang.reflect.Field.set(Native Method)
- at Main.testFieldReflection(Main.java:121)
- at Main.main(Main.java:269)
+got expected IllegalArgumentException
true (class java.lang.Boolean)
6 (class java.lang.Byte)
z (class java.lang.Character)
@@ -66,12 +63,6 @@
true 0 1 2.0 hello world 3.0 4 5 6
null (null)
[]
-java.lang.reflect.InvocationTargetException
- at java.lang.reflect.Method.invoke(Native Method)
- at Main.testMethodReflection(Main.java:210)
- at Main.main(Main.java:270)
-Caused by: java.lang.ArithmeticException: surprise!
- at Main.thrower(Main.java:218)
- ... 3 more
+got expected InvocationTargetException
(class java.lang.String)
yz (class java.lang.String)
diff --git a/test/100-reflect2/src/Main.java b/test/100-reflect2/src/Main.java
index 0404591..0cc1488 100644
--- a/test/100-reflect2/src/Main.java
+++ b/test/100-reflect2/src/Main.java
@@ -119,8 +119,9 @@
try {
f = Main.class.getDeclaredField("s");
f.set(null, Integer.valueOf(14));
+ System.out.println("************* should have thrown!");
} catch (IllegalArgumentException expected) {
- expected.printStackTrace();
+ System.out.println("got expected IllegalArgumentException");
}
f = Main.class.getDeclaredField("z");
@@ -209,8 +210,8 @@
System.out.println(Arrays.toString(m.getParameterTypes()));
show(m.invoke(null));
System.out.println("************* should have thrown!");
- } catch (Exception expected) {
- expected.printStackTrace();
+ } catch (InvocationTargetException expected) {
+ System.out.println("got expected InvocationTargetException");
}
}