8244090: public lookup should find public members of public exported types

Reviewed-by: lfoltan, psandoz
This commit is contained in:
Mandy Chung 2020-09-03 12:43:13 -07:00
parent 49a9d49dbd
commit 4e6a4af186
24 changed files with 369 additions and 75 deletions

View file

@ -28,7 +28,7 @@ package java.lang.invoke;
import java.util.Arrays;
import static java.lang.invoke.LambdaForm.*;
import static java.lang.invoke.LambdaForm.Kind.*;
import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeVirtual;
import static java.lang.invoke.MethodHandleNatives.Constants.*;
import static java.lang.invoke.MethodHandleStatics.*;
/**
@ -177,7 +177,7 @@ abstract class DelegatingMethodHandle extends MethodHandle {
MethodType.methodType(MethodHandle.class), REF_invokeVirtual);
NF_getTarget = new NamedFunction(
MemberName.getFactory()
.resolveOrFail(REF_invokeVirtual, member, DelegatingMethodHandle.class, NoSuchMethodException.class));
.resolveOrFail(REF_invokeVirtual, member, DelegatingMethodHandle.class, LM_TRUSTED, NoSuchMethodException.class));
} catch (ReflectiveOperationException ex) {
throw newInternalError(ex);
}

View file

@ -63,7 +63,7 @@ class DirectMethodHandle extends MethodHandle {
member.isMethod() && !member.isAbstract()) {
// Check for corner case: invokeinterface of Object method
MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null, LM_TRUSTED);
if (m != null && m.isPublic()) {
assert(member.getReferenceKind() == m.getReferenceKind()); // else this.form is wrong
member = m;
@ -260,7 +260,8 @@ class DirectMethodHandle extends MethodHandle {
.changeReturnType(void.class); // <init> returns void
MemberName linker = new MemberName(MethodHandle.class, linkerName, mtypeWithArg, REF_invokeStatic);
try {
linker = IMPL_NAMES.resolveOrFail(REF_invokeStatic, linker, null, NoSuchMethodException.class);
linker = IMPL_NAMES.resolveOrFail(REF_invokeStatic, linker, null, LM_TRUSTED,
NoSuchMethodException.class);
} catch (ReflectiveOperationException ex) {
throw newInternalError(ex);
}
@ -771,7 +772,8 @@ class DirectMethodHandle extends MethodHandle {
linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);
MemberName linker = new MemberName(Unsafe.class, kind.methodName, linkerType, REF_invokeVirtual);
try {
linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, NoSuchMethodException.class);
linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, LM_TRUSTED,
NoSuchMethodException.class);
} catch (ReflectiveOperationException ex) {
throw newInternalError(ex);
}
@ -914,13 +916,15 @@ class DirectMethodHandle extends MethodHandle {
case NF_UNSAFE:
MemberName member = new MemberName(MethodHandleStatics.class, "UNSAFE", Unsafe.class, REF_getField);
return new NamedFunction(
MemberName.getFactory()
.resolveOrFail(REF_getField, member, DirectMethodHandle.class, NoSuchMethodException.class));
MemberName.getFactory().resolveOrFail(REF_getField, member,
DirectMethodHandle.class, LM_TRUSTED,
NoSuchMethodException.class));
case NF_checkReceiver:
member = new MemberName(DirectMethodHandle.class, "checkReceiver", OBJ_OBJ_TYPE, REF_invokeVirtual);
return new NamedFunction(
MemberName.getFactory()
.resolveOrFail(REF_invokeVirtual, member, DirectMethodHandle.class, NoSuchMethodException.class));
MemberName.getFactory().resolveOrFail(REF_invokeVirtual, member,
DirectMethodHandle.class, LM_TRUSTED,
NoSuchMethodException.class));
default:
throw newInternalError("Unknown function: " + func);
}
@ -934,8 +938,9 @@ class DirectMethodHandle extends MethodHandle {
{
MemberName member = new MemberName(DirectMethodHandle.class, name, type, REF_invokeStatic);
return new NamedFunction(
MemberName.getFactory()
.resolveOrFail(REF_invokeStatic, member, DirectMethodHandle.class, NoSuchMethodException.class));
MemberName.getFactory().resolveOrFail(REF_invokeStatic, member,
DirectMethodHandle.class, LM_TRUSTED,
NoSuchMethodException.class));
}
static {

View file

@ -322,7 +322,9 @@ class InvokerBytecodeGenerator {
private static MemberName resolveInvokerMember(Class<?> invokerClass, String name, MethodType type) {
MemberName member = new MemberName(invokerClass, name, type, REF_invokeStatic);
try {
member = MEMBERNAME_FACTORY.resolveOrFail(REF_invokeStatic, member, HOST_CLASS, ReflectiveOperationException.class);
member = MEMBERNAME_FACTORY.resolveOrFail(REF_invokeStatic, member,
HOST_CLASS, LM_TRUSTED,
ReflectiveOperationException.class);
} catch (ReflectiveOperationException e) {
throw newInternalError(e);
}
@ -693,7 +695,7 @@ class InvokerBytecodeGenerator {
private static MemberName resolveFrom(String name, MethodType type, Class<?> holder) {
MemberName member = new MemberName(holder, name, type, REF_invokeStatic);
MemberName resolvedMember = MemberName.getFactory().resolveOrNull(REF_invokeStatic, member, holder);
MemberName resolvedMember = MemberName.getFactory().resolveOrNull(REF_invokeStatic, member, holder, LM_TRUSTED);
if (TRACE_RESOLVE) {
System.out.println("[LF_RESOLVE] " + holder.getName() + " " + name + " " +
shortenSignature(basicTypeSignature(type)) + (resolvedMember != null ? " (success)" : " (fail)") );

View file

@ -661,7 +661,7 @@ class Invokers {
MemberName member = new MemberName(Invokers.class, name, type, REF_invokeStatic);
return new NamedFunction(
MemberName.getFactory()
.resolveOrFail(REF_invokeStatic, member, Invokers.class, NoSuchMethodException.class));
.resolveOrFail(REF_invokeStatic, member, Invokers.class, LM_TRUSTED, NoSuchMethodException.class));
}
private static class Lazy {

View file

@ -40,7 +40,7 @@ import java.util.Arrays;
import java.util.HashMap;
import static java.lang.invoke.LambdaForm.BasicType.*;
import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
import static java.lang.invoke.MethodHandleNatives.Constants.*;
import static java.lang.invoke.MethodHandleStatics.*;
/**
@ -1758,10 +1758,10 @@ class LambdaForm {
MemberName idMem = new MemberName(LambdaForm.class, "identity_"+btChar, idType, REF_invokeStatic);
MemberName zeMem = null;
try {
idMem = IMPL_NAMES.resolveOrFail(REF_invokeStatic, idMem, null, NoSuchMethodException.class);
idMem = IMPL_NAMES.resolveOrFail(REF_invokeStatic, idMem, null, LM_TRUSTED, NoSuchMethodException.class);
if (!isVoid) {
zeMem = new MemberName(LambdaForm.class, "zero_"+btChar, zeType, REF_invokeStatic);
zeMem = IMPL_NAMES.resolveOrFail(REF_invokeStatic, zeMem, null, NoSuchMethodException.class);
zeMem = IMPL_NAMES.resolveOrFail(REF_invokeStatic, zeMem, null, LM_TRUSTED, NoSuchMethodException.class);
}
} catch (IllegalAccessException|NoSuchMethodException ex) {
throw newInternalError(ex);

View file

@ -1064,7 +1064,7 @@ final class MemberName implements Member, Cloneable {
* If lookup fails or access is not permitted, null is returned.
* Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
*/
private MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass,
private MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass, int allowedModes,
boolean speculativeResolve) {
MemberName m = ref.clone(); // JVM will side-effect the ref
assert(refKind == m.getReferenceKind());
@ -1084,7 +1084,7 @@ final class MemberName implements Member, Cloneable {
//
// REFC view on PTYPES doesn't matter, since it is used only as a starting point for resolution and doesn't
// participate in method selection.
m = MethodHandleNatives.resolve(m, lookupClass, speculativeResolve);
m = MethodHandleNatives.resolve(m, lookupClass, allowedModes, speculativeResolve);
if (m == null && speculativeResolve) {
return null;
}
@ -1108,10 +1108,12 @@ final class MemberName implements Member, Cloneable {
* Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
*/
public <NoSuchMemberException extends ReflectiveOperationException>
MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass,
Class<NoSuchMemberException> nsmClass)
MemberName resolveOrFail(byte refKind, MemberName m,
Class<?> lookupClass, int allowedModes,
Class<NoSuchMemberException> nsmClass)
throws IllegalAccessException, NoSuchMemberException {
MemberName result = resolve(refKind, m, lookupClass, false);
assert lookupClass != null || allowedModes == LM_TRUSTED;
MemberName result = resolve(refKind, m, lookupClass, allowedModes, false);
if (result.isResolved())
return result;
ReflectiveOperationException ex = result.makeAccessException();
@ -1124,8 +1126,9 @@ final class MemberName implements Member, Cloneable {
* If lookup fails or access is not permitted, return null.
* Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
*/
public MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass) {
MemberName result = resolve(refKind, m, lookupClass, true);
public MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass, int allowedModes) {
assert lookupClass != null || allowedModes == LM_TRUSTED;
MemberName result = resolve(refKind, m, lookupClass, allowedModes, true);
if (result != null && result.isResolved())
return result;
return null;

View file

@ -51,7 +51,7 @@ class MethodHandleNatives {
static native void init(MemberName self, Object ref);
static native void expand(MemberName self);
static native MemberName resolve(MemberName self, Class<?> caller,
static native MemberName resolve(MemberName self, Class<?> caller, int lookupMode,
boolean speculativeResolve) throws LinkageError, ClassNotFoundException;
static native int getMembers(Class<?> defc, String matchName, String matchSig,
int matchFlags, Class<?> caller, int skip, MemberName[] results);
@ -149,6 +149,15 @@ class MethodHandleNatives {
HIDDEN_CLASS = 0x00000002,
STRONG_LOADER_LINK = 0x00000004,
ACCESS_VM_ANNOTATIONS = 0x00000008;
/**
* Lookup modes
*/
static final int
LM_MODULE = Lookup.MODULE,
LM_UNCONDITIONAL = Lookup.UNCONDITIONAL,
LM_TRUSTED = -1;
}
static boolean refKindIsValid(int refKind) {
@ -561,7 +570,7 @@ class MethodHandleNatives {
guardType, REF_invokeStatic);
linker = MemberName.getFactory().resolveOrNull(REF_invokeStatic, linker,
VarHandleGuards.class);
VarHandleGuards.class, LM_TRUSTED);
if (linker != null) {
return linker;
}

View file

@ -1409,14 +1409,7 @@ public class MethodHandles {
// This is just for calling out to MethodHandleImpl.
private Class<?> lookupClassOrNull() {
if (allowedModes == TRUSTED) {
return null;
}
if (allowedModes == UNCONDITIONAL) {
// use Object as the caller to pass to VM doing resolution
return Object.class;
}
return lookupClass;
return (allowedModes == TRUSTED) ? null : lookupClass;
}
/** Tells which access-protection classes of members this lookup object can produce.
@ -3442,7 +3435,7 @@ return mh1;
checkSymbolicClass(refc); // do this before attempting to resolve
Objects.requireNonNull(name);
Objects.requireNonNull(type);
return IMPL_NAMES.resolveOrFail(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(),
return IMPL_NAMES.resolveOrFail(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(), allowedModes,
NoSuchFieldException.class);
}
@ -3451,7 +3444,7 @@ return mh1;
Objects.requireNonNull(name);
Objects.requireNonNull(type);
checkMethodName(refKind, name); // NPE check on name
return IMPL_NAMES.resolveOrFail(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(),
return IMPL_NAMES.resolveOrFail(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(), allowedModes,
NoSuchMethodException.class);
}
@ -3459,7 +3452,7 @@ return mh1;
checkSymbolicClass(member.getDeclaringClass()); // do this before attempting to resolve
Objects.requireNonNull(member.getName());
Objects.requireNonNull(member.getType());
return IMPL_NAMES.resolveOrFail(refKind, member, lookupClassOrNull(),
return IMPL_NAMES.resolveOrFail(refKind, member, lookupClassOrNull(), allowedModes,
ReflectiveOperationException.class);
}
@ -3470,7 +3463,7 @@ return mh1;
}
Objects.requireNonNull(member.getName());
Objects.requireNonNull(member.getType());
return IMPL_NAMES.resolveOrNull(refKind, member, lookupClassOrNull());
return IMPL_NAMES.resolveOrNull(refKind, member, lookupClassOrNull(), allowedModes);
}
void checkSymbolicClass(Class<?> refc) throws IllegalAccessException {
@ -3774,7 +3767,7 @@ return mh1;
method.getName(),
method.getMethodType(),
REF_invokeSpecial);
m2 = IMPL_NAMES.resolveOrNull(refKind, m2, lookupClassOrNull());
m2 = IMPL_NAMES.resolveOrNull(refKind, m2, lookupClassOrNull(), allowedModes);
} while (m2 == null && // no method is found yet
refc != refcAsSuper); // search up to refc
if (m2 == null) throw new InternalError(method.toString());