src/share/classes/sun/reflect/annotation/TypeAnnotationParser.java

Print this page
rev 8830 : 8023278: Reflection API methods do not throw AnnotationFormatError in case of malformed Runtime[In]VisibleTypeAnnotations attribute
Reviewed-by: duke


 377     private static final byte METHOD_FORMAL_PARAMETER = 0x16;
 378     private static final byte THROWS = 0x17;
 379     // Type Annotations inside method bodies
 380     private static final byte LOCAL_VARIABLE = (byte)0x40;
 381     private static final byte RESOURCE_VARIABLE = (byte)0x41;
 382     private static final byte EXCEPTION_PARAMETER = (byte)0x42;
 383     private static final byte INSTANCEOF = (byte)0x43;
 384     private static final byte NEW = (byte)0x44;
 385     private static final byte CONSTRUCTOR_REFERENCE = (byte)0x45;
 386     private static final byte METHOD_REFERENCE = (byte)0x46;
 387     private static final byte CAST = (byte)0x47;
 388     private static final byte CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = (byte)0x48;
 389     private static final byte METHOD_INVOCATION_TYPE_ARGUMENT = (byte)0x49;
 390     private static final byte CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = (byte)0x4A;
 391     private static final byte METHOD_REFERENCE_TYPE_ARGUMENT = (byte)0x4B;
 392 
 393     private static TypeAnnotation parseTypeAnnotation(ByteBuffer buf,
 394             ConstantPool cp,
 395             AnnotatedElement baseDecl,
 396             Class<?> container) {

 397         TypeAnnotationTargetInfo ti = parseTargetInfo(buf);
 398         LocationInfo locationInfo = LocationInfo.parseLocationInfo(buf);
 399         Annotation a = AnnotationParser.parseAnnotation(buf, cp, container, false);
 400         if (ti == null) // Inside a method for example
 401             return null;
 402         return new TypeAnnotation(ti, locationInfo, a, baseDecl);




 403     }
 404 
 405     private static TypeAnnotationTargetInfo parseTargetInfo(ByteBuffer buf) {
 406         byte posCode = buf.get();
 407         switch(posCode) {
 408         case CLASS_TYPE_PARAMETER:
 409         case METHOD_TYPE_PARAMETER: {
 410             byte index = buf.get();
 411             TypeAnnotationTargetInfo res;
 412             if (posCode == CLASS_TYPE_PARAMETER)
 413                 res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_TYPE_PARAMETER,
 414                         index);
 415             else
 416                 res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_TYPE_PARAMETER,
 417                         index);
 418             return res;
 419             } // unreachable break;
 420         case CLASS_EXTENDS: {
 421             short index = buf.getShort();
 422             if (index == -1) {
 423                 return new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_EXTENDS);
 424             } else if (index >= 0) {
 425                 TypeAnnotationTargetInfo res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_IMPLEMENTS,
 426                         index);
 427                 return res;
 428             }} break;
 429         case CLASS_TYPE_PARAMETER_BOUND:
 430             return parse2ByteTarget(TypeAnnotationTarget.CLASS_TYPE_PARAMETER_BOUND, buf);
 431         case METHOD_TYPE_PARAMETER_BOUND:
 432             return parse2ByteTarget(TypeAnnotationTarget.METHOD_TYPE_PARAMETER_BOUND, buf);
 433         case FIELD:
 434             return new TypeAnnotationTargetInfo(TypeAnnotationTarget.FIELD);
 435         case METHOD_RETURN:
 436             return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RETURN);
 437         case METHOD_RECEIVER:
 438             return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RECEIVER);
 439         case METHOD_FORMAL_PARAMETER: {
 440             byte index = buf.get();
 441             return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_FORMAL_PARAMETER,
 442                     index);
 443             } //unreachable break;
 444         case THROWS:
 445             return parseShortTarget(TypeAnnotationTarget.THROWS, buf);
 446 
 447         /*
 448          * The ones below are inside method bodies, we don't care about them for core reflection
 449          * other than adjusting for them in the byte stream.
 450          */
 451         case LOCAL_VARIABLE:
 452         case RESOURCE_VARIABLE:
 453             short length = buf.getShort();
 454             for (int i = 0; i < length; ++i) {
 455                 short offset = buf.getShort();
 456                 short varLength = buf.getShort();
 457                 short index = buf.getShort();
 458             }
 459             return null;
 460         case EXCEPTION_PARAMETER: {


 469             }
 470             return null;
 471         case CAST:
 472         case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
 473         case METHOD_INVOCATION_TYPE_ARGUMENT:
 474         case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
 475         case METHOD_REFERENCE_TYPE_ARGUMENT: {
 476             short offset = buf.getShort();
 477             byte index = buf.get();
 478             }
 479             return null;
 480 
 481         default:
 482             // will throw error below
 483             break;
 484         }
 485         throw new AnnotationFormatError("Could not parse bytes for type annotations");
 486     }
 487 
 488     private static TypeAnnotationTargetInfo parseShortTarget(TypeAnnotationTarget target, ByteBuffer buf) {
 489         short index = buf.getShort();
 490         return new TypeAnnotationTargetInfo(target, index);
 491     }
 492     private static TypeAnnotationTargetInfo parse2ByteTarget(TypeAnnotationTarget target, ByteBuffer buf) {
 493         byte count = buf.get();
 494         byte secondaryIndex = buf.get();
 495         return new TypeAnnotationTargetInfo(target,
 496                                             count,
 497                                             secondaryIndex);
 498     }
 499 }


 377     private static final byte METHOD_FORMAL_PARAMETER = 0x16;
 378     private static final byte THROWS = 0x17;
 379     // Type Annotations inside method bodies
 380     private static final byte LOCAL_VARIABLE = (byte)0x40;
 381     private static final byte RESOURCE_VARIABLE = (byte)0x41;
 382     private static final byte EXCEPTION_PARAMETER = (byte)0x42;
 383     private static final byte INSTANCEOF = (byte)0x43;
 384     private static final byte NEW = (byte)0x44;
 385     private static final byte CONSTRUCTOR_REFERENCE = (byte)0x45;
 386     private static final byte METHOD_REFERENCE = (byte)0x46;
 387     private static final byte CAST = (byte)0x47;
 388     private static final byte CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = (byte)0x48;
 389     private static final byte METHOD_INVOCATION_TYPE_ARGUMENT = (byte)0x49;
 390     private static final byte CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = (byte)0x4A;
 391     private static final byte METHOD_REFERENCE_TYPE_ARGUMENT = (byte)0x4B;
 392 
 393     private static TypeAnnotation parseTypeAnnotation(ByteBuffer buf,
 394             ConstantPool cp,
 395             AnnotatedElement baseDecl,
 396             Class<?> container) {
 397         try {
 398             TypeAnnotationTargetInfo ti = parseTargetInfo(buf);
 399             LocationInfo locationInfo = LocationInfo.parseLocationInfo(buf);
 400             Annotation a = AnnotationParser.parseAnnotation(buf, cp, container, false);
 401             if (ti == null) // Inside a method for example
 402                 return null;
 403             return new TypeAnnotation(ti, locationInfo, a, baseDecl);
 404         } catch (IllegalArgumentException | // Bad type in const pool at specified index
 405                 BufferUnderflowException e) {
 406             throw new AnnotationFormatError(e);
 407         }
 408     }
 409 
 410     private static TypeAnnotationTargetInfo parseTargetInfo(ByteBuffer buf) {
 411         int posCode = buf.get() & 0xFF;
 412         switch(posCode) {
 413         case CLASS_TYPE_PARAMETER:
 414         case METHOD_TYPE_PARAMETER: {
 415             int index = buf.get() & 0xFF;
 416             TypeAnnotationTargetInfo res;
 417             if (posCode == CLASS_TYPE_PARAMETER)
 418                 res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_TYPE_PARAMETER,
 419                         index);
 420             else
 421                 res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_TYPE_PARAMETER,
 422                         index);
 423             return res;
 424             } // unreachable break;
 425         case CLASS_EXTENDS: {
 426             short index = buf.getShort(); //needs to be signed
 427             if (index == -1) {
 428                 return new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_EXTENDS);
 429             } else if (index >= 0) {
 430                 TypeAnnotationTargetInfo res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_IMPLEMENTS,
 431                         index);
 432                 return res;
 433             }} break;
 434         case CLASS_TYPE_PARAMETER_BOUND:
 435             return parse2ByteTarget(TypeAnnotationTarget.CLASS_TYPE_PARAMETER_BOUND, buf);
 436         case METHOD_TYPE_PARAMETER_BOUND:
 437             return parse2ByteTarget(TypeAnnotationTarget.METHOD_TYPE_PARAMETER_BOUND, buf);
 438         case FIELD:
 439             return new TypeAnnotationTargetInfo(TypeAnnotationTarget.FIELD);
 440         case METHOD_RETURN:
 441             return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RETURN);
 442         case METHOD_RECEIVER:
 443             return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RECEIVER);
 444         case METHOD_FORMAL_PARAMETER: {
 445             int index = buf.get() & 0xFF;
 446             return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_FORMAL_PARAMETER,
 447                     index);
 448             } //unreachable break;
 449         case THROWS:
 450             return parseShortTarget(TypeAnnotationTarget.THROWS, buf);
 451 
 452         /*
 453          * The ones below are inside method bodies, we don't care about them for core reflection
 454          * other than adjusting for them in the byte stream.
 455          */
 456         case LOCAL_VARIABLE:
 457         case RESOURCE_VARIABLE:
 458             short length = buf.getShort();
 459             for (int i = 0; i < length; ++i) {
 460                 short offset = buf.getShort();
 461                 short varLength = buf.getShort();
 462                 short index = buf.getShort();
 463             }
 464             return null;
 465         case EXCEPTION_PARAMETER: {


 474             }
 475             return null;
 476         case CAST:
 477         case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
 478         case METHOD_INVOCATION_TYPE_ARGUMENT:
 479         case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
 480         case METHOD_REFERENCE_TYPE_ARGUMENT: {
 481             short offset = buf.getShort();
 482             byte index = buf.get();
 483             }
 484             return null;
 485 
 486         default:
 487             // will throw error below
 488             break;
 489         }
 490         throw new AnnotationFormatError("Could not parse bytes for type annotations");
 491     }
 492 
 493     private static TypeAnnotationTargetInfo parseShortTarget(TypeAnnotationTarget target, ByteBuffer buf) {
 494         int index = buf.getShort() & 0xFFFF;
 495         return new TypeAnnotationTargetInfo(target, index);
 496     }
 497     private static TypeAnnotationTargetInfo parse2ByteTarget(TypeAnnotationTarget target, ByteBuffer buf) {
 498         int count = buf.get() & 0xFF;
 499         int secondaryIndex = buf.get() & 0xFF;
 500         return new TypeAnnotationTargetInfo(target,
 501                                             count,
 502                                             secondaryIndex);
 503     }
 504 }