# HG changeset patch # User Gilles Duboscq # Date 1411113596 -7200 # Node ID a8eb7473d58a2a4f86ae686459509ace09cbd12c # Parent 7716c6993546ddba6c75fc27364fb30db5a3a240 Add test for interface types diff -r 7716c6993546 -r a8eb7473d58a graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/UntrustedInterfaces.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/UntrustedInterfaces.java Fri Sep 19 09:59:56 2014 +0200 @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.jtt.except; + +import org.junit.*; +import org.objectweb.asm.*; + +import com.oracle.graal.jtt.*; + +public class UntrustedInterfaces extends JTTTest { + + public interface CallBack { + public int callBack(TestInterface ti); + } + + private interface TestInterface { + int method(); + } + + /** + * What a GoodPill would look like: + * + *
+     * private static final class GoodPill extends Pill {
+     *     public void setField() {
+     *         field = new TestConstant();
+     *     }
+     *
+     *     public void setStaticField() {
+     *         staticField = new TestConstant();
+     *     }
+     *
+     *     public int callMe(CallBack callback) {
+     *         return callback.callBack(new TestConstant());
+     *     }
+     *
+     *     public TestInterface get() {
+     *         return new TestConstant();
+     *     }
+     * }
+     *
+     * private static final class TestConstant implements TestInterface {
+     *     public int method() {
+     *         return 42;
+     *     }
+     * }
+     * 
+ */ + public static abstract class Pill { + public static TestInterface staticField; + public TestInterface field; + + public abstract void setField(); + + public abstract void setStaticField(); + + public abstract int callMe(CallBack callback); + + public abstract TestInterface get(); + } + + public int callBack(TestInterface list) { + return list.method(); + } + + public int staticFieldInvoke(Pill pill) { + pill.setStaticField(); + return Pill.staticField.method(); + } + + public int fieldInvoke(Pill pill) { + pill.setField(); + return pill.field.method(); + } + + public int argumentInvoke(Pill pill) { + return pill.callMe(ti -> ti.method()); + } + + public int returnInvoke(Pill pill) { + return pill.get().method(); + } + + @SuppressWarnings("cast") + public boolean staticFieldInstanceof(Pill pill) { + pill.setStaticField(); + return Pill.staticField instanceof TestInterface; + } + + @SuppressWarnings("cast") + public boolean fieldInstanceof(Pill pill) { + pill.setField(); + return pill.field instanceof TestInterface; + } + + @SuppressWarnings("cast") + public int argumentInstanceof(Pill pill) { + return pill.callMe(ti -> ti instanceof TestInterface ? 42 : 24); + } + + @SuppressWarnings("cast") + public boolean returnInstanceof(Pill pill) { + return pill.get() instanceof TestInterface; + } + + public TestInterface staticFieldCheckcast(Pill pill) { + pill.setStaticField(); + return TestInterface.class.cast(Pill.staticField); + } + + public TestInterface fieldCheckcast(Pill pill) { + pill.setField(); + return TestInterface.class.cast(pill.field); + } + + public int argumentCheckcast(Pill pill) { + return pill.callMe(ti -> TestInterface.class.cast(ti).method()); + } + + public TestInterface returnCheckcast(Pill pill) { + return TestInterface.class.cast(pill.get()); + } + + private static Pill poisonPill; + + @BeforeClass + public static void setup() throws InstantiationException, IllegalAccessException, ClassNotFoundException { + poisonPill = (Pill) new PoisonLoader().findClass(PoisonLoader.POISON_IMPL_NAME).newInstance(); + } + + @Test + public void testStaticField0() { + runTest("staticFieldInvoke", poisonPill); + } + + @Test + public void testStaticField1() { + runTest("staticFieldInstanceof", poisonPill); + } + + @Test + public void testStaticField2() { + runTest("staticFieldCheckcast", poisonPill); + } + + @Test + public void testField0() { + runTest("fieldInvoke", poisonPill); + } + + @Test + public void testField1() { + runTest("fieldInstanceof", poisonPill); + } + + @Test + public void testField2() { + runTest("fieldCheckcast", poisonPill); + } + + @Test + public void testArgument0() { + runTest("argumentInvoke", poisonPill); + } + + @Test + public void testArgument1() { + runTest("argumentInstanceof", poisonPill); + } + + @Test + public void testArgument2() { + runTest("argumentCheckcast", poisonPill); + } + + @Test + public void testReturn0() { + runTest("returnInvoke", poisonPill); + } + + @Test + public void testReturn1() { + runTest("returnInstanceof", poisonPill); + } + + @Test + public void testReturn2() { + runTest("returnCheckcast", poisonPill); + } + + private static class PoisonLoader extends ClassLoader { + public static final String POISON_IMPL_NAME = "com.oracle.graal.jtt.except.PoisonPill"; + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + if (name.equals(POISON_IMPL_NAME)) { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); + + cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, POISON_IMPL_NAME.replace('.', '/'), null, Type.getInternalName(Pill.class), null); + // constructor + MethodVisitor constructor = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); + constructor.visitCode(); + constructor.visitVarInsn(Opcodes.ALOAD, 0); + constructor.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Pill.class), "", "()V", false); + constructor.visitInsn(Opcodes.RETURN); + constructor.visitMaxs(0, 0); + constructor.visitEnd(); + + MethodVisitor setList = cw.visitMethod(Opcodes.ACC_PUBLIC, "setField", "()V", null, null); + setList.visitCode(); + setList.visitVarInsn(Opcodes.ALOAD, 0); + setList.visitTypeInsn(Opcodes.NEW, Type.getInternalName(Object.class)); + setList.visitInsn(Opcodes.DUP); + setList.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), "", "()V", false); + setList.visitFieldInsn(Opcodes.PUTFIELD, Type.getInternalName(Pill.class), "field", Type.getDescriptor(TestInterface.class)); + setList.visitInsn(Opcodes.RETURN); + setList.visitMaxs(0, 0); + setList.visitEnd(); + + MethodVisitor setStaticList = cw.visitMethod(Opcodes.ACC_PUBLIC, "setStaticField", "()V", null, null); + setStaticList.visitCode(); + setStaticList.visitTypeInsn(Opcodes.NEW, Type.getInternalName(Object.class)); + setStaticList.visitInsn(Opcodes.DUP); + setStaticList.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), "", "()V", false); + setStaticList.visitFieldInsn(Opcodes.PUTSTATIC, Type.getInternalName(Pill.class), "staticField", Type.getDescriptor(TestInterface.class)); + setStaticList.visitInsn(Opcodes.RETURN); + setStaticList.visitMaxs(0, 0); + setStaticList.visitEnd(); + + MethodVisitor callMe = cw.visitMethod(Opcodes.ACC_PUBLIC, "callMe", Type.getMethodDescriptor(Type.INT_TYPE, Type.getType(CallBack.class)), null, null); + callMe.visitCode(); + callMe.visitVarInsn(Opcodes.ALOAD, 1); + callMe.visitTypeInsn(Opcodes.NEW, Type.getInternalName(Object.class)); + callMe.visitInsn(Opcodes.DUP); + callMe.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), "", "()V", false); + callMe.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.getInternalName(CallBack.class), "callBack", Type.getMethodDescriptor(Type.INT_TYPE, Type.getType(TestInterface.class)), true); + callMe.visitInsn(Opcodes.IRETURN); + callMe.visitMaxs(0, 0); + callMe.visitEnd(); + + MethodVisitor getList = cw.visitMethod(Opcodes.ACC_PUBLIC, "get", Type.getMethodDescriptor(Type.getType(TestInterface.class)), null, null); + getList.visitCode(); + getList.visitTypeInsn(Opcodes.NEW, Type.getInternalName(Object.class)); + getList.visitInsn(Opcodes.DUP); + getList.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), "", "()V", false); + getList.visitInsn(Opcodes.ARETURN); + getList.visitMaxs(0, 0); + getList.visitEnd(); + + cw.visitEnd(); + + byte[] bytes = cw.toByteArray(); + return defineClass(name, bytes, 0, bytes.length); + } + return super.findClass(name); + } + } +} diff -r 7716c6993546 -r a8eb7473d58a mx/projects --- a/mx/projects Thu Sep 18 17:41:19 2014 +0200 +++ b/mx/projects Fri Sep 19 09:59:56 2014 +0200 @@ -73,6 +73,13 @@ library@OKRA_WITH_SIM@sourceSha1=7eefd94f16a3e3fd3b8f470cf91e265c6f5e7767 library@OKRA_WITH_SIM@sourceUrls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/okra-1.10-with-sim-src.jar,http://cr.openjdk.java.net/~tdeneau/okra-1.10-with-sim-src.jar +library@ASM@path=lib/asm-5.0.3.jar +library@ASM@urls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/asm-5.0.3.jar,http://central.maven.org/maven2/org/ow2/asm/asm/5.0.3/asm-5.0.3.jar +library@ASM@sha1=dcc2193db20e19e1feca8b1240dbbc4e190824fa +library@ASM@sourcePath=lib/asm-5.0.3-sources.jar +library@ASM@sourceSha1=f0f24f6666c1a15c7e202e91610476bd4ce59368 +library@ASM@sourceUrls=http://lafo.ssw.uni-linz.ac.at/graal-external-deps/asm-5.0.3-sources.jar,http://central.maven.org/maven2/org/ow2/asm/asm/5.0.3/asm-5.0.3-sources.jar + library@JAVA_ALLOCATION_INSTRUMENTER@path=lib/java-allocation-instrumenter.jar library@JAVA_ALLOCATION_INSTRUMENTER@sourcePath=lib/java-allocation-instrumenter.jar library@JAVA_ALLOCATION_INSTRUMENTER@urls=http://lafo.ssw.uni-linz.ac.at/java-allocation-instrumenter/java-allocation-instrumenter-8f0db117e64e.jar @@ -675,7 +682,7 @@ # graal.jtt project@com.oracle.graal.jtt@subDir=graal project@com.oracle.graal.jtt@sourceDirs=src -project@com.oracle.graal.jtt@dependencies=com.oracle.graal.compiler.test +project@com.oracle.graal.jtt@dependencies=com.oracle.graal.compiler.test,ASM project@com.oracle.graal.jtt@checkstyle=com.oracle.graal.graph project@com.oracle.graal.jtt@javaCompliance=1.8 project@com.oracle.graal.jtt@workingSets=Graal,Test