1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 import annotations.BootstrapMethod; 18 import annotations.CalledByIndy; 19 import annotations.Constant; 20 import java.lang.invoke.CallSite; 21 import java.lang.invoke.ConstantCallSite; 22 import java.lang.invoke.MethodHandle; 23 import java.lang.invoke.MethodHandles; 24 import java.lang.invoke.MethodType; 25 import java.lang.invoke.WrongMethodTypeException; 26 27 public class TestBadBootstrapArguments extends TestBase { bsm( MethodHandles.Lookup lookup, String methodName, MethodType methodType, int extraInt, String extraString)28 private static CallSite bsm( 29 MethodHandles.Lookup lookup, 30 String methodName, 31 MethodType methodType, 32 int extraInt, 33 String extraString) 34 throws Throwable { 35 System.out.print("bsm("); 36 System.out.print(lookup.lookupClass()); 37 System.out.print(", "); 38 System.out.print(methodName); 39 System.out.print(", "); 40 System.out.print(methodType); 41 System.out.print(", "); 42 System.out.print(extraInt); 43 System.out.print(", "); 44 System.out.print(extraString); 45 System.out.println(")"); 46 MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType); 47 return new ConstantCallSite(mh); 48 } 49 50 @CalledByIndy( 51 bootstrapMethod = 52 @BootstrapMethod( 53 enclosingType = TestBadBootstrapArguments.class, 54 name = "bsm", 55 parameterTypes = { 56 MethodHandles.Lookup.class, 57 String.class, 58 MethodType.class, 59 int.class, 60 String.class 61 } 62 ), 63 fieldOrMethodName = "happy", 64 constantArgumentsForBootstrapMethod = { 65 @Constant(intValue = -1), 66 @Constant(stringValue = "very") 67 } 68 ) invokeHappy()69 private static void invokeHappy() { 70 assertNotReached(); 71 } 72 happy()73 private static void happy() { 74 System.out.println("happy"); 75 } 76 77 // BootstrapMethod.parameterTypes != parameterTypesOf(constantArgumentsForBootstrapMethod) 78 @CalledByIndy( 79 bootstrapMethod = 80 @BootstrapMethod( 81 enclosingType = TestBadBootstrapArguments.class, 82 name = "bsm", 83 parameterTypes = { 84 MethodHandles.Lookup.class, 85 String.class, 86 MethodType.class, 87 int.class, 88 double.class 89 } 90 ), 91 fieldOrMethodName = "wrongParameterTypes", 92 constantArgumentsForBootstrapMethod = { 93 @Constant(intValue = -1), 94 @Constant(stringValue = "very") 95 } 96 ) invokeWrongParameterTypes()97 private static void invokeWrongParameterTypes() throws NoSuchMethodError { 98 assertNotReached(); 99 } 100 wrongParameterTypes()101 private static void wrongParameterTypes() { 102 System.out.println("wrongParameterTypes"); 103 } 104 105 // BootstrapMethod.parameterTypes != parameterTypesOf(constantArgumentsForBootstrapMethod) 106 // (missing constantArgumentTypes)) 107 @CalledByIndy( 108 bootstrapMethod = 109 @BootstrapMethod( 110 enclosingType = TestBadBootstrapArguments.class, 111 name = "bsm", 112 parameterTypes = { 113 MethodHandles.Lookup.class, 114 String.class, 115 MethodType.class, 116 int.class, 117 double.class 118 } 119 ), 120 fieldOrMethodName = "missingParameterTypes", 121 constantArgumentsForBootstrapMethod = {} 122 ) invokeMissingParameterTypes()123 private static void invokeMissingParameterTypes() throws NoSuchMethodError { 124 assertNotReached(); 125 } 126 missingParameterTypes()127 private static void missingParameterTypes() { 128 System.out.println("missingParameterTypes"); 129 } 130 131 // BootstrapMethod.parameterTypes != parameterTypesOf(constantArgumentsForBootstrapMethod): 132 // extra constant present 133 @CalledByIndy( 134 bootstrapMethod = 135 @BootstrapMethod( 136 enclosingType = TestBadBootstrapArguments.class, 137 name = "bsm", 138 parameterTypes = { 139 MethodHandles.Lookup.class, 140 String.class, 141 MethodType.class, 142 int.class, 143 String.class 144 } 145 ), 146 fieldOrMethodName = "extraArguments", 147 constantArgumentsForBootstrapMethod = { 148 @Constant(intValue = 1), 149 @Constant(stringValue = "2"), 150 @Constant(intValue = 3) 151 } 152 ) invokeExtraArguments()153 private static void invokeExtraArguments() { 154 assertNotReached(); 155 } 156 extraArguments()157 private static void extraArguments() { 158 System.out.println("extraArguments"); 159 } 160 161 // constantArgumentTypes do not correspond to expected parameter types 162 @CalledByIndy( 163 bootstrapMethod = 164 @BootstrapMethod( 165 enclosingType = TestBadBootstrapArguments.class, 166 name = "bsm", 167 parameterTypes = { 168 MethodHandles.Lookup.class, 169 String.class, 170 MethodType.class, 171 int.class, 172 String.class 173 } 174 ), 175 fieldOrMethodName = "wrongArguments", 176 constantArgumentsForBootstrapMethod = { 177 @Constant(stringValue = "1"), 178 @Constant(doubleValue = Math.PI) 179 } 180 ) invokeWrongArguments()181 private static void invokeWrongArguments() { 182 assertNotReached(); 183 } 184 wrongArguments()185 private static void wrongArguments() { 186 System.out.println("wrongArguments"); 187 } 188 189 // constantArgumentTypes do not correspond to expected parameter types 190 @CalledByIndy( 191 bootstrapMethod = 192 @BootstrapMethod( 193 enclosingType = TestBadBootstrapArguments.class, 194 name = "bsm", 195 parameterTypes = { 196 MethodHandles.Lookup.class, 197 String.class, 198 MethodType.class, 199 int.class, 200 String.class 201 } 202 ), 203 fieldOrMethodName = "wrongArgumentsAgain", 204 constantArgumentsForBootstrapMethod = { 205 @Constant(doubleValue = Math.PI), 206 @Constant(stringValue = "pie") 207 } 208 ) invokeWrongArgumentsAgain()209 private static void invokeWrongArgumentsAgain() { 210 assertNotReached(); 211 } 212 wrongArgumentsAgain()213 private static void wrongArgumentsAgain() { 214 System.out.println("wrongArgumentsAgain"); 215 } 216 217 // Primitive argument types not supported {Z, B, C, S}. bsmZBCS( MethodHandles.Lookup lookup, String methodName, MethodType methodType, boolean extraArg0, byte extraArg1, char extraArg2, short extraArg3)218 private static CallSite bsmZBCS( 219 MethodHandles.Lookup lookup, 220 String methodName, 221 MethodType methodType, 222 boolean extraArg0, 223 byte extraArg1, 224 char extraArg2, 225 short extraArg3) 226 throws Throwable { 227 assertNotReached(); 228 return null; 229 } 230 231 // Arguments are narrower than supported. 232 @CalledByIndy( 233 bootstrapMethod = 234 @BootstrapMethod( 235 enclosingType = TestBadBootstrapArguments.class, 236 name = "bsmZBCS", 237 parameterTypes = { 238 MethodHandles.Lookup.class, 239 String.class, 240 MethodType.class, 241 boolean.class, 242 byte.class, 243 char.class, 244 short.class 245 } 246 ), 247 fieldOrMethodName = "narrowArguments", 248 constantArgumentsForBootstrapMethod = { 249 @Constant(booleanValue = true), 250 @Constant(byteValue = Byte.MAX_VALUE), 251 @Constant(charValue = 'A'), 252 @Constant(shortValue = Short.MIN_VALUE) 253 } 254 ) invokeNarrowArguments()255 private static void invokeNarrowArguments() { 256 assertNotReached(); 257 } 258 narrowArguments()259 private static void narrowArguments() { 260 assertNotReached(); 261 } 262 bsmDJ( MethodHandles.Lookup lookup, String methodName, MethodType methodType, double extraArg0, long extraArg1)263 private static CallSite bsmDJ( 264 MethodHandles.Lookup lookup, 265 String methodName, 266 MethodType methodType, 267 double extraArg0, 268 long extraArg1) 269 throws Throwable { 270 System.out.print("bsmDJ(..., "); 271 System.out.print(extraArg0); 272 System.out.print(", "); 273 System.out.print(extraArg1); 274 System.out.println(")"); 275 MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType); 276 return new ConstantCallSite(mh); 277 } 278 279 // Arguments need widening to parameter types. 280 @CalledByIndy( 281 bootstrapMethod = 282 @BootstrapMethod( 283 enclosingType = TestBadBootstrapArguments.class, 284 name = "bsmDJ", 285 parameterTypes = { 286 MethodHandles.Lookup.class, 287 String.class, 288 MethodType.class, 289 double.class, 290 long.class 291 } 292 ), 293 fieldOrMethodName = "wideningArguments", 294 constantArgumentsForBootstrapMethod = { 295 @Constant(doubleValue = Double.MAX_VALUE), 296 @Constant(intValue = Integer.MAX_VALUE) 297 } 298 ) invokeWideningArguments()299 private static void invokeWideningArguments() { 300 assertNotReached(); 301 } 302 wideningArguments()303 private static void wideningArguments() { 304 System.out.println("wideningArguments"); 305 } 306 bsmDoubleLong( MethodHandles.Lookup lookup, String methodName, MethodType methodType, Double extraArg0, Long extraArg1)307 private static CallSite bsmDoubleLong( 308 MethodHandles.Lookup lookup, 309 String methodName, 310 MethodType methodType, 311 Double extraArg0, 312 Long extraArg1) 313 throws Throwable { 314 System.out.print("bsmDoubleLong(..., "); 315 System.out.print(extraArg0); 316 System.out.print(", "); 317 System.out.print(extraArg1); 318 System.out.println(")"); 319 MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType); 320 return new ConstantCallSite(mh); 321 } 322 323 // Arguments need boxing to parameter types 324 @CalledByIndy( 325 bootstrapMethod = 326 @BootstrapMethod( 327 enclosingType = TestBadBootstrapArguments.class, 328 name = "bsmDoubleLong", 329 parameterTypes = { 330 MethodHandles.Lookup.class, 331 String.class, 332 MethodType.class, 333 Double.class, 334 Long.class 335 } 336 ), 337 fieldOrMethodName = "boxingArguments", 338 constantArgumentsForBootstrapMethod = { 339 @Constant(doubleValue = Double.MAX_VALUE), 340 @Constant(longValue = Long.MAX_VALUE) 341 } 342 ) invokeBoxingArguments()343 private static void invokeBoxingArguments() { 344 assertNotReached(); 345 } 346 boxingArguments()347 private static void boxingArguments() { 348 System.out.println("boxingArguments"); 349 } 350 351 // Arguments need widening and boxing to parameter types 352 @CalledByIndy( 353 bootstrapMethod = 354 @BootstrapMethod( 355 enclosingType = TestBadBootstrapArguments.class, 356 name = "bsmDoubleLong", 357 parameterTypes = { 358 MethodHandles.Lookup.class, 359 String.class, 360 MethodType.class, 361 Double.class, 362 Long.class 363 } 364 ), 365 fieldOrMethodName = "wideningBoxingArguments", 366 constantArgumentsForBootstrapMethod = { 367 @Constant(floatValue = Float.MAX_VALUE), 368 @Constant(longValue = Integer.MAX_VALUE) 369 } 370 ) invokeWideningBoxingArguments()371 private static void invokeWideningBoxingArguments() { 372 assertNotReached(); 373 } 374 wideningBoxingArguments()375 private static void wideningBoxingArguments() { 376 System.out.println("wideningBoxingArguments"); 377 } 378 bsmReturningVoid(MethodHandles.Lookup lookup, String name, MethodType type)379 static void bsmReturningVoid(MethodHandles.Lookup lookup, String name, MethodType type) { 380 System.out.println("bsm returning void value."); 381 } 382 383 @CalledByIndy( 384 bootstrapMethod = 385 @BootstrapMethod( 386 enclosingType = TestBadBootstrapArguments.class, 387 name = "bsmReturningVoid", 388 parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class}, 389 returnType = void.class 390 ), 391 fieldOrMethodName = "voidReturnType" 392 ) invokeVoidReturnType()393 private static void invokeVoidReturnType() { 394 assertNotReached(); 395 } 396 voidReturnType()397 private static void voidReturnType() { 398 assertNotReached(); 399 } 400 bsmReturningObject(MethodHandles.Lookup lookup, String name, MethodType type)401 static Object bsmReturningObject(MethodHandles.Lookup lookup, String name, MethodType type) { 402 System.out.println("bsm returning Object value."); 403 return new Object(); 404 } 405 406 @CalledByIndy( 407 bootstrapMethod = 408 @BootstrapMethod( 409 enclosingType = TestBadBootstrapArguments.class, 410 name = "bsmReturningObject", 411 parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class}, 412 returnType = Object.class 413 ), 414 fieldOrMethodName = "ObjectReturnType" 415 ) invokeObjectReturnType()416 private static void invokeObjectReturnType() { 417 assertNotReached(); 418 } 419 objectReturnType()420 private static void objectReturnType() { 421 assertNotReached(); 422 } 423 bsmReturningInteger(MethodHandles.Lookup lookup, String name, MethodType type)424 static Integer bsmReturningInteger(MethodHandles.Lookup lookup, String name, MethodType type) { 425 System.out.println("bsm returning Integer value."); 426 return Integer.valueOf(3); 427 } 428 429 @CalledByIndy( 430 bootstrapMethod = 431 @BootstrapMethod( 432 enclosingType = TestBadBootstrapArguments.class, 433 name = "bsmReturningInteger", 434 parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class}, 435 returnType = Integer.class 436 ), 437 fieldOrMethodName = "integerReturnType" 438 ) invokeIntegerReturnType()439 private static void invokeIntegerReturnType() { 440 assertNotReached(); 441 } 442 integerReturnType()443 private static void integerReturnType() { 444 assertNotReached(); 445 } 446 447 static class TestersConstantCallSite extends ConstantCallSite { TestersConstantCallSite(MethodHandle mh)448 public TestersConstantCallSite(MethodHandle mh) { 449 super(mh); 450 } 451 } 452 bsmReturningTestersConstantCallsite( MethodHandles.Lookup lookup, String name, MethodType type)453 static TestersConstantCallSite bsmReturningTestersConstantCallsite( 454 MethodHandles.Lookup lookup, String name, MethodType type) throws Throwable { 455 return new TestersConstantCallSite(lookup.findStatic(lookup.lookupClass(), name, type)); 456 } 457 458 @CalledByIndy( 459 bootstrapMethod = 460 @BootstrapMethod( 461 enclosingType = TestBadBootstrapArguments.class, 462 name = "bsmReturningTestersConstantCallsite", 463 parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class}, 464 returnType = TestersConstantCallSite.class 465 ), 466 fieldOrMethodName = "sayHello" 467 ) invokeViaCustomCallSiteClass()468 private static void invokeViaCustomCallSiteClass() { 469 assertNotReached(); 470 } 471 sayHello()472 private static void sayHello() { 473 System.out.println("Hello!"); 474 } 475 test()476 static void test() { 477 System.out.println("TestBadBootstrapArguments"); 478 invokeHappy(); 479 try { 480 invokeWrongParameterTypes(); 481 assertNotReached(); 482 } catch (NoSuchMethodError expected) { 483 System.out.print("invokeWrongParameterTypes => "); 484 System.out.println(expected.getClass()); 485 } 486 try { 487 invokeMissingParameterTypes(); 488 assertNotReached(); 489 } catch (NoSuchMethodError expected) { 490 System.out.print("invokeMissingParameterTypes => "); 491 System.out.println(expected.getClass()); 492 } 493 try { 494 invokeExtraArguments(); 495 assertNotReached(); 496 } catch (BootstrapMethodError expected) { 497 assertEquals(WrongMethodTypeException.class, expected.getCause().getClass()); 498 System.out.print("invokeExtraArguments => "); 499 System.out.print(expected.getClass()); 500 System.out.print(" => "); 501 System.out.println(expected.getCause().getClass()); 502 } 503 try { 504 invokeWrongArguments(); 505 assertNotReached(); 506 } catch (BootstrapMethodError expected) { 507 assertEquals(ClassCastException.class, expected.getCause().getClass()); 508 System.out.print("invokeWrongArguments => "); 509 System.out.print(expected.getClass()); 510 System.out.print(" => "); 511 System.out.println(expected.getCause().getClass()); 512 } 513 try { 514 invokeWrongArguments(); 515 assertNotReached(); 516 } catch (BootstrapMethodError expected) { 517 assertEquals(ClassCastException.class, expected.getCause().getClass()); 518 System.out.print("invokeWrongArguments => "); 519 System.out.print(expected.getClass()); 520 System.out.print(" => "); 521 System.out.println(expected.getCause().getClass()); 522 } 523 try { 524 invokeWrongArgumentsAgain(); 525 assertNotReached(); 526 } catch (BootstrapMethodError expected) { 527 assertEquals(ClassCastException.class, expected.getCause().getClass()); 528 System.out.print("invokeWrongArgumentsAgain => "); 529 System.out.print(expected.getClass()); 530 System.out.print(" => "); 531 System.out.println(expected.getCause().getClass()); 532 } 533 try { 534 invokeNarrowArguments(); 535 assertNotReached(); 536 } catch (BootstrapMethodError expected) { 537 assertEquals(ClassCastException.class, expected.getCause().getClass()); 538 System.out.print("invokeNarrowArguments => "); 539 System.out.print(expected.getClass()); 540 System.out.print(" => "); 541 System.out.println(expected.getCause().getClass()); 542 } 543 invokeWideningArguments(); 544 invokeBoxingArguments(); 545 try { 546 invokeWideningBoxingArguments(); 547 assertNotReached(); 548 } catch (BootstrapMethodError expected) { 549 System.out.print("invokeWideningBoxingArguments => "); 550 System.out.print(expected.getClass()); 551 System.out.print(" => "); 552 System.out.println(expected.getCause().getClass()); 553 } 554 try { 555 invokeVoidReturnType(); 556 assertNotReached(); 557 } catch (BootstrapMethodError expected) { 558 System.out.print("invokeVoidReturnType() => "); 559 System.out.print(expected.getClass()); 560 System.out.print(" => "); 561 System.out.println(expected.getCause().getClass()); 562 } 563 try { 564 invokeObjectReturnType(); 565 assertNotReached(); 566 } catch (BootstrapMethodError expected) { 567 System.out.print("invokeObjectReturnType() => "); 568 System.out.print(expected.getClass()); 569 System.out.print(" => "); 570 System.out.println(expected.getCause().getClass()); 571 } 572 try { 573 invokeIntegerReturnType(); 574 assertNotReached(); 575 } catch (BootstrapMethodError expected) { 576 System.out.print("invokeIntegerReturnType() => "); 577 System.out.print(expected.getClass()); 578 System.out.print(" => "); 579 System.out.println(expected.getCause().getClass()); 580 } 581 invokeViaCustomCallSiteClass(); 582 } 583 } 584