aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm/interpreter
diff options
context:
space:
mode:
authorkamg <none@none>2008-10-30 15:48:59 -0400
committerkamg <none@none>2008-10-30 15:48:59 -0400
commitf974a44683ca1c68a86149d89533394608fcaf7b (patch)
treec04d448c3064e4da016649215922a6eaeaec9123 /src/share/vm/interpreter
parent15e9a5265684eed94e1c5fc5ef0e2f54e1ddf358 (diff)
downloadjdk8u_hotspot-f974a44683ca1c68a86149d89533394608fcaf7b.tar.gz
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
Diffstat (limited to 'src/share/vm/interpreter')
-rw-r--r--src/share/vm/interpreter/bytecodeStream.cpp13
-rw-r--r--src/share/vm/interpreter/bytecodes.cpp20
-rw-r--r--src/share/vm/interpreter/bytecodes.hpp6
3 files changed, 29 insertions, 10 deletions
diff --git a/src/share/vm/interpreter/bytecodeStream.cpp b/src/share/vm/interpreter/bytecodeStream.cpp
index 9152907e1..bb051e530 100644
--- a/src/share/vm/interpreter/bytecodeStream.cpp
+++ b/src/share/vm/interpreter/bytecodeStream.cpp
@@ -28,8 +28,9 @@
Bytecodes::Code RawBytecodeStream::raw_next_special(Bytecodes::Code code) {
assert(!is_last_bytecode(), "should have been checked");
// set next bytecode position
- address bcp = RawBytecodeStream::bcp();
- int l = Bytecodes::raw_special_length_at(bcp);
+ address bcp = RawBytecodeStream::bcp();
+ address end = method()->code_base() + end_bci();
+ int l = Bytecodes::raw_special_length_at(bcp, end);
if (l <= 0 || (_bci + l) > _end_bci) {
code = Bytecodes::_illegal;
} else {
@@ -39,8 +40,12 @@ Bytecodes::Code RawBytecodeStream::raw_next_special(Bytecodes::Code code) {
_is_wide = false;
// check for special (uncommon) cases
if (code == Bytecodes::_wide) {
- code = (Bytecodes::Code)bcp[1];
- _is_wide = true;
+ if (bcp + 1 >= end) {
+ code = Bytecodes::_illegal;
+ } else {
+ code = (Bytecodes::Code)bcp[1];
+ _is_wide = true;
+ }
}
}
_code = code;
diff --git a/src/share/vm/interpreter/bytecodes.cpp b/src/share/vm/interpreter/bytecodes.cpp
index 1060a0797..396c87f95 100644
--- a/src/share/vm/interpreter/bytecodes.cpp
+++ b/src/share/vm/interpreter/bytecodes.cpp
@@ -54,13 +54,19 @@ Bytecodes::Code Bytecodes::non_breakpoint_code_at(address bcp, methodOop method)
return method->orig_bytecode_at(method->bci_from(bcp));
}
-int Bytecodes::special_length_at(address bcp) {
+int Bytecodes::special_length_at(address bcp, address end) {
Code code = code_at(bcp);
switch (code) {
case _wide:
+ if (end != NULL && bcp + 1 >= end) {
+ return -1; // don't read past end of code buffer
+ }
return wide_length_for(cast(*(bcp + 1)));
case _tableswitch:
{ address aligned_bcp = (address)round_to((intptr_t)bcp + 1, jintSize);
+ if (end != NULL && aligned_bcp + 3*jintSize >= end) {
+ return -1; // don't read past end of code buffer
+ }
jlong lo = (jint)Bytes::get_Java_u4(aligned_bcp + 1*jintSize);
jlong hi = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize);
jlong len = (aligned_bcp - bcp) + (3 + hi - lo + 1)*jintSize;
@@ -73,6 +79,9 @@ int Bytecodes::special_length_at(address bcp) {
case _fast_binaryswitch: // fall through
case _fast_linearswitch:
{ address aligned_bcp = (address)round_to((intptr_t)bcp + 1, jintSize);
+ if (end != NULL && aligned_bcp + 2*jintSize >= end) {
+ return -1; // don't read past end of code buffer
+ }
jlong npairs = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize);
jlong len = (aligned_bcp - bcp) + (2 + 2*npairs)*jintSize;
// only return len if it can be represented as a positive int;
@@ -90,14 +99,17 @@ int Bytecodes::special_length_at(address bcp) {
// verifier when reading in bytecode to verify. Other mechanisms that
// run at runtime (such as generateOopMaps) need to iterate over the code
// and don't expect to see breakpoints: they want to see the instruction
-// which was replaces so that they can get the correct length and find
+// which was replaced so that they can get the correct length and find
// the next bytecode.
-int Bytecodes::raw_special_length_at(address bcp) {
+//
+// 'end' indicates the end of the code buffer, which we should not try to read
+// past.
+int Bytecodes::raw_special_length_at(address bcp, address end) {
Code code = code_or_bp_at(bcp);
if (code == _breakpoint) {
return 1;
} else {
- return special_length_at(bcp);
+ return special_length_at(bcp, end);
}
}
diff --git a/src/share/vm/interpreter/bytecodes.hpp b/src/share/vm/interpreter/bytecodes.hpp
index 16ddc863b..f9201d953 100644
--- a/src/share/vm/interpreter/bytecodes.hpp
+++ b/src/share/vm/interpreter/bytecodes.hpp
@@ -340,8 +340,10 @@ class Bytecodes: AllStatic {
const char* wf = wide_format(code);
return (wf == NULL) ? 0 : (int)strlen(wf);
}
- static int special_length_at(address bcp);
- static int raw_special_length_at(address bcp);
+ // if 'end' is provided, it indicates the end of the code buffer which
+ // should not be read past when parsing.
+ static int special_length_at(address bcp, address end = NULL);
+ static int raw_special_length_at(address bcp, address end = NULL);
static int length_at (address bcp) { int l = length_for(code_at(bcp)); return l > 0 ? l : special_length_at(bcp); }
static int java_length_at (address bcp) { int l = length_for(java_code_at(bcp)); return l > 0 ? l : special_length_at(bcp); }
static bool is_java_code (Code code) { return 0 <= code && code < number_of_java_codes; }