undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 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 8035776
|
||||
* @summary Ensure that invocation parameters are always cast to the instantiatedMethodType
|
||||
*/
|
||||
import java.lang.invoke.*;
|
||||
import java.util.Arrays;
|
||||
import static java.lang.invoke.MethodType.methodType;
|
||||
|
||||
public class MetafactoryParameterCastTest {
|
||||
|
||||
static final MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
|
||||
public static class A {
|
||||
}
|
||||
|
||||
public static class B extends A {
|
||||
void instance0() {}
|
||||
void instance1(B arg) {}
|
||||
static void static1(B arg) {}
|
||||
static void static2(B arg1, B arg2) {}
|
||||
}
|
||||
|
||||
public static class C extends B {}
|
||||
public static class NotC extends B {}
|
||||
|
||||
public interface ASink { void take(A arg); }
|
||||
public interface BSink { void take(B arg); }
|
||||
|
||||
public static void main(String... args) throws Throwable {
|
||||
new MetafactoryParameterCastTest().test();
|
||||
}
|
||||
|
||||
void test() throws Throwable {
|
||||
MethodType takeA = methodType(void.class, A.class);
|
||||
MethodType takeB = methodType(void.class, B.class);
|
||||
MethodType takeC = methodType(void.class, C.class);
|
||||
|
||||
Class<?>[] noCapture = {};
|
||||
Class<?>[] captureB = { B.class };
|
||||
|
||||
MethodHandle[] oneBParam = { lookup.findVirtual(B.class, "instance0", methodType(void.class)),
|
||||
lookup.findStatic(B.class, "static1", methodType(void.class, B.class)) };
|
||||
MethodHandle[] twoBParams = { lookup.findVirtual(B.class, "instance1", methodType(void.class, B.class)),
|
||||
lookup.findStatic(B.class, "static2", methodType(void.class, B.class, B.class)) };
|
||||
|
||||
for (MethodHandle mh : oneBParam) {
|
||||
// sam
|
||||
tryASink(invokeMetafactory(mh, ASink.class, "take", noCapture, takeC, takeA));
|
||||
tryBSink(invokeMetafactory(mh, BSink.class, "take", noCapture, takeC, takeB));
|
||||
tryASink(invokeAltMetafactory(mh, ASink.class, "take", noCapture, takeC, takeA));
|
||||
tryBSink(invokeAltMetafactory(mh, BSink.class, "take", noCapture, takeC, takeB));
|
||||
|
||||
// bridge
|
||||
tryASink(invokeAltMetafactory(mh, ASink.class, "take", noCapture, takeC, takeC, takeA));
|
||||
tryBSink(invokeAltMetafactory(mh, BSink.class, "take", noCapture, takeC, takeC, takeB));
|
||||
}
|
||||
|
||||
for (MethodHandle mh : twoBParams) {
|
||||
// sam
|
||||
tryCapASink(invokeMetafactory(mh, ASink.class, "take", captureB, takeC, takeA));
|
||||
tryCapBSink(invokeMetafactory(mh, BSink.class, "take", captureB, takeC, takeB));
|
||||
tryCapASink(invokeAltMetafactory(mh, ASink.class, "take", captureB, takeC, takeA));
|
||||
tryCapBSink(invokeAltMetafactory(mh, BSink.class, "take", captureB, takeC, takeB));
|
||||
|
||||
// bridge
|
||||
tryCapASink(invokeAltMetafactory(mh, ASink.class, "take", captureB, takeC, takeC, takeA));
|
||||
tryCapBSink(invokeAltMetafactory(mh, BSink.class, "take", captureB, takeC, takeC, takeB));
|
||||
}
|
||||
}
|
||||
|
||||
void tryASink(CallSite cs) throws Throwable {
|
||||
ASink sink = (ASink) cs.dynamicInvoker().invoke();
|
||||
tryASink(sink);
|
||||
}
|
||||
|
||||
void tryCapASink(CallSite cs) throws Throwable {
|
||||
ASink sink = (ASink) cs.dynamicInvoker().invoke(new B());
|
||||
tryASink(sink);
|
||||
}
|
||||
|
||||
void tryBSink(CallSite cs) throws Throwable {
|
||||
BSink sink = (BSink) cs.dynamicInvoker().invoke();
|
||||
tryBSink(sink);
|
||||
}
|
||||
|
||||
void tryCapBSink(CallSite cs) throws Throwable {
|
||||
BSink sink = (BSink) cs.dynamicInvoker().invoke(new B());
|
||||
tryBSink(sink);
|
||||
}
|
||||
|
||||
void tryASink(ASink sink) {
|
||||
try { sink.take(new C()); }
|
||||
catch (ClassCastException e) {
|
||||
throw new AssertionError("Unexpected cast failure: " + e + " " + lastMFParams());
|
||||
}
|
||||
|
||||
try {
|
||||
sink.take(new B());
|
||||
throw new AssertionError("Missing cast from A to C: " + lastMFParams());
|
||||
}
|
||||
catch (ClassCastException e) { /* expected */ }
|
||||
|
||||
try {
|
||||
sink.take(new NotC());
|
||||
throw new AssertionError("Missing cast from A to C: " + lastMFParams());
|
||||
}
|
||||
catch (ClassCastException e) { /* expected */ }
|
||||
}
|
||||
|
||||
void tryBSink(BSink sink) {
|
||||
try { sink.take(new C()); }
|
||||
catch (ClassCastException e) {
|
||||
throw new AssertionError("Unexpected cast failure: " + e + " " + lastMFParams());
|
||||
}
|
||||
|
||||
try {
|
||||
sink.take(new B());
|
||||
throw new AssertionError("Missing cast from B to C: " + lastMFParams());
|
||||
}
|
||||
catch (ClassCastException e) { /* expected */ }
|
||||
|
||||
try {
|
||||
sink.take(new NotC());
|
||||
throw new AssertionError("Missing cast from B to C: " + lastMFParams());
|
||||
}
|
||||
catch (ClassCastException e) { /* expected */ }
|
||||
}
|
||||
|
||||
MethodHandle lastMH;
|
||||
Class<?>[] lastCaptured;
|
||||
MethodType lastInstMT;
|
||||
MethodType lastSamMT;
|
||||
MethodType[] lastBridgeMTs;
|
||||
|
||||
String lastMFParams() {
|
||||
return "mh=" + lastMH +
|
||||
", captured=" + Arrays.toString(lastCaptured) +
|
||||
", instMT=" + lastInstMT +
|
||||
", samMT=" + lastSamMT +
|
||||
", bridgeMTs=" + Arrays.toString(lastBridgeMTs);
|
||||
}
|
||||
|
||||
CallSite invokeMetafactory(MethodHandle mh, Class<?> sam, String methodName,
|
||||
Class<?>[] captured, MethodType instMT, MethodType samMT) {
|
||||
lastMH = mh;
|
||||
lastCaptured = captured;
|
||||
lastInstMT = instMT;
|
||||
lastSamMT = samMT;
|
||||
lastBridgeMTs = new MethodType[]{};
|
||||
try {
|
||||
return LambdaMetafactory.metafactory(lookup, methodName, methodType(sam, captured),
|
||||
samMT, mh, instMT);
|
||||
}
|
||||
catch (LambdaConversionException e) {
|
||||
// unexpected linkage error
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
CallSite invokeAltMetafactory(MethodHandle mh, Class<?> sam, String methodName,
|
||||
Class<?>[] captured, MethodType instMT,
|
||||
MethodType samMT, MethodType... bridgeMTs) {
|
||||
lastMH = mh;
|
||||
lastCaptured = captured;
|
||||
lastInstMT = instMT;
|
||||
lastSamMT = samMT;
|
||||
lastBridgeMTs = bridgeMTs;
|
||||
try {
|
||||
boolean bridge = bridgeMTs.length > 0;
|
||||
Object[] args = new Object[bridge ? 5+bridgeMTs.length : 4];
|
||||
args[0] = samMT;
|
||||
args[1] = mh;
|
||||
args[2] = instMT;
|
||||
args[3] = bridge ? LambdaMetafactory.FLAG_BRIDGES : 0;
|
||||
if (bridge) {
|
||||
args[4] = bridgeMTs.length;
|
||||
for (int i = 0; i < bridgeMTs.length; i++) args[5+i] = bridgeMTs[i];
|
||||
}
|
||||
return LambdaMetafactory.altMetafactory(lookup, methodName, methodType(sam, captured), args);
|
||||
}
|
||||
catch (LambdaConversionException e) {
|
||||
// unexpected linkage error
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue