1.1 --- a/rt/emul/compact/src/main/java/sun/invoke/util/VerifyAccess.java Sun Aug 17 20:09:05 2014 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,302 +0,0 @@
1.4 -/*
1.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
1.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 - *
1.8 - * This code is free software; you can redistribute it and/or modify it
1.9 - * under the terms of the GNU General Public License version 2 only, as
1.10 - * published by the Free Software Foundation. Oracle designates this
1.11 - * particular file as subject to the "Classpath" exception as provided
1.12 - * by Oracle in the LICENSE file that accompanied this code.
1.13 - *
1.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 - * version 2 for more details (a copy is included in the LICENSE file that
1.18 - * accompanied this code).
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License version
1.21 - * 2 along with this work; if not, write to the Free Software Foundation,
1.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 - *
1.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 - * or visit www.oracle.com if you need additional information or have any
1.26 - * questions.
1.27 - */
1.28 -
1.29 -package sun.invoke.util;
1.30 -
1.31 -import java.lang.reflect.Modifier;
1.32 -import static java.lang.reflect.Modifier.*;
1.33 -
1.34 -/**
1.35 - * This class centralizes information about the JVM's linkage access control.
1.36 - * @author jrose
1.37 - */
1.38 -public class VerifyAccess {
1.39 -
1.40 - private VerifyAccess() { } // cannot instantiate
1.41 -
1.42 - private static final int PACKAGE_ONLY = 0;
1.43 - private static final int PACKAGE_ALLOWED = java.lang.invoke.MethodHandles.Lookup.PACKAGE;
1.44 - private static final int PROTECTED_OR_PACKAGE_ALLOWED = (PACKAGE_ALLOWED|PROTECTED);
1.45 - private static final int ALL_ACCESS_MODES = (PUBLIC|PRIVATE|PROTECTED|PACKAGE_ONLY);
1.46 - private static final boolean ALLOW_NESTMATE_ACCESS = false;
1.47 -
1.48 - /**
1.49 - * Evaluate the JVM linkage rules for access to the given method
1.50 - * on behalf of a caller class which proposes to perform the access.
1.51 - * Return true if the caller class has privileges to invoke a method
1.52 - * or access a field with the given properties.
1.53 - * This requires an accessibility check of the referencing class,
1.54 - * plus an accessibility check of the member within the class,
1.55 - * which depends on the member's modifier flags.
1.56 - * <p>
1.57 - * The relevant properties include the defining class ({@code defc})
1.58 - * of the member, and its modifier flags ({@code mods}).
1.59 - * Also relevant is the class used to make the initial symbolic reference
1.60 - * to the member ({@code refc}). If this latter class is not distinguished,
1.61 - * the defining class should be passed for both arguments ({@code defc == refc}).
1.62 - * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
1.63 - * A field or method R is accessible to a class or interface D if
1.64 - * and only if any of the following conditions is true:<ul>
1.65 - * <li>R is public.
1.66 - * <li>R is protected and is declared in a class C, and D is either
1.67 - * a subclass of C or C itself. Furthermore, if R is not
1.68 - * static, then the symbolic reference to R must contain a
1.69 - * symbolic reference to a class T, such that T is either a
1.70 - * subclass of D, a superclass of D or D itself.
1.71 - * <li>R is either protected or has default access (that is,
1.72 - * neither public nor protected nor private), and is declared
1.73 - * by a class in the same runtime package as D.
1.74 - * <li>R is private and is declared in D.
1.75 - * </ul>
1.76 - * This discussion of access control omits a related restriction
1.77 - * on the target of a protected field access or method invocation
1.78 - * (the target must be of class D or a subtype of D). That
1.79 - * requirement is checked as part of the verification process
1.80 - * (5.4.1); it is not part of link-time access control.
1.81 - * @param refc the class used in the symbolic reference to the proposed member
1.82 - * @param defc the class in which the proposed member is actually defined
1.83 - * @param mods modifier flags for the proposed member
1.84 - * @param lookupClass the class for which the access check is being made
1.85 - * @return true iff the the accessing class can access such a member
1.86 - */
1.87 - public static boolean isMemberAccessible(Class<?> refc, // symbolic ref class
1.88 - Class<?> defc, // actual def class
1.89 - int mods, // actual member mods
1.90 - Class<?> lookupClass,
1.91 - int allowedModes) {
1.92 - if (allowedModes == 0) return false;
1.93 - assert((allowedModes & PUBLIC) != 0 &&
1.94 - (allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED)) == 0);
1.95 - // The symbolic reference class (refc) must always be fully verified.
1.96 - if (!isClassAccessible(refc, lookupClass, allowedModes)) {
1.97 - return false;
1.98 - }
1.99 - // Usually refc and defc are the same, but verify defc also in case they differ.
1.100 - if (defc == lookupClass &&
1.101 - (allowedModes & PRIVATE) != 0)
1.102 - return true; // easy check; all self-access is OK
1.103 - switch (mods & ALL_ACCESS_MODES) {
1.104 - case PUBLIC:
1.105 - return true; // already checked above
1.106 - case PROTECTED:
1.107 - if ((allowedModes & PROTECTED_OR_PACKAGE_ALLOWED) != 0 &&
1.108 - isSamePackage(defc, lookupClass))
1.109 - return true;
1.110 - if ((allowedModes & PROTECTED) == 0)
1.111 - return false;
1.112 - if ((mods & STATIC) != 0 &&
1.113 - !isRelatedClass(refc, lookupClass))
1.114 - return false;
1.115 - if ((allowedModes & PROTECTED) != 0 &&
1.116 - isSuperClass(defc, lookupClass))
1.117 - return true;
1.118 - return false;
1.119 - case PACKAGE_ONLY: // That is, zero. Unmarked member is package-only access.
1.120 - return ((allowedModes & PACKAGE_ALLOWED) != 0 &&
1.121 - isSamePackage(defc, lookupClass));
1.122 - case PRIVATE:
1.123 - // Loosened rules for privates follows access rules for inner classes.
1.124 - return (ALLOW_NESTMATE_ACCESS &&
1.125 - (allowedModes & PRIVATE) != 0 &&
1.126 - isSamePackageMember(defc, lookupClass));
1.127 - default:
1.128 - throw new IllegalArgumentException("bad modifiers: "+Modifier.toString(mods));
1.129 - }
1.130 - }
1.131 -
1.132 - static boolean isRelatedClass(Class<?> refc, Class<?> lookupClass) {
1.133 - return (refc == lookupClass ||
1.134 - refc.isAssignableFrom(lookupClass) ||
1.135 - lookupClass.isAssignableFrom(refc));
1.136 - }
1.137 -
1.138 - static boolean isSuperClass(Class<?> defc, Class<?> lookupClass) {
1.139 - return defc.isAssignableFrom(lookupClass);
1.140 - }
1.141 -
1.142 - static int getClassModifiers(Class<?> c) {
1.143 - // This would return the mask stored by javac for the source-level modifiers.
1.144 - // return c.getModifiers();
1.145 - // But what we need for JVM access checks are the actual bits from the class header.
1.146 - // ...But arrays and primitives are synthesized with their own odd flags:
1.147 - if (c.isArray() || c.isPrimitive())
1.148 - return c.getModifiers();
1.149 - return c.getModifiers();
1.150 -// return Reflection.getClassAccessFlags(c);
1.151 - }
1.152 -
1.153 - /**
1.154 - * Evaluate the JVM linkage rules for access to the given class on behalf of caller.
1.155 - * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
1.156 - * A class or interface C is accessible to a class or interface D
1.157 - * if and only if either of the following conditions are true:<ul>
1.158 - * <li>C is public.
1.159 - * <li>C and D are members of the same runtime package.
1.160 - * </ul>
1.161 - * @param refc the symbolic reference class to which access is being checked (C)
1.162 - * @param lookupClass the class performing the lookup (D)
1.163 - */
1.164 - public static boolean isClassAccessible(Class<?> refc, Class<?> lookupClass,
1.165 - int allowedModes) {
1.166 - if (allowedModes == 0) return false;
1.167 - assert((allowedModes & PUBLIC) != 0 &&
1.168 - (allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED)) == 0);
1.169 - int mods = getClassModifiers(refc);
1.170 - if (isPublic(mods))
1.171 - return true;
1.172 - if ((allowedModes & PACKAGE_ALLOWED) != 0 &&
1.173 - isSamePackage(lookupClass, refc))
1.174 - return true;
1.175 - return false;
1.176 - }
1.177 -
1.178 - /**
1.179 - * Decide if the given method type, attributed to a member or symbolic
1.180 - * reference of a given reference class, is really visible to that class.
1.181 - * @param type the supposed type of a member or symbolic reference of refc
1.182 - * @param refc the class attempting to make the reference
1.183 - */
1.184 - public static boolean isTypeVisible(Class<?> type, Class<?> refc) {
1.185 - if (type == refc) return true; // easy check
1.186 - while (type.isArray()) type = type.getComponentType();
1.187 - if (type.isPrimitive() || type == Object.class) return true;
1.188 - ClassLoader parent = type.getClassLoader();
1.189 - if (parent == null) return true;
1.190 - ClassLoader child = refc.getClassLoader();
1.191 - if (child == null) return false;
1.192 - if (parent == child || loadersAreRelated(parent, child, true))
1.193 - return true;
1.194 - // Do it the hard way: Look up the type name from the refc loader.
1.195 - try {
1.196 - Class<?> res = child.loadClass(type.getName());
1.197 - return (type == res);
1.198 - } catch (ClassNotFoundException ex) {
1.199 - return false;
1.200 - }
1.201 - }
1.202 -
1.203 - /**
1.204 - * Decide if the given method type, attributed to a member or symbolic
1.205 - * reference of a given reference class, is really visible to that class.
1.206 - * @param type the supposed type of a member or symbolic reference of refc
1.207 - * @param refc the class attempting to make the reference
1.208 - */
1.209 - public static boolean isTypeVisible(java.lang.invoke.MethodType type, Class<?> refc) {
1.210 - for (int n = -1, max = type.parameterCount(); n < max; n++) {
1.211 - Class<?> ptype = (n < 0 ? type.returnType() : type.parameterType(n));
1.212 - if (!isTypeVisible(ptype, refc))
1.213 - return false;
1.214 - }
1.215 - return true;
1.216 - }
1.217 -
1.218 - /**
1.219 - * Test if two classes have the same class loader and package qualifier.
1.220 - * @param class1 a class
1.221 - * @param class2 another class
1.222 - * @return whether they are in the same package
1.223 - */
1.224 - public static boolean isSamePackage(Class<?> class1, Class<?> class2) {
1.225 - assert(!class1.isArray() && !class2.isArray());
1.226 - if (class1 == class2)
1.227 - return true;
1.228 - if (class1.getClassLoader() != class2.getClassLoader())
1.229 - return false;
1.230 - String name1 = class1.getName(), name2 = class2.getName();
1.231 - int dot = name1.lastIndexOf('.');
1.232 - if (dot != name2.lastIndexOf('.'))
1.233 - return false;
1.234 - for (int i = 0; i < dot; i++) {
1.235 - if (name1.charAt(i) != name2.charAt(i))
1.236 - return false;
1.237 - }
1.238 - return true;
1.239 - }
1.240 -
1.241 - /** Return the package name for this class.
1.242 - */
1.243 - public static String getPackageName(Class<?> cls) {
1.244 - assert(!cls.isArray());
1.245 - String name = cls.getName();
1.246 - int dot = name.lastIndexOf('.');
1.247 - if (dot < 0) return "";
1.248 - return name.substring(0, dot);
1.249 - }
1.250 -
1.251 - /**
1.252 - * Test if two classes are defined as part of the same package member (top-level class).
1.253 - * If this is true, they can share private access with each other.
1.254 - * @param class1 a class
1.255 - * @param class2 another class
1.256 - * @return whether they are identical or nested together
1.257 - */
1.258 - public static boolean isSamePackageMember(Class<?> class1, Class<?> class2) {
1.259 - if (class1 == class2)
1.260 - return true;
1.261 - if (!isSamePackage(class1, class2))
1.262 - return false;
1.263 - if (getOutermostEnclosingClass(class1) != getOutermostEnclosingClass(class2))
1.264 - return false;
1.265 - return true;
1.266 - }
1.267 -
1.268 - private static Class<?> getOutermostEnclosingClass(Class<?> c) {
1.269 - throw new IllegalStateException("Needed?");
1.270 -// Class<?> pkgmem = c;
1.271 -// for (Class<?> enc = c; (enc = enc.getEnclosingClass()) != null; )
1.272 -// pkgmem = enc;
1.273 -// return pkgmem;
1.274 - }
1.275 -
1.276 - private static boolean loadersAreRelated(ClassLoader loader1, ClassLoader loader2,
1.277 - boolean loader1MustBeParent) {
1.278 - if (loader1 == loader2 || loader1 == null
1.279 - || (loader2 == null && !loader1MustBeParent)) {
1.280 - return true;
1.281 - }
1.282 - for (ClassLoader scan2 = loader2;
1.283 - scan2 != null; scan2 = scan2.getParent()) {
1.284 - if (scan2 == loader1) return true;
1.285 - }
1.286 - if (loader1MustBeParent) return false;
1.287 - // see if loader2 is a parent of loader1:
1.288 - for (ClassLoader scan1 = loader1;
1.289 - scan1 != null; scan1 = scan1.getParent()) {
1.290 - if (scan1 == loader2) return true;
1.291 - }
1.292 - return false;
1.293 - }
1.294 -
1.295 - /**
1.296 - * Is the class loader of parentClass identical to, or an ancestor of,
1.297 - * the class loader of childClass?
1.298 - * @param parentClass a class
1.299 - * @param childClass another class, which may be a descendent of the first class
1.300 - * @return whether parentClass precedes or equals childClass in class loader order
1.301 - */
1.302 - public static boolean classLoaderIsAncestor(Class<?> parentClass, Class<?> childClass) {
1.303 - return loadersAreRelated(parentClass.getClassLoader(), childClass.getClassLoader(), true);
1.304 - }
1.305 -}