123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- package test.javassist.proxy;
- import static org.hamcrest.Matchers.arrayWithSize;
- import static org.hamcrest.Matchers.both;
- import static org.hamcrest.Matchers.endsWith;
- import static org.hamcrest.Matchers.equalTo;
- import static org.hamcrest.Matchers.instanceOf;
- import static org.hamcrest.Matchers.not;
- import static org.hamcrest.Matchers.notNullValue;
- import static org.hamcrest.Matchers.startsWith;
- import static org.hamcrest.Matchers.stringContainsInOrder;
- import static org.junit.Assert.assertThat;
- import static org.junit.Assert.assertTrue;
-
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import java.lang.reflect.Modifier;
- import java.security.ProtectionDomain;
- import java.util.Arrays;
-
- import org.junit.Rule;
- import org.junit.Test;
- import org.junit.rules.ExpectedException;
-
- import javassist.ClassPool;
- import javassist.CtClass;
- import javassist.util.proxy.DefineClassHelper;
-
- public class TestSecuredPrivileged {
-
- public TestSecuredPrivileged() {
- }
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
- /**
- * Test proves that you cannot even access members with
- * private static and final modifiers. */
- @Test
- public void testDefinedHelperPrivilegedFieldVisibility() {
- try {
- Field privi = DefineClassHelper.class.getDeclaredField("privileged");
- assertTrue(Modifier.isStatic(privi.getModifiers()));
- thrown.expectCause(instanceOf(IllegalAccessException.class));
- thrown.expectMessage(both(stringContainsInOrder(Arrays.asList("cannot access a member")))
- .and(stringContainsInOrder(Arrays.asList("with modifiers \"private static final".split("", 1)))));
-
- privi.get(null);
- } catch(Throwable t) {
- throw new RuntimeException(t);
- }
- }
- /**
- * Test proves that the default enum constant is a class and specifically
- * auto selected for Java 9. */
- @Test
- public void testDefinedHelperPrivilegedField() {
- try {
- Field privi = DefineClassHelper.class.getDeclaredField("privileged");
- assertTrue(Modifier.isStatic(privi.getModifiers()));
- Constructor<DefineClassHelper> con = DefineClassHelper.class.getDeclaredConstructor();
- con.setAccessible(true);
- DefineClassHelper inst = con.newInstance();
- assertThat(inst, instanceOf(DefineClassHelper.class));
- privi.setAccessible(true);
- Object p = privi.get(inst);
- assertThat(""+p, equalTo("JAVA_9"));
- assertThat(p.getClass().getName(), endsWith("SecuredPrivileged$1"));
- } catch(Throwable t) {
- throw new RuntimeException(t);
- }
- }
- /**
- * Test proves that caller class security is enforced and works
- * as expected. */
- @Test
- public void testDefinedHelperPrivilegedFieldMethodAccessDenied() {
- try {
- Constructor<DefineClassHelper> con = DefineClassHelper.class.getDeclaredConstructor();
- con.setAccessible(true);
- DefineClassHelper inst = con.newInstance();
- Field privi = DefineClassHelper.class.getDeclaredField("privileged");
- privi.setAccessible(true);
- Object priviInst = privi.get(inst);
- Method defineClass = priviInst.getClass().getDeclaredMethod(
- "defineClass", new Class[] {
- String.class, byte[].class, int.class, int.class,
- ClassLoader.class, ProtectionDomain.class
- });
-
- assertThat(defineClass, notNullValue());
- defineClass.setAccessible(true);
- assertThat(defineClass.getName(), equalTo("defineClass"));
- assertTrue(defineClass.canAccess(priviInst));
- ClassPool cp = ClassPool.getDefault();
- CtClass c = cp.makeClass("a.b.C");
- byte[] bc = c.toBytecode();
-
- thrown.expectCause(instanceOf(IllegalAccessError.class));
- thrown.expectMessage(equalTo("java.lang.IllegalAccessError: Access denied for caller."));
-
- @SuppressWarnings("unused")
- Object res = defineClass.invoke(priviInst, new Object[] {
- c.getName(), bc, 0, bc.length, new ClassLoader() {},
- ClassLoader.class.getProtectionDomain()
- });
- } catch(InvocationTargetException t) {
- throw new RuntimeException(t.getTargetException());
- } catch(Throwable t) { throw new RuntimeException(t); }
- }
- /**
- * Test proves that we do have 3 enum constants in the private static
- * inner class. */
- @Test
- public void testDefinedHelperEnumClass() {
- try {
- Constructor<DefineClassHelper> con = DefineClassHelper.class.getDeclaredConstructor();
- con.setAccessible(true);
- assertThat(DefineClassHelper.class.getDeclaredClasses(), arrayWithSize(1));
- Class<?> secPriv = DefineClassHelper.class.getDeclaredClasses()[0];
- assertTrue(secPriv.isEnum());
- assertThat(secPriv.getEnumConstants(), arrayWithSize(3));
- assertThat(""+secPriv.getEnumConstants()[0], equalTo("JAVA_9"));
- assertThat(""+secPriv.getEnumConstants()[1], equalTo("JAVA_7"));
- assertThat(""+secPriv.getEnumConstants()[2], equalTo("JAVA_OTHER"));
-
- } catch (Throwable t) {t.printStackTrace();}
-
- }
- /**
- * Test proves that you cannot modify private static final reference even
- * with setAccessible(true). */
- @Test
- public void testDefinedHelperCannotSetPrivileged() {
- try {
- Constructor<DefineClassHelper> con = DefineClassHelper.class.getDeclaredConstructor();
- con.setAccessible(true);
- DefineClassHelper inst = con.newInstance();
- Class<?> secPriv = DefineClassHelper.class.getDeclaredClasses()[0];
- Object J7 = secPriv.getEnumConstants()[1];
- Field privi = DefineClassHelper.class.getDeclaredField("privileged");
- privi.setAccessible(true);
- thrown.expectCause(instanceOf(IllegalAccessException.class));
- thrown.expectMessage(startsWith("java.lang.IllegalAccessException: Can not set static final"));
- privi.set(inst, J7);
-
- } catch (Throwable t) {throw new RuntimeException(t);}
-
- }
- /**
- * Test proves that you can achieve the impossible and modify private
- * static final class reference without an instance. Now we can Mock
- * test JDK 6 to 8 functionality */
- @Test
- public void testDefinedHelperSetPrivilegedToJava7() {
- try {
- Constructor<DefineClassHelper> con = DefineClassHelper.class.getDeclaredConstructor();
- con.setAccessible(true);
- DefineClassHelper inst = con.newInstance();
- Class<?> secPriv = DefineClassHelper.class.getDeclaredClasses()[0];
- Object J9 = secPriv.getEnumConstants()[0];
- Object J7 = secPriv.getEnumConstants()[1];
- Field privi = DefineClassHelper.class.getDeclaredField("privileged");
- privi.setAccessible(true);
- Object privInst = privi.get(inst);
- Field unsf = privInst.getClass().getDeclaredField("sunMiscUnsafe");
- unsf.setAccessible(true);
- Object refu = unsf.get(privInst);
- Field tuf = refu.getClass().getDeclaredField("sunMiscUnsafeTheUnsafe");
- tuf.setAccessible(true);
- Object tu = tuf.get(refu);
- Method tu_call = tu.getClass().getMethod("call", new Class<?>[] {String.class, Object[].class});
- tu_call.setAccessible(true);
- long offset = (Long) tu_call.invoke(tu, new Object[] {"staticFieldOffset", new Object[] {privi}});
- tu_call.invoke(tu, new Object[] {"putObjectVolatile", new Object[] {DefineClassHelper.class, offset, J7}});
-
- Object p = privi.get(inst);
- assertThat(""+p, equalTo("JAVA_7"));
- assertThat(p.getClass().getName(), endsWith("SecuredPrivileged$2"));
-
- tu_call.invoke(tu, new Object[] {"putObjectVolatile", new Object[] {DefineClassHelper.class, offset, J9}});
-
- } catch (Throwable t) {t.printStackTrace();}
-
- }
- /**
- * Test proves that Java 7+ MethodHandle defineClass (or DefineClassHelper.toClass)
- * works as expected. */
- @Test
- public void testDefinedHelperJava7ToClass() {
- try {
- Constructor<DefineClassHelper> con = DefineClassHelper.class.getDeclaredConstructor();
- con.setAccessible(true);
- DefineClassHelper inst = con.newInstance();
- Class<?> secPriv = DefineClassHelper.class.getDeclaredClasses()[0];
- Object J9 = secPriv.getEnumConstants()[0];
- Object J7 = secPriv.getEnumConstants()[1];
- Field privi = DefineClassHelper.class.getDeclaredField("privileged");
- privi.setAccessible(true);
- Object privInst = privi.get(inst);
- Field unsf = privInst.getClass().getDeclaredField("sunMiscUnsafe");
- unsf.setAccessible(true);
- Object refu = unsf.get(privInst);
- Field tuf = refu.getClass().getDeclaredField("sunMiscUnsafeTheUnsafe");
- tuf.setAccessible(true);
- Object tu = tuf.get(refu);
- Method tu_call = tu.getClass().getMethod("call", new Class<?>[] {String.class, Object[].class});
- tu_call.setAccessible(true);
- long offset = (Long) tu_call.invoke(tu, new Object[] {"staticFieldOffset", new Object[] {privi}});
- tu_call.invoke(tu, new Object[] {"putObjectVolatile", new Object[] {DefineClassHelper.class, offset, J7}});
-
- ClassPool cp = ClassPool.getDefault();
- CtClass c = cp.makeClass("a.b.J7");
- byte[] bc = c.toBytecode();
- Class<?> bcCls = DefineClassHelper.toClass("a.b.J7", new ClassLoader() {}, null, bc);
- assertThat(bcCls.getName(), equalTo("a.b.J7"));
- assertThat(bcCls.getDeclaredConstructor().newInstance(),
- not(equalTo(bcCls.getDeclaredConstructor().newInstance())));
-
- tu_call.invoke(tu, new Object[] {"putObjectVolatile", new Object[] {DefineClassHelper.class, offset, J9}});
-
- } catch (Throwable t) {t.printStackTrace();}
-
- }
- /**
- * Test proves that Java 6 reflection method defineClass (or DefineClassHelper.toClass)
- * works as expected. */
- @Test
- public void testDefinedHelperJavaOtherToClass() {
- try {
- Constructor<DefineClassHelper> con = DefineClassHelper.class.getDeclaredConstructor();
- con.setAccessible(true);
- DefineClassHelper inst = con.newInstance();
- Class<?> secPriv = DefineClassHelper.class.getDeclaredClasses()[0];
- Object J9 = secPriv.getEnumConstants()[0];
- Object JO = secPriv.getEnumConstants()[2];
- Field privi = DefineClassHelper.class.getDeclaredField("privileged");
- privi.setAccessible(true);
- Object privInst = privi.get(inst);
- Field unsf = privInst.getClass().getDeclaredField("sunMiscUnsafe");
- unsf.setAccessible(true);
- Object refu = unsf.get(privInst);
- Field tuf = refu.getClass().getDeclaredField("sunMiscUnsafeTheUnsafe");
- tuf.setAccessible(true);
- Object tu = tuf.get(refu);
- Method tu_call = tu.getClass().getMethod("call", new Class<?>[] {String.class, Object[].class});
- tu_call.setAccessible(true);
- long offset = (Long) tu_call.invoke(tu, new Object[] {"staticFieldOffset", new Object[] {privi}});
- tu_call.invoke(tu, new Object[] {"putObjectVolatile", new Object[] {DefineClassHelper.class, offset, JO}});
-
- ClassPool cp = ClassPool.getDefault();
- CtClass c = cp.makeClass("a.b.JO");
- byte[] bc = c.toBytecode();
- Class<?> bcCls = DefineClassHelper.toClass("a.b.JO", new ClassLoader() {}, null, bc);
- assertThat(bcCls.getName(), equalTo("a.b.JO"));
- assertThat(bcCls.getDeclaredConstructor().newInstance(),
- not(equalTo(bcCls.getDeclaredConstructor().newInstance())));
-
- tu_call.invoke(tu, new Object[] {"putObjectVolatile", new Object[] {DefineClassHelper.class, offset, J9}});
-
- } catch (Throwable t) {t.printStackTrace();}
-
- }
- /**
- * Test proves that default Java 9 defineClass (or DefineClassHelper.toClass)
- * works as expected. */
- @Test
- public void testDefinedHelperDefaultToClass() {
- try {
- ClassPool cp = ClassPool.getDefault();
- CtClass c = cp.makeClass("a.b.D");
- byte[] bc = c.toBytecode();
- Class<?> bcCls = DefineClassHelper.toClass("a.b.D", new ClassLoader() {}, null, bc);
- assertThat(bcCls.getName(), equalTo("a.b.D"));
- assertThat(bcCls.getDeclaredConstructor().newInstance(),
- not(equalTo(bcCls.getDeclaredConstructor().newInstance())));
- } catch (Throwable t) {t.printStackTrace();}
-
- }
- }
|