changeset 8191:fff265b31090

8159507: RuntimeVisibleAnnotation validation Reviewed-by: rprotacio
author vkempik
date Thu, 11 Aug 2016 12:17:39 +0300
parents 57f957f4731d
children 6009b66f2fa1
files src/share/vm/classfile/classFileParser.cpp
diffstat 1 files changed, 19 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- 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();