Thu, 30 Oct 2008 15:48:59 -0400
6756528: Bytecodes::special_length_at reads past end of code buffer
Summary: Add end-of-buffer indicator for paths used by the verifier
Reviewed-by: acorn, coleenp
1.1 --- a/src/share/vm/interpreter/bytecodeStream.cpp Wed Oct 22 20:47:00 2008 -0700 1.2 +++ b/src/share/vm/interpreter/bytecodeStream.cpp Thu Oct 30 15:48:59 2008 -0400 1.3 @@ -28,8 +28,9 @@ 1.4 Bytecodes::Code RawBytecodeStream::raw_next_special(Bytecodes::Code code) { 1.5 assert(!is_last_bytecode(), "should have been checked"); 1.6 // set next bytecode position 1.7 - address bcp = RawBytecodeStream::bcp(); 1.8 - int l = Bytecodes::raw_special_length_at(bcp); 1.9 + address bcp = RawBytecodeStream::bcp(); 1.10 + address end = method()->code_base() + end_bci(); 1.11 + int l = Bytecodes::raw_special_length_at(bcp, end); 1.12 if (l <= 0 || (_bci + l) > _end_bci) { 1.13 code = Bytecodes::_illegal; 1.14 } else { 1.15 @@ -39,8 +40,12 @@ 1.16 _is_wide = false; 1.17 // check for special (uncommon) cases 1.18 if (code == Bytecodes::_wide) { 1.19 - code = (Bytecodes::Code)bcp[1]; 1.20 - _is_wide = true; 1.21 + if (bcp + 1 >= end) { 1.22 + code = Bytecodes::_illegal; 1.23 + } else { 1.24 + code = (Bytecodes::Code)bcp[1]; 1.25 + _is_wide = true; 1.26 + } 1.27 } 1.28 } 1.29 _code = code;
2.1 --- a/src/share/vm/interpreter/bytecodes.cpp Wed Oct 22 20:47:00 2008 -0700 2.2 +++ b/src/share/vm/interpreter/bytecodes.cpp Thu Oct 30 15:48:59 2008 -0400 2.3 @@ -54,13 +54,19 @@ 2.4 return method->orig_bytecode_at(method->bci_from(bcp)); 2.5 } 2.6 2.7 -int Bytecodes::special_length_at(address bcp) { 2.8 +int Bytecodes::special_length_at(address bcp, address end) { 2.9 Code code = code_at(bcp); 2.10 switch (code) { 2.11 case _wide: 2.12 + if (end != NULL && bcp + 1 >= end) { 2.13 + return -1; // don't read past end of code buffer 2.14 + } 2.15 return wide_length_for(cast(*(bcp + 1))); 2.16 case _tableswitch: 2.17 { address aligned_bcp = (address)round_to((intptr_t)bcp + 1, jintSize); 2.18 + if (end != NULL && aligned_bcp + 3*jintSize >= end) { 2.19 + return -1; // don't read past end of code buffer 2.20 + } 2.21 jlong lo = (jint)Bytes::get_Java_u4(aligned_bcp + 1*jintSize); 2.22 jlong hi = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize); 2.23 jlong len = (aligned_bcp - bcp) + (3 + hi - lo + 1)*jintSize; 2.24 @@ -73,6 +79,9 @@ 2.25 case _fast_binaryswitch: // fall through 2.26 case _fast_linearswitch: 2.27 { address aligned_bcp = (address)round_to((intptr_t)bcp + 1, jintSize); 2.28 + if (end != NULL && aligned_bcp + 2*jintSize >= end) { 2.29 + return -1; // don't read past end of code buffer 2.30 + } 2.31 jlong npairs = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize); 2.32 jlong len = (aligned_bcp - bcp) + (2 + 2*npairs)*jintSize; 2.33 // only return len if it can be represented as a positive int; 2.34 @@ -90,14 +99,17 @@ 2.35 // verifier when reading in bytecode to verify. Other mechanisms that 2.36 // run at runtime (such as generateOopMaps) need to iterate over the code 2.37 // and don't expect to see breakpoints: they want to see the instruction 2.38 -// which was replaces so that they can get the correct length and find 2.39 +// which was replaced so that they can get the correct length and find 2.40 // the next bytecode. 2.41 -int Bytecodes::raw_special_length_at(address bcp) { 2.42 +// 2.43 +// 'end' indicates the end of the code buffer, which we should not try to read 2.44 +// past. 2.45 +int Bytecodes::raw_special_length_at(address bcp, address end) { 2.46 Code code = code_or_bp_at(bcp); 2.47 if (code == _breakpoint) { 2.48 return 1; 2.49 } else { 2.50 - return special_length_at(bcp); 2.51 + return special_length_at(bcp, end); 2.52 } 2.53 } 2.54
3.1 --- a/src/share/vm/interpreter/bytecodes.hpp Wed Oct 22 20:47:00 2008 -0700 3.2 +++ b/src/share/vm/interpreter/bytecodes.hpp Thu Oct 30 15:48:59 2008 -0400 3.3 @@ -340,8 +340,10 @@ 3.4 const char* wf = wide_format(code); 3.5 return (wf == NULL) ? 0 : (int)strlen(wf); 3.6 } 3.7 - static int special_length_at(address bcp); 3.8 - static int raw_special_length_at(address bcp); 3.9 + // if 'end' is provided, it indicates the end of the code buffer which 3.10 + // should not be read past when parsing. 3.11 + static int special_length_at(address bcp, address end = NULL); 3.12 + static int raw_special_length_at(address bcp, address end = NULL); 3.13 static int length_at (address bcp) { int l = length_for(code_at(bcp)); return l > 0 ? l : special_length_at(bcp); } 3.14 static int java_length_at (address bcp) { int l = length_for(java_code_at(bcp)); return l > 0 ? l : special_length_at(bcp); } 3.15 static bool is_java_code (Code code) { return 0 <= code && code < number_of_java_codes; }