From 8de5c68f44893997440a5d98a61978c1bb52b54a Mon Sep 17 00:00:00 2001 From: hseigel Date: Thu, 30 Jun 2016 08:11:30 -0400 Subject: [PATCH] 8159511: Stack map validation Reviewed-by: acorn, mschoene Contributed-by: harold.seigel@oracle.com --- .../vm/classfile/stackMapTableFormat.hpp | 39 ++++++++++++++++++- src/share/vm/classfile/verifier.cpp | 11 ++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/share/vm/classfile/stackMapTableFormat.hpp b/src/share/vm/classfile/stackMapTableFormat.hpp index 8bfa625ca..469a6b5ad 100644 --- a/src/share/vm/classfile/stackMapTableFormat.hpp +++ b/src/share/vm/classfile/stackMapTableFormat.hpp @@ -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 @@ class stack_map_frame { 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 @@ class same_frame : public stack_map_frame { 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 @@ class same_frame_extended : public stack_map_frame { 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 @@ class same_locals_1_stack_item_frame : public stack_map_frame { 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 @@ class same_locals_1_stack_item_extended : public stack_map_frame { 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 @@ class chop_frame : public stack_map_frame { 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 @@ class append_frame : public stack_map_frame { } 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 @@ class full_frame : public stack_map_frame { } 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 @@ void stack_map_frame::print_on(outputStream* st, int offs = -1) const { 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 diff --git a/src/share/vm/classfile/verifier.cpp b/src/share/vm/classfile/verifier.cpp index e1f9f2381..58bd4f7ab 100644 --- a/src/share/vm/classfile/verifier.cpp +++ b/src/share/vm/classfile/verifier.cpp @@ -504,8 +504,19 @@ void ErrorContext::stackmap_details(outputStream* ss, const Method* method) cons 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(); -- GitLab