222 lines
10 KiB
Diff
222 lines
10 KiB
Diff
From 5fbf4e8b326dd8453822ae40f3c6e4adffbf42ac Mon Sep 17 00:00:00 2001
|
|
From: zhangyipeng <zhangyipeng7@huawei.com>
|
|
Date: Fri, 3 Nov 2023 16:21:09 +0800
|
|
Subject: [PATCH] [Backport]8177146: MethodHandles.Lookup::bind allows illegal protected
|
|
access
|
|
|
|
---
|
|
.../classes/java/lang/invoke/MethodHandles.java | 22 +++--
|
|
.../lang/invoke/8177146/TestMethodHandleBind.java | 96 ++++++++++++++++++++++
|
|
jdk/test/java/lang/invoke/8177146/pkg/A.java | 40 +++++++++
|
|
3 files changed, 149 insertions(+), 9 deletions(-)
|
|
create mode 100644 jdk/test/java/lang/invoke/8177146/TestMethodHandleBind.java
|
|
create mode 100644 jdk/test/java/lang/invoke/8177146/pkg/A.java
|
|
|
|
diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java
|
|
index 7b9353ab0..62888c019 100644
|
|
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java
|
|
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java
|
|
@@ -1148,7 +1148,13 @@ return mh1;
|
|
public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
|
|
Class<? extends Object> refc = receiver.getClass(); // may get NPE
|
|
MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type);
|
|
- MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, findBoundCallerClass(method));
|
|
+ MethodHandle mh = getDirectMethodNoRestrictInvokeSpecial(refc, method, findBoundCallerClass(method));
|
|
+ if (!mh.type().leadingReferenceParameter().isAssignableFrom(receiver.getClass())) {
|
|
+ throw new IllegalAccessException("The restricted defining class " +
|
|
+ mh.type().leadingReferenceParameter().getName() +
|
|
+ " is not assignable from receiver class " +
|
|
+ receiver.getClass().getName());
|
|
+ }
|
|
return mh.bindArgumentL(0, receiver).setVarargs(method);
|
|
}
|
|
|
|
@@ -1591,7 +1597,7 @@ return mh1;
|
|
throw method.makeAccessException("caller class must be a subclass below the method", caller);
|
|
}
|
|
MethodType rawType = mh.type();
|
|
- if (rawType.parameterType(0) == caller) return mh;
|
|
+ if (caller.isAssignableFrom(rawType.parameterType(0))) return mh; // no need to restrict; already narrow
|
|
MethodType narrowType = rawType.changeParameterType(0, caller);
|
|
assert(!mh.isVarargsCollector()); // viewAsType will lose varargs-ness
|
|
assert(mh.viewAsTypeChecks(narrowType, true));
|
|
@@ -1604,11 +1610,11 @@ return mh1;
|
|
final boolean checkSecurity = true;
|
|
return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass);
|
|
}
|
|
- /** Check access and get the requested method, eliding receiver narrowing rules. */
|
|
- private MethodHandle getDirectMethodNoRestrict(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
|
|
+ /** Check access and get the requested method, for invokespecial with no restriction on the application of narrowing rules. */
|
|
+ private MethodHandle getDirectMethodNoRestrictInvokeSpecial(Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
|
|
final boolean doRestrict = false;
|
|
final boolean checkSecurity = true;
|
|
- return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass);
|
|
+ return getDirectMethodCommon(REF_invokeSpecial, refc, method, checkSecurity, doRestrict, callerClass);
|
|
}
|
|
/** Check access and get the requested method, eliding security manager checks. */
|
|
private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
|
|
@@ -1660,10 +1666,8 @@ return mh1;
|
|
DirectMethodHandle dmh = DirectMethodHandle.make(refKind, refc, method);
|
|
MethodHandle mh = dmh;
|
|
// Optionally narrow the receiver argument to refc using restrictReceiver.
|
|
- if (doRestrict &&
|
|
- (refKind == REF_invokeSpecial ||
|
|
- (MethodHandleNatives.refKindHasReceiver(refKind) &&
|
|
- restrictProtectedReceiver(method)))) {
|
|
+ if ((doRestrict && refKind == REF_invokeSpecial) ||
|
|
+ (MethodHandleNatives.refKindHasReceiver(refKind) && restrictProtectedReceiver(method))) {
|
|
mh = restrictReceiver(method, dmh, lookupClass());
|
|
}
|
|
mh = maybeBindCaller(method, mh, callerClass);
|
|
diff --git a/jdk/test/java/lang/invoke/8177146/TestMethodHandleBind.java b/jdk/test/java/lang/invoke/8177146/TestMethodHandleBind.java
|
|
new file mode 100644
|
|
index 000000000..134cc9f75
|
|
--- /dev/null
|
|
+++ b/jdk/test/java/lang/invoke/8177146/TestMethodHandleBind.java
|
|
@@ -0,0 +1,96 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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.
|
|
+ *
|
|
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
+ * version 2 for more details (a copy is included in the LICENSE file that
|
|
+ * accompanied this code).
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License version
|
|
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
|
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
+ *
|
|
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
+ * or visit www.oracle.com if you need additional information or have any
|
|
+ * questions.
|
|
+ */
|
|
+
|
|
+/* @test
|
|
+ * @bug 8177146
|
|
+ * @run testng/othervm TestMethodHandleBind
|
|
+ */
|
|
+
|
|
+import org.testng.annotations.Test;
|
|
+
|
|
+import java.lang.invoke.MethodHandle;
|
|
+import java.lang.invoke.MethodType;
|
|
+
|
|
+import static java.lang.invoke.MethodHandles.lookup;
|
|
+
|
|
+import static org.testng.Assert.*;
|
|
+
|
|
+public class TestMethodHandleBind extends pkg.A {
|
|
+ static class B extends TestMethodHandleBind {}
|
|
+
|
|
+ @Test
|
|
+ public void testInstanceOfCallerClass() throws Throwable {
|
|
+ MethodHandle bound = lookup().bind(new TestMethodHandleBind() , "m1", MethodType.methodType(String.class));
|
|
+ String x = (String)bound.invoke();
|
|
+ assertEquals(x, this.getClass().getSimpleName());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void testInstanceOfCallerSubclass() throws Throwable {
|
|
+ MethodHandle bound = lookup().bind(new B() , "m1", MethodType.methodType(String.class));
|
|
+ // MethodHandle bound = lookup().findVirtual(B.class, "m1", MethodType.methodType(String.class)).bindTo(new B());
|
|
+ String x = (String)bound.invoke();
|
|
+ assertEquals(x, "B");
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void testInstanceOfReceiverClass() throws Throwable {
|
|
+ try {
|
|
+ MethodHandle bound = lookup().bind(new pkg.A() , "m1", MethodType.methodType(String.class));
|
|
+ bound.invoke();
|
|
+ fail("IllegalAccessException expected");
|
|
+ } catch (IllegalAccessException e) {
|
|
+ }
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void testPublicMethod() throws Throwable {
|
|
+ MethodHandle bound = lookup().bind(new pkg.A() , "m2", MethodType.methodType(String.class));
|
|
+ String x = (String)bound.invoke();
|
|
+ assertEquals(x, "A");
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void testPublicMethod2() throws Throwable {
|
|
+ MethodHandle bound = lookup().bind(new TestMethodHandleBind(), "m2", MethodType.methodType(String.class));
|
|
+ String x = (String)bound.invoke();
|
|
+ assertEquals(x, this.getClass().getSimpleName());
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void testInstanceOfCallerClassVarargs() throws Throwable {
|
|
+ MethodHandle bound = lookup().bind(new TestMethodHandleBind() , "m3", MethodType.methodType(String.class, String[].class));
|
|
+ String x = (String)bound.invoke("a", "b", "c");
|
|
+ assertEquals(x, this.getClass().getSimpleName() + "abc");
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void testInstanceOfReceiverClassVarargs() throws Throwable {
|
|
+ try {
|
|
+ MethodHandle bound = lookup().bind(new pkg.A(), "m3", MethodType.methodType(String.class, String[].class));
|
|
+ bound.invoke();
|
|
+ fail("IllegalAccessException expected");
|
|
+ } catch (IllegalAccessException e) {
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/jdk/test/java/lang/invoke/8177146/pkg/A.java b/jdk/test/java/lang/invoke/8177146/pkg/A.java
|
|
new file mode 100644
|
|
index 000000000..f34d52b8e
|
|
--- /dev/null
|
|
+++ b/jdk/test/java/lang/invoke/8177146/pkg/A.java
|
|
@@ -0,0 +1,40 @@
|
|
+/*
|
|
+ * Copyright (c) 2017, 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.
|
|
+ *
|
|
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
+ * version 2 for more details (a copy is included in the LICENSE file that
|
|
+ * accompanied this code).
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License version
|
|
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
|
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
+ *
|
|
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
+ * or visit www.oracle.com if you need additional information or have any
|
|
+ * questions.
|
|
+ */
|
|
+package pkg;
|
|
+
|
|
+public class A {
|
|
+ protected String m1() {
|
|
+ return this.getClass().getSimpleName();
|
|
+ }
|
|
+
|
|
+ public String m2() {
|
|
+ return this.getClass().getSimpleName();
|
|
+ }
|
|
+
|
|
+ protected String m3(String... args) {
|
|
+ StringBuilder sb = new StringBuilder();
|
|
+ for (String s : args)
|
|
+ sb.append(s);
|
|
+ return this.getClass().getSimpleName() + sb.toString();
|
|
+ }
|
|
+}
|
|
--
|
|
2.12.3
|
|
|