< prev index next >

test/jdk/java/lang/invoke/AccessControlTest.java

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. --- 1,7 ---- /* ! * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.
*** 31,41 **** import java.lang.invoke.*; import java.lang.reflect.*; import java.lang.reflect.Modifier; import java.util.*; - import org.testng.*; import org.testng.annotations.*; import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodHandles.Lookup.*; import static java.lang.invoke.MethodType.*; --- 31,40 ----
*** 60,109 **** } private class LookupCase implements Comparable<LookupCase> { final Lookup lookup; final Class<?> lookupClass; final int lookupModes; public LookupCase(Lookup lookup) { this.lookup = lookup; this.lookupClass = lookup.lookupClass(); this.lookupModes = lookup.lookupModes(); assert(lookupString().equals(lookup.toString())); numberOf(lookupClass().getClassLoader()); // assign CL# } ! public LookupCase(Class<?> lookupClass, int lookupModes) { this.lookup = null; this.lookupClass = lookupClass; this.lookupModes = lookupModes; numberOf(lookupClass().getClassLoader()); // assign CL# } public final Class<?> lookupClass() { return lookupClass; } public final int lookupModes() { return lookupModes; } public Lookup lookup() { lookup.getClass(); return lookup; } @Override public int compareTo(LookupCase that) { Class<?> c1 = this.lookupClass(); Class<?> c2 = that.lookupClass(); if (c1 != c2) { int cmp = c1.getName().compareTo(c2.getName()); if (cmp != 0) return cmp; cmp = numberOf(c1.getClassLoader()) - numberOf(c2.getClassLoader()); assert(cmp != 0); return cmp; } return -(this.lookupModes() - that.lookupModes()); } @Override public boolean equals(Object that) { return (that instanceof LookupCase && equals((LookupCase)that)); } public boolean equals(LookupCase that) { return (this.lookupClass() == that.lookupClass() && this.lookupModes() == that.lookupModes()); } @Override public int hashCode() { --- 59,126 ---- } private class LookupCase implements Comparable<LookupCase> { final Lookup lookup; final Class<?> lookupClass; + final Class<?> prevLookupClass; final int lookupModes; public LookupCase(Lookup lookup) { this.lookup = lookup; this.lookupClass = lookup.lookupClass(); + this.prevLookupClass = lookup.previousLookupClass(); this.lookupModes = lookup.lookupModes(); + assert(lookupString().equals(lookup.toString())); numberOf(lookupClass().getClassLoader()); // assign CL# } ! public LookupCase(Class<?> lookupClass, Class<?> prevLookupClass, int lookupModes) { this.lookup = null; this.lookupClass = lookupClass; + this.prevLookupClass = prevLookupClass; this.lookupModes = lookupModes; numberOf(lookupClass().getClassLoader()); // assign CL# } public final Class<?> lookupClass() { return lookupClass; } + public final Class<?> prevLookupClass() { return prevLookupClass; } public final int lookupModes() { return lookupModes; } public Lookup lookup() { lookup.getClass(); return lookup; } @Override public int compareTo(LookupCase that) { Class<?> c1 = this.lookupClass(); Class<?> c2 = that.lookupClass(); + Class<?> p1 = this.prevLookupClass(); + Class<?> p2 = that.prevLookupClass(); if (c1 != c2) { int cmp = c1.getName().compareTo(c2.getName()); if (cmp != 0) return cmp; cmp = numberOf(c1.getClassLoader()) - numberOf(c2.getClassLoader()); assert(cmp != 0); return cmp; + } else if (p1 != p2){ + if (p1 == null) + return 1; + else if (p2 == null) + return -1; + int cmp = p1.getName().compareTo(p2.getName()); + if (cmp != 0) return cmp; + cmp = numberOf(p1.getClassLoader()) - numberOf(p2.getClassLoader()); + assert(cmp != 0); + return cmp; } return -(this.lookupModes() - that.lookupModes()); } @Override public boolean equals(Object that) { return (that instanceof LookupCase && equals((LookupCase)that)); } public boolean equals(LookupCase that) { return (this.lookupClass() == that.lookupClass() && + this.prevLookupClass() == that.prevLookupClass() && this.lookupModes() == that.lookupModes()); } @Override public int hashCode() {
*** 111,134 **** } /** Simulate all assertions in the spec. for Lookup.toString. */ private String lookupString() { String name = lookupClass.getName(); String suffix = ""; if (lookupModes == 0) suffix = "/noaccess"; else if (lookupModes == PUBLIC) suffix = "/public"; ! else if (lookupModes == (PUBLIC|UNCONDITIONAL)) suffix = "/publicLookup"; else if (lookupModes == (PUBLIC|MODULE)) suffix = "/module"; ! else if (lookupModes == (PUBLIC|MODULE|PACKAGE)) suffix = "/package"; ! else if (lookupModes == (PUBLIC|MODULE|PACKAGE|PRIVATE)) suffix = "/private"; ! else if (lookupModes == (PUBLIC|MODULE|PACKAGE|PRIVATE|PROTECTED)) suffix = ""; else suffix = "/#"+Integer.toHexString(lookupModes); return name+suffix; } --- 128,156 ---- } /** Simulate all assertions in the spec. for Lookup.toString. */ private String lookupString() { String name = lookupClass.getName(); + if (prevLookupClass != null) + name += "/" + prevLookupClass.getName(); String suffix = ""; if (lookupModes == 0) suffix = "/noaccess"; else if (lookupModes == PUBLIC) suffix = "/public"; ! else if (lookupModes == UNCONDITIONAL) suffix = "/publicLookup"; else if (lookupModes == (PUBLIC|MODULE)) suffix = "/module"; ! else if (lookupModes == (PUBLIC|PACKAGE) ! || lookupModes == (PUBLIC|MODULE|PACKAGE)) suffix = "/package"; ! else if (lookupModes == (PUBLIC|PACKAGE|PRIVATE) ! || lookupModes == (PUBLIC|MODULE|PACKAGE|PRIVATE)) suffix = "/private"; ! else if (lookupModes == (PUBLIC|PACKAGE|PRIVATE|PROTECTED) ! || lookupModes == (PUBLIC|MODULE|PACKAGE|PRIVATE|PROTECTED)) suffix = ""; else suffix = "/#"+Integer.toHexString(lookupModes); return name+suffix; }
*** 136,221 **** /** Simulate all assertions from the spec. for Lookup.in: * <hr> * Creates a lookup on the specified new lookup class. * [A1] The resulting object will report the specified * class as its own {@link #lookupClass lookupClass}. - * <p> * [A2] However, the resulting {@code Lookup} object is guaranteed * to have no more access capabilities than the original. * In particular, access capabilities can be lost as follows:<ul> ! * <li> [A3] If the old lookup class is in a named module, and the new ! * lookup class is in a different module {@code M}, then no members, not ! * even public members in {@code M}'s exported packages, will be accessible. ! * The exception to this is when this lookup is publicLookup, in which case ! * public access is not lost. ! * <li> [A4] If the old lookup class is in an unnamed module, and the new ! * lookup class is a different module then module access is lost. ! * <li> [A5] If the new lookup class differs from the old one then UNCONDITIONAL ! * is lost. If the new lookup class is not within the same package member as the ! * old one, protected members will not be accessible by virtue of inheritance. * (Protected members may continue to be accessible because of package sharing.) ! * <li> [A6] If the new lookup class is in a different package than the old one, ! * protected and default (package) members will not be accessible. ! * <li> [A7] If the new lookup class is not within the same package member ! * as the old one, private members will not be accessible. ! * <li> [A8] If the new lookup class is not accessible to the old lookup class, ! * then no members, not even public members, will be accessible. ! * <li> [A9] (In all other cases, public members will continue to be accessible.) ! * </ul> * Other than the above cases, the new lookup will have the same ! * access capabilities as the original. [A10] * <hr> */ public LookupCase in(Class<?> c2) { Class<?> c1 = lookupClass(); ! int m1 = lookupModes(); int changed = 0; // for the purposes of access control then treat classes in different unnamed // modules as being in the same module. ! boolean sameModule = (c1.getModule() == c2.getModule()) || ! (!c1.getModule().isNamed() && !c2.getModule().isNamed()); boolean samePackage = (c1.getClassLoader() == c2.getClassLoader() && c1.getPackageName().equals(c2.getPackageName())); boolean sameTopLevel = (topLevelClass(c1) == topLevelClass(c2)); boolean sameClass = (c1 == c2); assert(samePackage || !sameTopLevel); assert(sameTopLevel || !sameClass); boolean accessible = sameClass; ! if ((m1 & PACKAGE) != 0) accessible |= samePackage; ! if ((m1 & PUBLIC ) != 0) accessible |= (c2.getModifiers() & PUBLIC) != 0; ! if (!sameModule) { ! if (c1.getModule().isNamed() && (m1 & UNCONDITIONAL) == 0) { ! accessible = false; // [A3] ! } else { ! changed |= (MODULE|PACKAGE|PRIVATE|PROTECTED); // [A3] [A4] } } if (!accessible) { ! // Different package and no access to c2; lose all access. ! changed |= (PUBLIC|MODULE|PACKAGE|PRIVATE|PROTECTED); // [A8] } if (!samePackage) { // Different package; loose PACKAGE and lower access. ! changed |= (PACKAGE|PRIVATE|PROTECTED); // [A6] } if (!sameTopLevel) { // Different top-level class. Lose PRIVATE and PROTECTED access. ! changed |= (PRIVATE|PROTECTED); // [A5] [A7] } ! if (!sameClass) { ! changed |= (UNCONDITIONAL); // [A5] ! } else { ! assert(changed == 0); // [A10] (no deprivation if same class) } ! if (accessible) assert((changed & PUBLIC) == 0); // [A9] ! int m2 = m1 & ~changed; ! LookupCase l2 = new LookupCase(c2, m2); assert(l2.lookupClass() == c2); // [A1] ! assert((m1 | m2) == m1); // [A2] (no elevation of access) return l2; } @Override public String toString() { String s = lookupClass().getSimpleName(); String lstr = lookupString(); int sl = lstr.indexOf('/'); --- 158,297 ---- /** Simulate all assertions from the spec. for Lookup.in: * <hr> * Creates a lookup on the specified new lookup class. * [A1] The resulting object will report the specified * class as its own {@link #lookupClass lookupClass}. * [A2] However, the resulting {@code Lookup} object is guaranteed * to have no more access capabilities than the original. * In particular, access capabilities can be lost as follows:<ul> ! * [A3] If the new lookup class is in a different module from the old one, ! * i.e. {@link #MODULE MODULE} access is lost. ! * [A4] If the new lookup class is in a different package ! * than the old one, protected and default (package) members will not be accessible, ! * i.e. {@link #PROTECTED PROTECTED} and {@link #PACKAGE PACKAGE} access are lost. ! * [A5] If the new lookup class is not within the same package member ! * as the old one, private members will not be accessible, and protected members ! * will not be accessible by virtue of inheritance, ! * i.e. {@link #PRIVATE PRIVATE} access is lost. * (Protected members may continue to be accessible because of package sharing.) ! * [A6] If the new lookup class is not ! * {@linkplain #accessClass(Class) accessible} to this lookup, ! * then no members, not even public members, will be accessible ! * i.e. all access modes are lost. ! * [A7] If the new lookup class, the old lookup class and the previous lookup class ! * are all in different modules i.e. teleporting to a third module, ! * all access modes are lost. ! * <p> ! * The new previous lookup class is chosen as follows: ! * [A8] If the new lookup object has {@link #UNCONDITIONAL UNCONDITIONAL} bit, ! * the new previous lookup class is {@code null}. ! * [A9] If the new lookup class is in the same module as the old lookup class, ! * the new previous lookup class is the old previous lookup class. ! * [A10] If the new lookup class is in a different module from the old lookup class, ! * the new previous lookup class is the the old lookup class. ! * * Other than the above cases, the new lookup will have the same ! * access capabilities as the original. [A11] * <hr> */ public LookupCase in(Class<?> c2) { Class<?> c1 = lookupClass(); ! Module m1 = c1.getModule(); ! Module m2 = c2.getModule(); ! Module m0 = prevLookupClass() != null ? prevLookupClass.getModule() : c1.getModule(); ! int modes1 = lookupModes(); int changed = 0; // for the purposes of access control then treat classes in different unnamed // modules as being in the same module. ! boolean sameModule = (m1 == m2) || ! (!m1.isNamed() && !m2.isNamed()); boolean samePackage = (c1.getClassLoader() == c2.getClassLoader() && c1.getPackageName().equals(c2.getPackageName())); boolean sameTopLevel = (topLevelClass(c1) == topLevelClass(c2)); boolean sameClass = (c1 == c2); assert(samePackage || !sameTopLevel); assert(sameTopLevel || !sameClass); boolean accessible = sameClass; ! ! if ((modes1 & PACKAGE) != 0) accessible |= samePackage; ! if ((modes1 & PUBLIC ) != 0) { ! if (isModuleAccessible(c2)) ! accessible |= (c2.getModifiers() & PUBLIC) != 0; ! else ! accessible = false; } + if ((modes1 & UNCONDITIONAL) != 0) { + if (m2.isExported(c2.getPackageName())) + accessible |= (c2.getModifiers() & PUBLIC) != 0; + else + accessible = false; } if (!accessible) { ! // no access to c2; lose all access. ! changed |= (PUBLIC|MODULE|PACKAGE|PRIVATE|PROTECTED|UNCONDITIONAL); // [A6] ! } ! if (m2 != m1 && m0 != m1) { ! // hop to a third module; lose all access ! changed |= (PUBLIC|MODULE|PACKAGE|PRIVATE|PROTECTED); // [A7] ! } ! if (!sameModule) { ! changed |= MODULE; // [A3] } if (!samePackage) { // Different package; loose PACKAGE and lower access. ! changed |= (PACKAGE|PRIVATE|PROTECTED); // [A4] } if (!sameTopLevel) { // Different top-level class. Lose PRIVATE and PROTECTED access. ! changed |= (PRIVATE|PROTECTED); // [A5] } ! if (sameClass) { ! assert(changed == 0); // [A11] (no deprivation if same class) } ! ! if (accessible) assert((changed & PUBLIC) == 0); ! int modes2 = modes1 & ~changed; ! Class<?> plc = (m1 == m2) ? prevLookupClass() : c1; // [A9] [A10] ! if ((modes1 & UNCONDITIONAL) != 0) plc = null; // [A8] ! LookupCase l2 = new LookupCase(c2, plc, modes2); assert(l2.lookupClass() == c2); // [A1] ! assert((modes1 | modes2) == modes1); // [A2] (no elevation of access) ! assert(l2.prevLookupClass() == null || (modes2 & MODULE) == 0); return l2; } + LookupCase dropLookupMode(int modeToDrop) { + int oldModes = lookupModes(); + int newModes = oldModes & ~(modeToDrop | PROTECTED); + switch (modeToDrop) { + case PUBLIC: newModes &= ~(MODULE|PACKAGE|PROTECTED|PRIVATE); break; + case MODULE: newModes &= ~(PACKAGE|PRIVATE); break; + case PACKAGE: newModes &= ~(PRIVATE); break; + case PROTECTED: + case PRIVATE: + case UNCONDITIONAL: break; + default: throw new IllegalArgumentException(modeToDrop + " is not a valid mode to drop"); + } + if (newModes == oldModes) return this; // return self if no change + LookupCase l2 = new LookupCase(lookupClass(), prevLookupClass(), newModes); + assert((oldModes | newModes) == oldModes); // [A2] (no elevation of access) + assert(l2.prevLookupClass() == null || (newModes & MODULE) == 0); + return l2; + } + + boolean isModuleAccessible(Class<?> c) { + Module m1 = lookupClass().getModule(); + Module m2 = c.getModule(); + Module m0 = prevLookupClass() != null ? prevLookupClass.getModule() : m1; + String pn = c.getPackageName(); + boolean accessible = m1.canRead(m2) && m2.isExported(pn, m1); + if (m1 != m0) { + accessible = accessible && m0.canRead(m2) && m2.isExported(pn, m0); + } + return accessible; + } + @Override public String toString() { String s = lookupClass().getSimpleName(); String lstr = lookupString(); int sl = lstr.indexOf('/');
*** 227,263 **** /** Predict the success or failure of accessing this method. */ public boolean willAccess(Method m) { Class<?> c1 = lookupClass(); Class<?> c2 = m.getDeclaringClass(); ! // publicLookup has access to all public types/members of types in unnamed modules ! if ((lookupModes & UNCONDITIONAL) != 0 ! && (lookupModes & PUBLIC) != 0 ! && !c2.getModule().isNamed() && Modifier.isPublic(c2.getModifiers()) ! && Modifier.isPublic(m.getModifiers())) ! return true; LookupCase lc = this.in(c2); ! int m1 = lc.lookupModes(); ! int m2 = fixMods(m.getModifiers()); // allow private lookup on nestmates. Otherwise, privacy is strictly enforced ! if (c1 != c2 && ((m2 & PRIVATE) == 0 || !c1.isNestmateOf(c2))) { ! m1 &= ~PRIVATE; } // protected access is sometimes allowed ! if ((m2 & PROTECTED) != 0) { ! int prev = m2; ! m2 |= PACKAGE; // it acts like a package method also if ((lookupModes() & PROTECTED) != 0 && c2.isAssignableFrom(c1)) ! m2 |= PUBLIC; // from a subclass, it acts like a public method also } if (verbosity >= 2) ! System.out.format("%s willAccess %s m1=0x%h m2=0x%h => %s%n", this, lc, m1, m2, ((m2 & m1) != 0)); ! return (m2 & m1) != 0; } /** Predict the success or failure of accessing this class. */ public boolean willAccessClass(Class<?> c2, boolean load) { Class<?> c1 = lookupClass(); --- 303,354 ---- /** Predict the success or failure of accessing this method. */ public boolean willAccess(Method m) { Class<?> c1 = lookupClass(); Class<?> c2 = m.getDeclaringClass(); + Module m1 = c1.getModule(); + Module m2 = c2.getModule(); + Module m0 = prevLookupClass != null ? prevLookupClass.getModule() : m1; + // unconditional has access to all public types/members of types that is in a package + // are unconditionally exported + if ((lookupModes & UNCONDITIONAL) != 0) { + return m2.isExported(c2.getPackageName()) + && Modifier.isPublic(c2.getModifiers()) + && Modifier.isPublic(m.getModifiers()); + } ! // c1 and c2 are in different module ! if (m1 != m2 || m0 != m2) { ! return (lookupModes & PUBLIC) != 0 ! && isModuleAccessible(c2) && Modifier.isPublic(c2.getModifiers()) ! && Modifier.isPublic(m.getModifiers()); ! } ! ! assert(m1 == m2 && prevLookupClass == null); ! ! if (!willAccessClass(c2, false)) ! return false; LookupCase lc = this.in(c2); ! int modes1 = lc.lookupModes(); ! int modes2 = fixMods(m.getModifiers()); // allow private lookup on nestmates. Otherwise, privacy is strictly enforced ! if (c1 != c2 && ((modes2 & PRIVATE) == 0 || !c1.isNestmateOf(c2))) { ! modes1 &= ~PRIVATE; } // protected access is sometimes allowed ! if ((modes2 & PROTECTED) != 0) { ! int prev = modes2; ! modes2 |= PACKAGE; // it acts like a package method also if ((lookupModes() & PROTECTED) != 0 && c2.isAssignableFrom(c1)) ! modes2 |= PUBLIC; // from a subclass, it acts like a public method also } if (verbosity >= 2) ! System.out.format("%s willAccess %s modes1=0x%h modes2=0x%h => %s%n", lookupString(), lc.lookupString(), modes1, modes2, (modes2 & modes1) != 0); ! return (modes2 & modes1) != 0; } /** Predict the success or failure of accessing this class. */ public boolean willAccessClass(Class<?> c2, boolean load) { Class<?> c1 = lookupClass();
*** 266,292 **** // not visible return false; } } ! // publicLookup has access to all public types/members of types in unnamed modules ! if ((lookupModes & UNCONDITIONAL) != 0 ! && (lookupModes & PUBLIC) != 0 ! && (!c2.getModule().isNamed()) ! && Modifier.isPublic(c2.getModifiers())) ! return true; LookupCase lc = this.in(c2); ! int m1 = lc.lookupModes(); boolean r = false; ! if (m1 == 0) { r = false; } else { ! int m2 = fixMods(c2.getModifiers()); ! if ((m2 & PUBLIC) != 0) { r = true; ! } else if ((m1 & PACKAGE) != 0 && c1.getPackage() == c2.getPackage()) { r = true; } } if (verbosity >= 2) { System.out.println(this+" willAccessClass "+lc+" c1="+c1+" c2="+c2+" => "+r); --- 357,395 ---- // not visible return false; } } ! Module m1 = c1.getModule(); ! Module m2 = c2.getModule(); ! Module m0 = prevLookupClass != null ? prevLookupClass.getModule() : m1; ! // unconditional has access to all public types that is in an unconditionally exported package ! if ((lookupModes & UNCONDITIONAL) != 0) { ! return m2.isExported(c2.getPackageName()) && Modifier.isPublic(c2.getModifiers()); ! } ! // c1 and c2 are in different module ! if (m1 != m2 || m0 != m2) { ! return (lookupModes & PUBLIC) != 0 ! && isModuleAccessible(c2) ! && Modifier.isPublic(c2.getModifiers()); ! } ! ! assert(m1 == m2 && prevLookupClass == null); LookupCase lc = this.in(c2); ! int modes1 = lc.lookupModes(); boolean r = false; ! if (modes1 == 0) { r = false; } else { ! if (Modifier.isPublic(c2.getModifiers())) { ! if ((modes1 & MODULE) != 0) r = true; ! else if ((modes1 & PUBLIC) != 0) ! r = m1.isExported(c2.getPackageName()); ! } else { ! if ((modes1 & PACKAGE) != 0 && c1.getPackage() == c2.getPackage()) r = true; } } if (verbosity >= 2) { System.out.println(this+" willAccessClass "+lc+" c1="+c1+" c2="+c2+" => "+r);
*** 326,345 **** LOADERS.add(cl); } return i+1; } ! private void addLookupEdge(LookupCase l1, Class<?> c2, LookupCase l2) { TreeSet<LookupCase> edges = CASE_EDGES.get(l2); if (edges == null) CASE_EDGES.put(l2, edges = new TreeSet<>()); if (edges.add(l1)) { Class<?> c1 = l1.lookupClass(); assert(l2.lookupClass() == c2); // [A1] int m1 = l1.lookupModes(); int m2 = l2.lookupModes(); assert((m1 | m2) == m1); // [A2] (no elevation of access) ! LookupCase expect = l1.in(c2); if (!expect.equals(l2)) System.out.println("*** expect "+l1+" => "+expect+" but got "+l2); assertEquals(l2, expect); } } --- 429,448 ---- LOADERS.add(cl); } return i+1; } ! private void addLookupEdge(LookupCase l1, Class<?> c2, LookupCase l2, int dropAccess) { TreeSet<LookupCase> edges = CASE_EDGES.get(l2); if (edges == null) CASE_EDGES.put(l2, edges = new TreeSet<>()); if (edges.add(l1)) { Class<?> c1 = l1.lookupClass(); assert(l2.lookupClass() == c2); // [A1] int m1 = l1.lookupModes(); int m2 = l2.lookupModes(); assert((m1 | m2) == m1); // [A2] (no elevation of access) ! LookupCase expect = dropAccess == 0 ? l1.in(c2) : l1.in(c2).dropLookupMode(dropAccess); if (!expect.equals(l2)) System.out.println("*** expect "+l1+" => "+expect+" but got "+l2); assertEquals(l2, expect); } }
*** 356,368 **** System.out.println("loaders = "+LOADERS); int rounds = 0; for (int lastCount = -1; lastCount != CASES.size(); ) { lastCount = CASES.size(); // if CASES grow in the loop we go round again for (LookupCase lc1 : CASES.toArray(new LookupCase[0])) { for (Class<?> c2 : classes) { LookupCase lc2 = new LookupCase(lc1.lookup().in(c2)); ! addLookupEdge(lc1, c2, lc2); CASES.add(lc2); } } rounds++; } --- 459,476 ---- System.out.println("loaders = "+LOADERS); int rounds = 0; for (int lastCount = -1; lastCount != CASES.size(); ) { lastCount = CASES.size(); // if CASES grow in the loop we go round again for (LookupCase lc1 : CASES.toArray(new LookupCase[0])) { + for (int mode : ACCESS_CASES) { + LookupCase lc2 = new LookupCase(lc1.lookup().dropLookupMode(mode)); + addLookupEdge(lc1, lc1.lookupClass(), lc2, mode); + CASES.add(lc2); + } for (Class<?> c2 : classes) { LookupCase lc2 = new LookupCase(lc1.lookup().in(c2)); ! addLookupEdge(lc1, c2, lc2, 0); CASES.add(lc2); } } rounds++; }
*** 384,405 **** @Test public void test() { makeCases(lookups()); if (verbosity > 0) { verbosity += 9; Method pro_in_self = targetMethod(THIS_CLASS, PROTECTED, methodType(void.class)); ! testOneAccess(lookupCase("AccessControlTest/public"), pro_in_self, "find"); ! testOneAccess(lookupCase("Remote_subclass/public"), pro_in_self, "find"); testOneAccess(lookupCase("Remote_subclass"), pro_in_self, "find"); verbosity -= 9; } Set<Class<?>> targetClassesDone = new HashSet<>(); for (LookupCase targetCase : CASES) { Class<?> targetClass = targetCase.lookupClass(); if (!targetClassesDone.add(targetClass)) continue; // already saw this one String targetPlace = placeName(targetClass); if (targetPlace == null) continue; // Object, String, not a target for (int targetAccess : ACCESS_CASES) { MethodType methodType = methodType(void.class); Method method = targetMethod(targetClass, targetAccess, methodType); // Try to access target method from various contexts. for (LookupCase sourceCase : CASES) { testOneAccess(sourceCase, method, "findClass"); --- 492,515 ---- @Test public void test() { makeCases(lookups()); if (verbosity > 0) { verbosity += 9; Method pro_in_self = targetMethod(THIS_CLASS, PROTECTED, methodType(void.class)); ! testOneAccess(lookupCase("AccessControlTest/module"), pro_in_self, "find"); ! testOneAccess(lookupCase("Remote_subclass/module"), pro_in_self, "find"); testOneAccess(lookupCase("Remote_subclass"), pro_in_self, "find"); verbosity -= 9; } Set<Class<?>> targetClassesDone = new HashSet<>(); for (LookupCase targetCase : CASES) { Class<?> targetClass = targetCase.lookupClass(); if (!targetClassesDone.add(targetClass)) continue; // already saw this one String targetPlace = placeName(targetClass); if (targetPlace == null) continue; // Object, String, not a target for (int targetAccess : ACCESS_CASES) { + if (targetAccess == MODULE || targetAccess == UNCONDITIONAL) + continue; MethodType methodType = methodType(void.class); Method method = targetMethod(targetClass, targetAccess, methodType); // Try to access target method from various contexts. for (LookupCase sourceCase : CASES) { testOneAccess(sourceCase, method, "findClass");
*** 455,465 **** testCount++; if (!didAccess) testCountFails++; } static Method targetMethod(Class<?> targetClass, int targetAccess, MethodType methodType) { - assert targetAccess != MODULE; String methodName = accessName(targetAccess)+placeName(targetClass); if (verbosity >= 2) System.out.println(targetClass.getSimpleName()+"."+methodName+methodType); try { Method method = targetClass.getDeclaredMethod(methodName, methodType.parameterArray()); --- 565,574 ----
*** 489,502 **** case PRIVATE: return "pri_in_"; } assert(false); return "?"; } - // MODULE not a test case at this time private static final int[] ACCESS_CASES = { ! PUBLIC, PACKAGE, PRIVATE, PROTECTED }; /** Return one of the ACCESS_CASES. */ static int fixMods(int mods) { mods &= (PUBLIC|PRIVATE|PROTECTED); switch (mods) { case PUBLIC: case PRIVATE: case PROTECTED: return mods; --- 598,614 ---- case PRIVATE: return "pri_in_"; } assert(false); return "?"; } private static final int[] ACCESS_CASES = { ! PUBLIC, PACKAGE, PRIVATE, PROTECTED, MODULE, UNCONDITIONAL }; + /* + * Adjust PUBLIC => PUBLIC|MODULE|UNCONDITIONAL + * Adjust 0 => PACKAGE + */ /** Return one of the ACCESS_CASES. */ static int fixMods(int mods) { mods &= (PUBLIC|PRIVATE|PROTECTED); switch (mods) { case PUBLIC: case PRIVATE: case PROTECTED: return mods;
< prev index next >