1 /* 2 * Copyright (c) 2013, 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 package org.graalvm.compiler.phases.verify; 24 25 import static org.graalvm.compiler.core.common.util.Util.Java8OrEarlier; 26 27 import java.lang.annotation.Annotation; 28 29 import org.graalvm.compiler.nodes.Invoke; 30 import org.graalvm.compiler.nodes.StructuredGraph; 31 import org.graalvm.compiler.nodes.java.MethodCallTargetNode; 32 import org.graalvm.compiler.phases.VerifyPhase; 33 import org.graalvm.compiler.phases.tiers.PhaseContext; 34 35 import jdk.vm.ci.meta.ResolvedJavaMethod; 36 import jdk.vm.ci.meta.ResolvedJavaType; 37 38 /** 39 * Verifies a method is annotated with CallerSensitive iff it calls Reflection#getCallerClass(). 40 */ 41 public class VerifyCallerSensitiveMethods extends VerifyPhase<PhaseContext> { 42 43 Class<? extends Annotation> callerSensitiveClass; 44 Class<?> reflectionClass; 45 46 @Override 47 public boolean checkContract() { 48 return false; 49 } 50 51 @SuppressWarnings("unchecked") 52 public VerifyCallerSensitiveMethods() { 53 try { 54 ClassLoader classLoader = ClassLoader.getSystemClassLoader(); 55 if (Java8OrEarlier) { 56 reflectionClass = classLoader.loadClass("sun.reflect.Reflection"); 57 callerSensitiveClass = (Class<? extends Annotation>) classLoader.loadClass("sun.reflect.ConstantPool"); 58 } else { 59 reflectionClass = classLoader.loadClass("jdk.internal.reflect.Reflection"); 60 callerSensitiveClass = (Class<? extends Annotation>) classLoader.loadClass("jdk.internal.reflect.ConstantPool"); 61 } 62 } catch (ClassNotFoundException e) { 63 throw new AssertionError(e); 64 } 65 } 66 67 @Override 68 protected boolean verify(StructuredGraph graph, PhaseContext context) { 69 Invoke invoke = callsReflectionGetCallerClass(graph, context); 70 Annotation annotation = graph.method().getAnnotation(callerSensitiveClass); 71 if (invoke != null) { 72 if (annotation == null) { 73 StackTraceElement e = graph.method().asStackTraceElement(invoke.bci()); 74 throw new VerificationError(String.format("%s: method that calls Reflection.getCallerClass() must be annotated with @CallerSensitive", e)); 75 } 76 77 } else if (annotation != null) { 78 throw new VerificationError(String.format("%s: method annotated with @CallerSensitive does not call Reflection.getCallerClass()", graph.method().format("%H.%n(%p)"))); 79 } 80 return true; 81 } 82 83 private Invoke callsReflectionGetCallerClass(StructuredGraph graph, PhaseContext context) { 84 ResolvedJavaType reflectionType = context.getMetaAccess().lookupJavaType(reflectionClass); 85 for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.TYPE)) { 86 ResolvedJavaMethod callee = t.targetMethod(); 87 if (callee.getDeclaringClass().equals(reflectionType)) { 88 if (callee.getName().equals("getCallerClass")) { 89 return t.invoke(); 90 } 91 } 92 } 93 return null; 94 } 95 }