8159511: Stack map validation
authorhseigel
Thu, 30 Jun 2016 08:11:30 -0400
changeset 41542 c705c10c4914
parent 41541 95362dbd84f5
child 41543 92f720daf12d
8159511: Stack map validation Reviewed-by: acorn, mschoene Contributed-by: harold.seigel@oracle.com
hotspot/src/share/vm/classfile/stackMapTableFormat.hpp
hotspot/src/share/vm/classfile/verifier.cpp
--- a/hotspot/src/share/vm/classfile/stackMapTableFormat.hpp	Wed Jun 29 11:52:27 2016 -0400
+++ b/hotspot/src/share/vm/classfile/stackMapTableFormat.hpp	Thu Jun 30 08:11:30 2016 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -203,6 +203,7 @@
   inline bool verify(address start, address end) const;
 
   inline void print_on(outputStream* st, int current_offset) const;
+  inline void print_truncated(outputStream* st, int current_offset) const;
 
   // Create as_xxx and is_xxx methods for the subtypes
 #define FRAME_TYPE_DECL(stackmap_frame_type, arg1, arg2) \
@@ -263,6 +264,10 @@
   void print_on(outputStream* st, int current_offset = -1) const {
     st->print("same_frame(@%d)", offset_delta() + current_offset);
   }
+
+  void print_truncated(outputStream* st, int current_offset = -1) const {
+    print_on(st, current_offset);
+  }
 };
 
 class same_frame_extended : public stack_map_frame {
@@ -309,6 +314,10 @@
   void print_on(outputStream* st, int current_offset = -1) const {
     st->print("same_frame_extended(@%d)", offset_delta() + current_offset);
   }
+
+  void print_truncated(outputStream* st, int current_offset = -1) const {
+    print_on(st, current_offset);
+  }
 };
 
 class same_locals_1_stack_item_frame : public stack_map_frame {
@@ -381,6 +390,11 @@
     types()->print_on(st);
     st->print(")");
   }
+
+  void print_truncated(outputStream* st, int current_offset = -1) const {
+    st->print("same_locals_1_stack_item_frame(@%d), output truncated, Stackmap exceeds table size.",
+              offset_delta() + current_offset);
+  }
 };
 
 class same_locals_1_stack_item_extended : public stack_map_frame {
@@ -446,6 +460,11 @@
     types()->print_on(st);
     st->print(")");
   }
+
+  void print_truncated(outputStream* st, int current_offset = -1) const {
+    st->print("same_locals_1_stack_item_extended(@%d), output truncated, Stackmap exceeds table size.",
+              offset_delta() + current_offset);
+  }
 };
 
 class chop_frame : public stack_map_frame {
@@ -511,6 +530,10 @@
   void print_on(outputStream* st, int current_offset = -1) const {
     st->print("chop_frame(@%d,%d)", offset_delta() + current_offset, chops());
   }
+
+  void print_truncated(outputStream* st, int current_offset = -1) const {
+    print_on(st, current_offset);
+  }
 };
 
 class append_frame : public stack_map_frame {
@@ -619,6 +642,11 @@
     }
     st->print(")");
   }
+
+  void print_truncated(outputStream* st, int current_offset = -1) const {
+    st->print("append_frame(@%d), output truncated, Stackmap exceeds table size.",
+              offset_delta() + current_offset);
+  }
 };
 
 class full_frame : public stack_map_frame {
@@ -784,6 +812,11 @@
     }
     st->print("})");
   }
+
+  void print_truncated(outputStream* st, int current_offset = -1) const {
+    st->print("full_frame(@%d), output truncated, Stackmap exceeds table size.",
+              offset_delta() + current_offset);
+  }
 };
 
 #define VIRTUAL_DISPATCH(stack_frame_type, func_name, args) \
@@ -841,6 +874,10 @@
   FOR_EACH_STACKMAP_FRAME_TYPE(VOID_VIRTUAL_DISPATCH, print_on, (st, offs));
 }
 
+void stack_map_frame::print_truncated(outputStream* st, int offs = -1) const {
+  FOR_EACH_STACKMAP_FRAME_TYPE(VOID_VIRTUAL_DISPATCH, print_truncated, (st, offs));
+}
+
 #undef VIRTUAL_DISPATCH
 #undef VOID_VIRTUAL_DISPATCH
 
--- a/hotspot/src/share/vm/classfile/verifier.cpp	Wed Jun 29 11:52:27 2016 -0400
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Thu Jun 30 08:11:30 2016 -0400
@@ -541,8 +541,19 @@
     stack_map_frame* sm_frame = sm_table->entries();
     streamIndentor si2(ss);
     int current_offset = -1;
+    // Subtract two from StackMapAttribute length because the length includes
+    // two bytes for number of table entries.
+    size_t sm_table_space = method->stackmap_data()->length() - 2;
     for (u2 i = 0; i < sm_table->number_of_entries(); ++i) {
       ss->indent();
+      size_t sm_frame_size = sm_frame->size();
+      // If the size of the next stackmap exceeds the length of the entire
+      // stackmap table then print a truncated message and return.
+      if (sm_frame_size > sm_table_space) {
+        sm_frame->print_truncated(ss, current_offset);
+        return;
+      }
+      sm_table_space -= sm_frame_size;
       sm_frame->print_on(ss, current_offset);
       ss->cr();
       current_offset += sm_frame->offset_delta();