# HG changeset patch # User vkempik # Date 1470907059 -10800 # Node ID fff265b310906946678b2efba34072f3af2131bd # Parent 57f957f4731d2fe04427afe6eddc8872611fbcf0 8159507: RuntimeVisibleAnnotation validation Reviewed-by: rprotacio diff -r 57f957f4731d -r fff265b31090 src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Tue Aug 09 13:24:03 2016 -0700 +++ b/src/share/vm/classfile/classFileParser.cpp Thu Aug 11 12:17:39 2016 +0300 @@ -944,11 +944,12 @@ runtime_visible_annotations_length = attribute_length; runtime_visible_annotations = cfs->get_u1_buffer(); assert(runtime_visible_annotations != NULL, "null visible annotations"); + cfs->guarantee_more(runtime_visible_annotations_length, CHECK); parse_annotations(runtime_visible_annotations, runtime_visible_annotations_length, parsed_annotations, CHECK); - cfs->skip_u1(runtime_visible_annotations_length, CHECK); + cfs->skip_u1_fast(runtime_visible_annotations_length); } else if (PreserveAllAnnotations && attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { runtime_invisible_annotations_length = attribute_length; runtime_invisible_annotations = cfs->get_u1_buffer(); @@ -1655,6 +1656,11 @@ return index; } +// Safely increment index by val if does not pass limit +#define SAFE_ADD(index, limit, val) \ +if (index >= limit - val) return limit; \ +index += val; + // Skip an annotation value. Return >=limit if there is any problem. int ClassFileParser::skip_annotation_value(u1* buffer, int limit, int index) { // value := switch (tag:u1) { @@ -1665,19 +1671,19 @@ // case @: annotation; // case s: s_con:u2; // } - if ((index += 1) >= limit) return limit; // read tag + SAFE_ADD(index, limit, 1); // read tag u1 tag = buffer[index-1]; switch (tag) { case 'B': case 'C': case 'I': case 'S': case 'Z': case 'D': case 'F': case 'J': case 'c': case 's': - index += 2; // skip con or s_con + SAFE_ADD(index, limit, 2); // skip con or s_con break; case 'e': - index += 4; // skip e_class, e_name + SAFE_ADD(index, limit, 4); // skip e_class, e_name break; case '[': { - if ((index += 2) >= limit) return limit; // read nval + SAFE_ADD(index, limit, 2); // read nval int nval = Bytes::get_Java_u2(buffer+index-2); while (--nval >= 0 && index < limit) { index = skip_annotation_value(buffer, limit, index); @@ -1699,8 +1705,8 @@ ClassFileParser::AnnotationCollector* coll, TRAPS) { // annotations := do(nann:u2) {annotation} - int index = 0; - if ((index += 2) >= limit) return; // read nann + int index = 2; + if (index >= limit) return; // read nann int nann = Bytes::get_Java_u2(buffer+index-2); enum { // initial annotation layout atype_off = 0, // utf8 such as 'Ljava/lang/annotation/Retention;' @@ -1719,7 +1725,8 @@ s_size = 9, min_size = 6 // smallest possible size (zero members) }; - while ((--nann) >= 0 && (index-2 + min_size <= limit)) { + // Cannot add min_size to index in case of overflow MAX_INT + while ((--nann) >= 0 && (index-2 <= limit - min_size)) { int index0 = index; index = skip_annotation(buffer, limit, index); u1* abase = buffer + index0; @@ -2324,10 +2331,11 @@ runtime_visible_annotations_length = method_attribute_length; runtime_visible_annotations = cfs->get_u1_buffer(); assert(runtime_visible_annotations != NULL, "null visible annotations"); + cfs->guarantee_more(runtime_visible_annotations_length, CHECK_(nullHandle)); parse_annotations(runtime_visible_annotations, runtime_visible_annotations_length, &parsed_annotations, CHECK_(nullHandle)); - cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle)); + cfs->skip_u1_fast(runtime_visible_annotations_length); } else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { runtime_invisible_annotations_length = method_attribute_length; runtime_invisible_annotations = cfs->get_u1_buffer(); @@ -2953,11 +2961,12 @@ runtime_visible_annotations_length = attribute_length; runtime_visible_annotations = cfs->get_u1_buffer(); assert(runtime_visible_annotations != NULL, "null visible annotations"); + cfs->guarantee_more(runtime_visible_annotations_length, CHECK); parse_annotations(runtime_visible_annotations, runtime_visible_annotations_length, parsed_annotations, CHECK); - cfs->skip_u1(runtime_visible_annotations_length, CHECK); + cfs->skip_u1_fast(runtime_visible_annotations_length); } else if (PreserveAllAnnotations && tag == vmSymbols::tag_runtime_invisible_annotations()) { runtime_invisible_annotations_length = attribute_length; runtime_invisible_annotations = cfs->get_u1_buffer();