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 { 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 ) 69 private static void invokeHappy() { 70 assertNotReached(); 71 } 72 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 ) 97 private static void invokeWrongParameterTypes() throws NoSuchMethodError { 98 assertNotReached(); 99 } 100 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 ) 123 private static void invokeMissingParameterTypes() throws NoSuchMethodError { 124 assertNotReached(); 125 } 126 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 ) 153 private static void invokeExtraArguments() { 154 assertNotReached(); 155 } 156 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 ) 181 private static void invokeWrongArguments() { 182 assertNotReached(); 183 } 184 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 ) 209 private static void invokeWrongArgumentsAgain() { 210 assertNotReached(); 211 } 212 213 private static void wrongArgumentsAgain() { 214 System.out.println("wrongArgumentsAgain"); 215 } 216 217 // Primitive argument types not supported {Z, B, C, S}. 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 ) 255 private static void invokeNarrowArguments() { 256 assertNotReached(); 257 } 258 259 private static void narrowArguments() { 260 assertNotReached(); 261 } 262 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 ) 299 private static void invokeWideningArguments() { 300 assertNotReached(); 301 } 302 303 private static void wideningArguments() { 304 System.out.println("wideningArguments"); 305 } 306 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 ) 343 private static void invokeBoxingArguments() { 344 assertNotReached(); 345 } 346 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 ) 371 private static void invokeWideningBoxingArguments() { 372 assertNotReached(); 373 } 374 375 private static void wideningBoxingArguments() { 376 System.out.println("wideningBoxingArguments"); 377 } 378 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 ) 393 private static void invokeVoidReturnType() { 394 assertNotReached(); 395 } 396 397 private static void voidReturnType() { 398 assertNotReached(); 399 } 400 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 ) 416 private static void invokeObjectReturnType() { 417 assertNotReached(); 418 } 419 420 private static void objectReturnType() { 421 assertNotReached(); 422 } 423 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 ) 439 private static void invokeIntegerReturnType() { 440 assertNotReached(); 441 } 442 443 private static void integerReturnType() { 444 assertNotReached(); 445 } 446 447 static class TestersConstantCallSite extends ConstantCallSite { 448 public TestersConstantCallSite(MethodHandle mh) { 449 super(mh); 450 } 451 } 452 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 ) 468 private static void invokeViaCustomCallSiteClass() { 469 assertNotReached(); 470 } 471 472 private static void sayHello() { 473 System.out.println("Hello!"); 474 } 475 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