Mercurial > hg > openjdk > jdk6 > hotspot
changeset 4062:6177a94d77fd
8035119: Fix exceptions to bytecode verification
Summary: Prevent ctor calls to super() and this() from avoidable code (try blocks, if stmts, etc.). Modified for openjdk6 hs23.
Reviewed-by: hseigel, coleenp, acorn, mschoene
author | chrisphi |
---|---|
date | Sun, 06 Jul 2014 12:44:28 -0400 |
parents | 1304e61f6271 |
children | ce8ddc29d76d |
files | src/share/vm/classfile/stackMapTable.cpp src/share/vm/classfile/verifier.cpp src/share/vm/classfile/verifier.hpp |
diffstat | 3 files changed, 48 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/vm/classfile/stackMapTable.cpp Mon Apr 07 09:22:54 2014 -0400 +++ b/src/share/vm/classfile/stackMapTable.cpp Sun Jul 06 12:44:28 2014 -0400 @@ -134,6 +134,7 @@ } // check if uninitialized objects exist on backward branches check_new_object(frame, target, CHECK_VERIFY(frame->verifier())); + frame->verifier()->update_furthest_jump(target); } void StackMapTable::check_new_object(
--- a/src/share/vm/classfile/verifier.cpp Mon Apr 07 09:22:54 2014 -0400 +++ b/src/share/vm/classfile/verifier.cpp Sun Jul 06 12:44:28 2014 -0400 @@ -378,6 +378,9 @@ bool no_control_flow = false; // Set to true when there is no direct control // flow from current instruction to the next // instruction in sequence + + set_furthest_jump(0); + Bytecodes::Code opcode; while (!bcs.is_last_bytecode()) { // Check for recursive re-verification before each bytecode. @@ -1891,6 +1894,34 @@ verify_error(bci, "Bad <init> method call"); return; } + + // Make sure that this call is not jumped over. + if (bci < furthest_jump()) { + verify_error(bci, "Bad <init> method call from inside of a branch"); + return; + } + + // Make sure that this call is not done from within a TRY block because + // that can result in returning an incomplete object. Simply checking + // (bci >= start_pc) also ensures that this call is not done after a TRY + // block. That is also illegal because this call must be the first Java + // statement in the constructor. + typeArrayHandle exhandlers (THREAD, _method->exception_table()); + for(int i = 0; i < exhandlers->length(); i += 4) { + /* + * Skip reading end_pc, handler_pc and catch_type_index. + * Looks like this if you need all of them: + * u2 start_pc = exhandlers->int_at(i++); + * u2 end_pc = exhandlers->int_at(i++); + * u2 handler_pc = exhandlers->int_at(i++); + * int catch_type_index = exhandlers->int_at(i++); + */ + u2 start_pc = exhandlers->int_at(i); + if (bci >= start_pc) { + verify_error(bci, "Bad <init> method call from after the start of a try block"); + } + } + current_frame->initialize_object(type, current_type()); *this_uninit = true; } else if (type.is_uninitialized()) {
--- a/src/share/vm/classfile/verifier.hpp Mon Apr 07 09:22:54 2014 -0400 +++ b/src/share/vm/classfile/verifier.hpp Sun Jul 06 12:44:28 2014 -0400 @@ -97,6 +97,9 @@ size_t _message_buffer_len; GrowableArray<Symbol*>* _symbols; // keep a list of symbols created + // Used to detect illegal jumps over calls to super() nd this() in ctors. + int32_t _furthest_jump; + void verify_method(methodHandle method, TRAPS); char* generate_code_data(methodHandle m, u4 code_length, TRAPS); void verify_exception_handler_table(u4 code_length, char* code_data, int& min, int& max, TRAPS); @@ -232,6 +235,19 @@ Symbol* create_temporary_symbol(const char *s, int length, TRAPS); static bool _verify_verbose; // for debugging + + // Keep track of the furthest branch done in a method to make sure that + // there are no branches over calls to super() or this() from inside of + // a constructor. + int32_t furthest_jump() { return _furthest_jump; } + + void set_furthest_jump(int32_t target) { + _furthest_jump = target; + } + + void update_furthest_jump(int32_t target) { + if (target > _furthest_jump) _furthest_jump = target; + } }; inline int ClassVerifier::change_sig_to_verificationType(