1 /* 2 * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @modules java.base/jdk.internal.foreign 27 * @run testng/othervm --enable-native-access=ALL-UNNAMED TestIllegalLink 28 */ 29 30 import java.lang.foreign.Arena; 31 import java.lang.foreign.Linker; 32 import java.lang.foreign.FunctionDescriptor; 33 import java.lang.foreign.MemorySegment; 34 import java.lang.foreign.MemoryLayout; 35 import java.lang.foreign.ValueLayout; 36 import java.lang.invoke.MethodHandle; 37 import java.lang.invoke.MethodHandles; 38 import java.lang.invoke.MethodType; 39 import java.nio.ByteOrder; 40 import java.util.ArrayList; 41 import java.util.Arrays; 42 import java.util.List; 43 44 import jdk.internal.foreign.CABI; 45 import org.testng.annotations.DataProvider; 46 import org.testng.annotations.Test; 47 48 import static java.lang.foreign.ValueLayout.*; 49 50 import static org.testng.Assert.assertTrue; 51 import static org.testng.Assert.fail; 52 53 public class TestIllegalLink extends NativeTestHelper { 54 55 private static final boolean IS_SYSV = CABI.current() == CABI.SYS_V; 56 private static final boolean IS_LE = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN; 57 58 private static final MemorySegment DUMMY_TARGET = MemorySegment.ofAddress(1); 59 private static final MethodHandle DUMMY_TARGET_MH = MethodHandles.empty(MethodType.methodType(void.class)); 60 private static final Linker ABI = Linker.nativeLinker(); 61 62 @Test(dataProvider = "types") 63 public void testIllegalLayouts(FunctionDescriptor desc, Linker.Option[] options, String expectedExceptionMessage) { 64 try { 65 ABI.downcallHandle(DUMMY_TARGET, desc, options); 66 fail("Expected IllegalArgumentException was not thrown"); 67 } catch (IllegalArgumentException e) { 68 assertTrue(e.getMessage().contains(expectedExceptionMessage), 69 e.getMessage() + " does not contain " + expectedExceptionMessage); 70 } 71 } 72 73 @Test(dataProvider = "downcallOnlyOptions", 74 expectedExceptions = IllegalArgumentException.class, 75 expectedExceptionsMessageRegExp = ".*Not supported for upcall.*") 76 public void testIllegalUpcallOptions(Linker.Option downcallOnlyOption) { 77 ABI.upcallStub(DUMMY_TARGET_MH, FunctionDescriptor.ofVoid(), Arena.ofAuto(), downcallOnlyOption); 78 } 79 80 @Test(dataProvider = "illegalCaptureState", 81 expectedExceptions = IllegalArgumentException.class, 82 expectedExceptionsMessageRegExp = ".*Unknown name.*") 83 public void testIllegalCaptureState(String name) { 84 Linker.Option.captureCallState(name); 85 } 86 87 // where 88 89 @DataProvider 90 public static Object[][] illegalCaptureState() { 91 if (!IS_WINDOWS) { 92 return new Object[][]{ 93 { "GetLastError" }, 94 { "WSAGetLastError" }, 95 }; 96 } 97 return new Object[][]{}; 98 } 99 100 @DataProvider 101 public static Object[][] downcallOnlyOptions() { 102 return new Object[][]{ 103 { Linker.Option.firstVariadicArg(0) }, 104 { Linker.Option.captureCallState("errno") }, 105 { Linker.Option.critical() }, 106 }; 107 } 108 109 @DataProvider 110 public static Object[][] types() { 111 Linker.Option[] NO_OPTIONS = new Linker.Option[0]; 112 List<Object[]> cases = new ArrayList<>(Arrays.asList(new Object[][]{ 113 { 114 FunctionDescriptor.of(MemoryLayout.sequenceLayout(2, C_INT)), 115 NO_OPTIONS, 116 IS_LE ? "Unsupported layout: [2:i4]" : "Unsupported layout: [2:I4]" 117 }, 118 { 119 FunctionDescriptor.ofVoid(MemoryLayout.sequenceLayout(2, C_INT)), 120 NO_OPTIONS, 121 IS_LE ? "Unsupported layout: [2:i4]" : "Unsupported layout: [2:I4]" 122 }, 123 { 124 FunctionDescriptor.ofVoid(C_INT.withByteAlignment(2)), 125 NO_OPTIONS, 126 IS_LE ? "Unsupported layout: 2%i4" : "Unsupported layout: 2%I4" 127 }, 128 { 129 FunctionDescriptor.ofVoid(C_POINTER.withByteAlignment(2)), 130 NO_OPTIONS, 131 (IS_LE ? "Unsupported layout: 2%a" : "Unsupported layout: 2%A") + ADDRESS.byteSize() 132 }, 133 { 134 FunctionDescriptor.ofVoid(ValueLayout.JAVA_CHAR.withByteAlignment(4)), 135 NO_OPTIONS, 136 IS_LE ? "Unsupported layout: 4%c2" : "Unsupported layout: 4%C2" 137 }, 138 { 139 FunctionDescriptor.ofVoid(MemoryLayout.structLayout( 140 C_CHAR.withName("x").withByteAlignment(1), 141 C_SHORT.withName("y").withByteAlignment(1), 142 C_INT.withName("z").withByteAlignment(1) 143 ).withByteAlignment(1)), 144 NO_OPTIONS, 145 IS_LE ? "Unsupported layout: 1%s2" : "Unsupported layout: 1%S2" 146 }, 147 { 148 FunctionDescriptor.ofVoid(MemoryLayout.structLayout( 149 MemoryLayout.structLayout( 150 C_CHAR.withName("x").withByteAlignment(1), 151 C_SHORT.withName("y").withByteAlignment(1), 152 C_INT.withName("z").withByteAlignment(1) 153 ))), 154 NO_OPTIONS, 155 IS_LE ? "Unsupported layout: 1%s2" : "Unsupported layout: 1%S2" 156 }, 157 { 158 FunctionDescriptor.ofVoid(MemoryLayout.structLayout( 159 MemoryLayout.sequenceLayout(1, 160 C_INT.withByteAlignment(1) 161 ))), 162 NO_OPTIONS, 163 IS_LE ? "Unsupported layout: 1%i4" : "Unsupported layout: 1%I4" 164 }, 165 { 166 FunctionDescriptor.ofVoid(MemoryLayout.structLayout( 167 ValueLayout.JAVA_INT, 168 MemoryLayout.paddingLayout(4), // no excess padding 169 ValueLayout.JAVA_INT)), 170 NO_OPTIONS, 171 "unexpected offset" 172 }, 173 { 174 FunctionDescriptor.of(C_INT.withOrder(nonNativeOrder())), 175 NO_OPTIONS, 176 IS_LE ? "Unsupported layout: I4" : "Unsupported layout: i4" 177 }, 178 { 179 FunctionDescriptor.of(MemoryLayout.structLayout(C_INT.withOrder(nonNativeOrder()))), 180 NO_OPTIONS, 181 IS_LE ? "Unsupported layout: I4" : "Unsupported layout: i4" 182 }, 183 { 184 FunctionDescriptor.of(MemoryLayout.structLayout(MemoryLayout.sequenceLayout(1, C_INT.withOrder(nonNativeOrder())))), 185 NO_OPTIONS, 186 IS_LE ? "Unsupported layout: I4" : "Unsupported layout: i4" 187 }, 188 { 189 FunctionDescriptor.ofVoid(MemoryLayout.structLayout( 190 ValueLayout.JAVA_INT, 191 MemoryLayout.paddingLayout(4))), // too much trailing padding 192 NO_OPTIONS, 193 "has unexpected size" 194 }, 195 { 196 FunctionDescriptor.ofVoid(), 197 new Linker.Option[]{Linker.Option.critical(), Linker.Option.captureCallState("errno")}, 198 "Incompatible linker options: captureCallState, critical" 199 }, 200 })); 201 202 for (ValueLayout illegalLayout : List.of(C_CHAR, ValueLayout.JAVA_CHAR, C_BOOL, C_SHORT, C_FLOAT)) { 203 cases.add(new Object[]{ 204 FunctionDescriptor.ofVoid(C_INT, illegalLayout), 205 new Linker.Option[]{Linker.Option.firstVariadicArg(1)}, 206 "Invalid variadic argument layout" 207 }); 208 } 209 210 if (IS_SYSV) { 211 cases.add(new Object[] { 212 FunctionDescriptor.ofVoid(MemoryLayout.structLayout( 213 MemoryLayout.sequenceLayout(Long.MAX_VALUE / C_INT.byteSize(), 214 C_INT 215 ))), 216 NO_OPTIONS, 217 "GroupLayout is too large" 218 }); 219 } 220 if (ValueLayout.JAVA_LONG.byteAlignment() == 8) { 221 cases.add(new Object[]{ 222 FunctionDescriptor.ofVoid(MemoryLayout.structLayout( 223 ValueLayout.JAVA_LONG, 224 ValueLayout.JAVA_INT)), // missing trailing padding 225 NO_OPTIONS, 226 "has unexpected size" 227 }); 228 } 229 return cases.toArray(Object[][]::new); 230 } 231 232 private static ByteOrder nonNativeOrder() { 233 return ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN 234 ? ByteOrder.BIG_ENDIAN 235 : ByteOrder.LITTLE_ENDIAN; 236 } 237 }