1 /* 2 * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 25 package org.graalvm.compiler.core.test; 26 27 import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier; 28 29 import java.lang.annotation.Annotation; 30 31 import org.graalvm.compiler.nodes.Invoke; 32 import org.graalvm.compiler.nodes.StructuredGraph; 33 import org.graalvm.compiler.nodes.java.MethodCallTargetNode; 34 import org.graalvm.compiler.phases.VerifyPhase; 35 import org.graalvm.compiler.phases.tiers.PhaseContext; 36 37 import jdk.vm.ci.meta.ResolvedJavaMethod; 38 import jdk.vm.ci.meta.ResolvedJavaType; 39 40 /** 41 * Verifies a method is annotated with CallerSensitive iff it calls Reflection#getCallerClass(). 42 */ 43 public class VerifyCallerSensitiveMethods extends VerifyPhase<PhaseContext> { 44 45 Class<? extends Annotation> callerSensitiveClass; 46 Class<?> reflectionClass; 47 48 @Override 49 public boolean checkContract() { 50 return false; 51 } 52 53 @SuppressWarnings("unchecked") 54 public VerifyCallerSensitiveMethods() { 55 try { 56 ClassLoader classLoader = ClassLoader.getSystemClassLoader(); 57 if (Java8OrEarlier) { 58 reflectionClass = classLoader.loadClass("sun.reflect.Reflection"); 59 callerSensitiveClass = (Class<? extends Annotation>) classLoader.loadClass("sun.reflect.ConstantPool"); 60 } else { 61 reflectionClass = classLoader.loadClass("jdk.internal.reflect.Reflection"); 62 callerSensitiveClass = (Class<? extends Annotation>) classLoader.loadClass("jdk.internal.reflect.ConstantPool"); 63 } 64 } catch (ClassNotFoundException e) { 65 throw new AssertionError(e); 66 } 67 } 68 69 @Override 70 protected boolean verify(StructuredGraph graph, PhaseContext context) { 71 Invoke invoke = callsReflectionGetCallerClass(graph, context); 72 Annotation annotation = graph.method().getAnnotation(callerSensitiveClass); 73 if (invoke != null) { 74 if (annotation == null) { 75 StackTraceElement e = graph.method().asStackTraceElement(invoke.bci()); 76 throw new VerificationError(String.format("%s: method that calls Reflection.getCallerClass() must be annotated with @CallerSensitive", e)); 77 } 78 79 } else if (annotation != null) { 80 throw new VerificationError(String.format("%s: method annotated with @CallerSensitive does not call Reflection.getCallerClass()", graph.method().format("%H.%n(%p)"))); 81 } 82 return true; 83 } 84 85 private Invoke callsReflectionGetCallerClass(StructuredGraph graph, PhaseContext context) { 86 ResolvedJavaType reflectionType = context.getMetaAccess().lookupJavaType(reflectionClass); 87 for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.TYPE)) { 88 ResolvedJavaMethod callee = t.targetMethod(); 89 if (callee.getDeclaringClass().equals(reflectionType)) { 90 if (callee.getName().equals("getCallerClass")) { 91 return t.invoke(); 92 } 93 } 94 } 95 return null; 96 } 97 }