< prev index next >

src/java.base/share/classes/java/lang/invoke/MethodHandles.java

Print this page


   1 /*
   2  * Copyright (c) 2008, 2017, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 818             if (allowedModes == TRUSTED)  // IMPL_LOOKUP can make any lookup at all
 819                 return new Lookup(requestedLookupClass, FULL_POWER_MODES);
 820             if (requestedLookupClass == this.lookupClass)
 821                 return this;  // keep same capabilities
 822             int newModes = (allowedModes & FULL_POWER_MODES);
 823             if (!VerifyAccess.isSameModule(this.lookupClass, requestedLookupClass)) {
 824                 // Need to drop all access when teleporting from a named module to another
 825                 // module. The exception is publicLookup where PUBLIC is not lost.
 826                 if (this.lookupClass.getModule().isNamed()
 827                     && (this.allowedModes & UNCONDITIONAL) == 0)
 828                     newModes = 0;
 829                 else
 830                     newModes &= ~(MODULE|PACKAGE|PRIVATE|PROTECTED);
 831             }
 832             if ((newModes & PACKAGE) != 0
 833                 && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) {
 834                 newModes &= ~(PACKAGE|PRIVATE|PROTECTED);
 835             }
 836             // Allow nestmate lookups to be created without special privilege:
 837             if ((newModes & PRIVATE) != 0
 838                 && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) {
 839                 newModes &= ~(PRIVATE|PROTECTED);
 840             }
 841             if ((newModes & PUBLIC) != 0
 842                 && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass, allowedModes)) {
 843                 // The requested class it not accessible from the lookup class.
 844                 // No permissions.
 845                 newModes = 0;
 846             }
 847 
 848             checkUnprivilegedlookupClass(requestedLookupClass);
 849             return new Lookup(requestedLookupClass, newModes);
 850         }
 851 
 852 
 853         /**
 854          * Creates a lookup on the same lookup class which this lookup object
 855          * finds members, but with a lookup mode that has lost the given lookup mode.
 856          * The lookup mode to drop is one of {@link #PUBLIC PUBLIC}, {@link #MODULE
 857          * MODULE}, {@link #PACKAGE PACKAGE}, {@link #PROTECTED PROTECTED} or {@link #PRIVATE PRIVATE}.
 858          * {@link #PROTECTED PROTECTED} and {@link #UNCONDITIONAL UNCONDITIONAL} are always


2199             // check the class first:
2200             boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
2201                                (defc == refc ||
2202                                 Modifier.isPublic(refc.getModifiers())));
2203             if (!classOK && (allowedModes & PACKAGE) != 0) {
2204                 classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), FULL_POWER_MODES) &&
2205                            (defc == refc ||
2206                             VerifyAccess.isClassAccessible(refc, lookupClass(), FULL_POWER_MODES)));
2207             }
2208             if (!classOK)
2209                 return "class is not public";
2210             if (Modifier.isPublic(mods))
2211                 return "access to public member failed";  // (how?, module not readable?)
2212             if (Modifier.isPrivate(mods))
2213                 return "member is private";
2214             if (Modifier.isProtected(mods))
2215                 return "member is protected";
2216             return "member is private to package";
2217         }
2218 
2219         private static final boolean ALLOW_NESTMATE_ACCESS = false; // experiment with protected nestmate access
2220 
2221         private void checkSpecialCaller(Class<?> specialCaller, Class<?> refc) throws IllegalAccessException {
2222             int allowedModes = this.allowedModes;
2223             if (allowedModes == TRUSTED)  return;
2224             if (!hasPrivateAccess()
2225                 || (specialCaller != lookupClass()
2226                        // ensure non-abstract methods in superinterfaces can be special-invoked
2227                     && !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))
2228                     && !(ALLOW_NESTMATE_ACCESS &&
2229                          VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
2230                 throw new MemberName(specialCaller).
2231                     makeAccessException("no private access for invokespecial", this);
2232         }
2233 
2234         private boolean restrictProtectedReceiver(MemberName method) {
2235             // The accessing class only has the right to use a protected member
2236             // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
2237             if (!method.isProtected() || method.isStatic()
2238                 || allowedModes == TRUSTED
2239                 || method.getDeclaringClass() == lookupClass()
2240                 || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass())
2241                 || (ALLOW_NESTMATE_ACCESS &&
2242                     VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
2243                 return false;
2244             return true;
2245         }
2246         private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, Class<?> caller) throws IllegalAccessException {
2247             assert(!method.isStatic());
2248             // receiver type of mh is too wide; narrow to caller
2249             if (!method.getDeclaringClass().isAssignableFrom(caller)) {
2250                 throw method.makeAccessException("caller class must be a subclass below the method", caller);
2251             }
2252             MethodType rawType = mh.type();
2253             if (caller.isAssignableFrom(rawType.parameterType(0))) return mh; // no need to restrict; already narrow
2254             MethodType narrowType = rawType.changeParameterType(0, caller);
2255             assert(!mh.isVarargsCollector());  // viewAsType will lose varargs-ness
2256             assert(mh.viewAsTypeChecks(narrowType, true));
2257             return mh.copyWith(narrowType, mh.form);
2258         }
2259 
2260         /** Check access and get the requested method. */
2261         private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
2262             final boolean doRestrict    = true;


   1 /*
   2  * Copyright (c) 2008, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 818             if (allowedModes == TRUSTED)  // IMPL_LOOKUP can make any lookup at all
 819                 return new Lookup(requestedLookupClass, FULL_POWER_MODES);
 820             if (requestedLookupClass == this.lookupClass)
 821                 return this;  // keep same capabilities
 822             int newModes = (allowedModes & FULL_POWER_MODES);
 823             if (!VerifyAccess.isSameModule(this.lookupClass, requestedLookupClass)) {
 824                 // Need to drop all access when teleporting from a named module to another
 825                 // module. The exception is publicLookup where PUBLIC is not lost.
 826                 if (this.lookupClass.getModule().isNamed()
 827                     && (this.allowedModes & UNCONDITIONAL) == 0)
 828                     newModes = 0;
 829                 else
 830                     newModes &= ~(MODULE|PACKAGE|PRIVATE|PROTECTED);
 831             }
 832             if ((newModes & PACKAGE) != 0
 833                 && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) {
 834                 newModes &= ~(PACKAGE|PRIVATE|PROTECTED);
 835             }
 836             // Allow nestmate lookups to be created without special privilege:
 837             if ((newModes & PRIVATE) != 0
 838                 && !Reflection.areNestMates(this.lookupClass, requestedLookupClass)) {
 839                 newModes &= ~(PRIVATE|PROTECTED);
 840             }
 841             if ((newModes & PUBLIC) != 0
 842                 && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass, allowedModes)) {
 843                 // The requested class it not accessible from the lookup class.
 844                 // No permissions.
 845                 newModes = 0;
 846             }
 847 
 848             checkUnprivilegedlookupClass(requestedLookupClass);
 849             return new Lookup(requestedLookupClass, newModes);
 850         }
 851 
 852 
 853         /**
 854          * Creates a lookup on the same lookup class which this lookup object
 855          * finds members, but with a lookup mode that has lost the given lookup mode.
 856          * The lookup mode to drop is one of {@link #PUBLIC PUBLIC}, {@link #MODULE
 857          * MODULE}, {@link #PACKAGE PACKAGE}, {@link #PROTECTED PROTECTED} or {@link #PRIVATE PRIVATE}.
 858          * {@link #PROTECTED PROTECTED} and {@link #UNCONDITIONAL UNCONDITIONAL} are always


2199             // check the class first:
2200             boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
2201                                (defc == refc ||
2202                                 Modifier.isPublic(refc.getModifiers())));
2203             if (!classOK && (allowedModes & PACKAGE) != 0) {
2204                 classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), FULL_POWER_MODES) &&
2205                            (defc == refc ||
2206                             VerifyAccess.isClassAccessible(refc, lookupClass(), FULL_POWER_MODES)));
2207             }
2208             if (!classOK)
2209                 return "class is not public";
2210             if (Modifier.isPublic(mods))
2211                 return "access to public member failed";  // (how?, module not readable?)
2212             if (Modifier.isPrivate(mods))
2213                 return "member is private";
2214             if (Modifier.isProtected(mods))
2215                 return "member is protected";
2216             return "member is private to package";
2217         }
2218 


2219         private void checkSpecialCaller(Class<?> specialCaller, Class<?> refc) throws IllegalAccessException {
2220             int allowedModes = this.allowedModes;
2221             if (allowedModes == TRUSTED)  return;
2222             if (!hasPrivateAccess()
2223                 || (specialCaller != lookupClass()
2224                        // ensure non-abstract methods in superinterfaces can be special-invoked
2225                     && !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))))


2226                 throw new MemberName(specialCaller).
2227                     makeAccessException("no private access for invokespecial", this);
2228         }
2229 
2230         private boolean restrictProtectedReceiver(MemberName method) {
2231             // The accessing class only has the right to use a protected member
2232             // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
2233             if (!method.isProtected() || method.isStatic()
2234                 || allowedModes == TRUSTED
2235                 || method.getDeclaringClass() == lookupClass()
2236                 || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass()))


2237                 return false;
2238             return true;
2239         }
2240         private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, Class<?> caller) throws IllegalAccessException {
2241             assert(!method.isStatic());
2242             // receiver type of mh is too wide; narrow to caller
2243             if (!method.getDeclaringClass().isAssignableFrom(caller)) {
2244                 throw method.makeAccessException("caller class must be a subclass below the method", caller);
2245             }
2246             MethodType rawType = mh.type();
2247             if (caller.isAssignableFrom(rawType.parameterType(0))) return mh; // no need to restrict; already narrow
2248             MethodType narrowType = rawType.changeParameterType(0, caller);
2249             assert(!mh.isVarargsCollector());  // viewAsType will lose varargs-ness
2250             assert(mh.viewAsTypeChecks(narrowType, true));
2251             return mh.copyWith(narrowType, mh.form);
2252         }
2253 
2254         /** Check access and get the requested method. */
2255         private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
2256             final boolean doRestrict    = true;


< prev index next >