1 /* 2 * Copyright (c) 2019, 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 java.util.regex.Matcher; 28 import java.util.regex.Pattern; 29 30 import org.graalvm.compiler.nodes.StructuredGraph; 31 import org.graalvm.compiler.nodes.java.MethodCallTargetNode; 32 import org.graalvm.compiler.nodes.spi.CoreProviders; 33 import org.graalvm.compiler.phases.VerifyPhase; 34 35 import jdk.vm.ci.meta.MetaAccessProvider; 36 import jdk.vm.ci.meta.ResolvedJavaMethod; 37 import jdk.vm.ci.meta.ResolvedJavaType; 38 import jdk.vm.ci.services.Services; 39 40 /** 41 * Checks against calls to {@link System#getProperty(String)}, 42 * {@link System#getProperty(String, String)} and {@link System#getProperties()}. System properties 43 * can be modified by application code so {@link Services#getSavedProperties()} should be used 44 * instead. 45 */ 46 public class VerifySystemPropertyUsage extends VerifyPhase<CoreProviders> { 47 48 static final Class<?>[] BOXES = {Integer.class, Long.class, Boolean.class, Float.class, Double.class}; 49 static final int JVMCI_VERSION_MAJOR; 50 static final int JVMCI_VERSION_MINOR; 51 static { 52 int major = -1; 53 int minor = -1; 54 String vmVersion = System.getProperty("java.vm.version"); 55 if (System.getProperty("java.specification.version").compareTo("1.9") < 0) { 56 Pattern re = Pattern.compile(".*-jvmci-(\\d+)\\.(\\d+).*"); 57 Matcher matcher = re.matcher(vmVersion); 58 if (matcher.matches()) { 59 major = Integer.parseInt(matcher.group(1)); 60 minor = Integer.parseInt(matcher.group(2)); 61 } 62 } 63 JVMCI_VERSION_MAJOR = major; 64 JVMCI_VERSION_MINOR = minor; 65 } 66 67 @Override 68 protected void verify(StructuredGraph graph, CoreProviders context) { 69 MetaAccessProvider metaAccess = context.getMetaAccess(); 70 final ResolvedJavaType systemType = metaAccess.lookupJavaType(System.class); 71 final ResolvedJavaType[] boxTypes = new ResolvedJavaType[BOXES.length]; 72 for (int i = 0; i < boxTypes.length; i++) { 73 boxTypes[i] = metaAccess.lookupJavaType(BOXES[i]); 74 } 75 76 ResolvedJavaMethod caller = graph.method(); 77 String holderQualified = caller.format("%H"); 78 String holderUnqualified = caller.format("%h"); 79 String packageName = holderQualified.equals(holderUnqualified) ? "" : holderQualified.substring(0, holderQualified.length() - holderUnqualified.length() - 1); 80 if (packageName.startsWith("jdk.vm.ci")) { 81 if (JVMCI_VERSION_MAJOR >= 0 && JVMCI_VERSION_MINOR > 56) { 82 // This JVMCI version should not use non-saved system properties 83 } else { 84 // This JVMCI version still has some calls that need to be removed 85 return; 86 } 87 } else if (holderQualified.equals("org.graalvm.compiler.hotspot.JVMCIVersionCheck") && caller.getName().equals("main")) { 88 // The main method in JVMCIVersionCheck is only called from the shell 89 return; 90 } else if (packageName.startsWith("com.oracle.truffle") || packageName.startsWith("org.graalvm.polyglot")) { 91 // Truffle and Polyglot do not depend on JVMCI so cannot use 92 // Services.getSavedProperties() 93 return; 94 } else if (packageName.startsWith("com.oracle.svm")) { 95 // SVM must read system properties in: 96 // * its JDK substitutions to mimic required JDK semantics 97 // * native-image for config info 98 return; 99 } 100 for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.TYPE)) { 101 ResolvedJavaMethod callee = t.targetMethod(); 102 if (callee.getDeclaringClass().equals(systemType)) { 103 if (callee.getName().equals("getProperty") || callee.getName().equals("getProperties")) { 104 throw new VerificationError("Call to %s at callsite %s is prohibited. Call Services.getSavedProperties().get(String) instead.", 105 callee.format("%H.%n(%p)"), 106 caller.format("%H.%n(%p)")); 107 } 108 } else { 109 for (int i = 0; i < boxTypes.length; i++) { 110 ResolvedJavaType boxType = boxTypes[i]; 111 if (callee.getDeclaringClass().equals(boxType)) { 112 String simpleName = boxType.toJavaName(false); 113 if (callee.getName().equals("get" + simpleName)) { 114 throw new VerificationError("Call to %s at callsite %s is prohibited. Call %s.parse%s(Services.getSavedProperties().get(String)) instead.", 115 callee.format("%H.%n(%p)"), 116 caller.format("%H.%n(%p)"), 117 simpleName, simpleName); 118 } 119 } 120 } 121 } 122 } 123 } 124 125 }