219 if (!jdk.internal.misc.VM.isModuleSystemInited())
220 return true;
221 }
222
223 // public class not accessible to lookupClass
224 return false;
225 }
226 if ((allowedModes & PACKAGE_ALLOWED) != 0 &&
227 isSamePackage(lookupClass, refc))
228 return true;
229 return false;
230 }
231
232 /**
233 * Decide if the given method type, attributed to a member or symbolic
234 * reference of a given reference class, is really visible to that class.
235 * @param type the supposed type of a member or symbolic reference of refc
236 * @param refc the class attempting to make the reference
237 */
238 public static boolean isTypeVisible(Class<?> type, Class<?> refc) {
239 if (type.asBoxType() == refc.asBoxType()) {
240 return true; // easy check
241 }
242 while (type.isArray()) type = type.getComponentType();
243 if (type.isPrimitive() || type == Object.class) {
244 return true;
245 }
246 ClassLoader typeLoader = type.getClassLoader();
247 ClassLoader refcLoader = refc.getClassLoader();
248 if (typeLoader == refcLoader) {
249 return true;
250 }
251 if (refcLoader == null && typeLoader != null) {
252 return false;
253 }
254 if (typeLoader == null && type.getName().startsWith("java.")) {
255 // Note: The API for actually loading classes, ClassLoader.defineClass,
256 // guarantees that classes with names beginning "java." cannot be aliased,
257 // because class loaders cannot load them directly.
258 return true;
259 }
267 // This would be wasted effort, but it is expected to be very rare, occurring
268 // only when an attacker is attempting to create a type alias.
269 // In the normal case, one class loader will simply delegate to the other,
270 // and the same type will be visible through both, with no extra loading.
271 //
272 // It is important to go through Class.forName instead of ClassLoader.loadClass
273 // because Class.forName goes through the JVM system dictionary, which records
274 // the class lookup once for all. This means that even if a not-well-behaved class loader
275 // would "change its mind" about the meaning of the name, the Class.forName request
276 // will use the result cached in the JVM system dictionary. Note that the JVM system dictionary
277 // will record the first successful result. Unsuccessful results are not stored.
278 //
279 // We use doPrivileged in order to allow an unprivileged caller to ask an arbitrary
280 // class loader about the binding of the proposed name (type.getName()).
281 // The looked up type ("res") is compared for equality against the proposed
282 // type ("type") and then is discarded. Thus, the worst that can happen to
283 // the "child" class loader is that it is bothered to load and report a class
284 // that differs from "type"; this happens once due to JVM system dictionary
285 // memoization. And the caller never gets to look at the alternate type binding
286 // ("res"), whether it exists or not.
287 final String name = type.getName();
288 Class<?> res = java.security.AccessController.doPrivileged(
289 new java.security.PrivilegedAction<>() {
290 public Class<?> run() {
291 try {
292 return Class.forName(name, false, refcLoader);
293 } catch (ClassNotFoundException | LinkageError e) {
294 return null; // Assume the class is not found
295 }
296 }
297 });
298 return (type.asBoxType() == res);
299 }
300
301 /**
302 * Decide if the given method type, attributed to a member or symbolic
303 * reference of a given reference class, is really visible to that class.
304 * @param type the supposed type of a member or symbolic reference of refc
305 * @param refc the class attempting to make the reference
306 */
307 public static boolean isTypeVisible(java.lang.invoke.MethodType type, Class<?> refc) {
308 if (!isTypeVisible(type.returnType(), refc)) {
309 return false;
310 }
311 for (int n = 0, max = type.parameterCount(); n < max; n++) {
312 if (!isTypeVisible(type.parameterType(n), refc)) {
313 return false;
314 }
315 }
316 return true;
317 }
318
|
219 if (!jdk.internal.misc.VM.isModuleSystemInited())
220 return true;
221 }
222
223 // public class not accessible to lookupClass
224 return false;
225 }
226 if ((allowedModes & PACKAGE_ALLOWED) != 0 &&
227 isSamePackage(lookupClass, refc))
228 return true;
229 return false;
230 }
231
232 /**
233 * Decide if the given method type, attributed to a member or symbolic
234 * reference of a given reference class, is really visible to that class.
235 * @param type the supposed type of a member or symbolic reference of refc
236 * @param refc the class attempting to make the reference
237 */
238 public static boolean isTypeVisible(Class<?> type, Class<?> refc) {
239 if (type.asNullableType() == refc.asNullableType()) {
240 return true; // easy check
241 }
242 while (type.isArray()) type = type.getComponentType();
243 if (type.isPrimitive() || type == Object.class) {
244 return true;
245 }
246 ClassLoader typeLoader = type.getClassLoader();
247 ClassLoader refcLoader = refc.getClassLoader();
248 if (typeLoader == refcLoader) {
249 return true;
250 }
251 if (refcLoader == null && typeLoader != null) {
252 return false;
253 }
254 if (typeLoader == null && type.getName().startsWith("java.")) {
255 // Note: The API for actually loading classes, ClassLoader.defineClass,
256 // guarantees that classes with names beginning "java." cannot be aliased,
257 // because class loaders cannot load them directly.
258 return true;
259 }
267 // This would be wasted effort, but it is expected to be very rare, occurring
268 // only when an attacker is attempting to create a type alias.
269 // In the normal case, one class loader will simply delegate to the other,
270 // and the same type will be visible through both, with no extra loading.
271 //
272 // It is important to go through Class.forName instead of ClassLoader.loadClass
273 // because Class.forName goes through the JVM system dictionary, which records
274 // the class lookup once for all. This means that even if a not-well-behaved class loader
275 // would "change its mind" about the meaning of the name, the Class.forName request
276 // will use the result cached in the JVM system dictionary. Note that the JVM system dictionary
277 // will record the first successful result. Unsuccessful results are not stored.
278 //
279 // We use doPrivileged in order to allow an unprivileged caller to ask an arbitrary
280 // class loader about the binding of the proposed name (type.getName()).
281 // The looked up type ("res") is compared for equality against the proposed
282 // type ("type") and then is discarded. Thus, the worst that can happen to
283 // the "child" class loader is that it is bothered to load and report a class
284 // that differs from "type"; this happens once due to JVM system dictionary
285 // memoization. And the caller never gets to look at the alternate type binding
286 // ("res"), whether it exists or not.
287
288 if (type.isInlineClass()) {
289 type = type.asPrimaryType();
290 }
291 final String name = type.getName();
292 Class<?> res = java.security.AccessController.doPrivileged(
293 new java.security.PrivilegedAction<>() {
294 public Class<?> run() {
295 try {
296 return Class.forName(name, false, refcLoader);
297 } catch (ClassNotFoundException | LinkageError e) {
298 return null; // Assume the class is not found
299 }
300 }
301 });
302 return (type == res);
303 }
304
305 /**
306 * Decide if the given method type, attributed to a member or symbolic
307 * reference of a given reference class, is really visible to that class.
308 * @param type the supposed type of a member or symbolic reference of refc
309 * @param refc the class attempting to make the reference
310 */
311 public static boolean isTypeVisible(java.lang.invoke.MethodType type, Class<?> refc) {
312 if (!isTypeVisible(type.returnType(), refc)) {
313 return false;
314 }
315 for (int n = 0, max = type.parameterCount(); n < max; n++) {
316 if (!isTypeVisible(type.parameterType(n), refc)) {
317 return false;
318 }
319 }
320 return true;
321 }
322
|