7104960: JSR 292: +VerifyMethodHandles in product JVM can overflow buffer

Reviewed-by: kvn, jrose, twisti
This commit is contained in:
Tom Rodriguez 2011-11-08 10:31:53 -08:00
parent 0bc2963b7d
commit 051c64ad4d
9 changed files with 74 additions and 32 deletions

View file

@ -26,6 +26,7 @@
#include "asm/codeBuffer.hpp"
#include "compiler/disassembler.hpp"
#include "utilities/copy.hpp"
#include "utilities/xmlstream.hpp"
// The structure of a CodeSection:
//
@ -81,7 +82,7 @@ typedef CodeBuffer::csize_t csize_t; // file-local definition
CodeBuffer::CodeBuffer(CodeBlob* blob) {
initialize_misc("static buffer");
initialize(blob->content_begin(), blob->content_size());
assert(verify_section_allocation(), "initial use of buffer OK");
verify_section_allocation();
}
void CodeBuffer::initialize(csize_t code_size, csize_t locs_size) {
@ -108,17 +109,18 @@ void CodeBuffer::initialize(csize_t code_size, csize_t locs_size) {
_insts.initialize_locs(locs_size / sizeof(relocInfo));
}
assert(verify_section_allocation(), "initial use of blob is OK");
verify_section_allocation();
}
CodeBuffer::~CodeBuffer() {
verify_section_allocation();
// If we allocate our code buffer from the CodeCache
// via a BufferBlob, and it's not permanent, then
// free the BufferBlob.
// The rest of the memory will be freed when the ResourceObj
// is released.
assert(verify_section_allocation(), "final storage configuration still OK");
for (CodeBuffer* cb = this; cb != NULL; cb = cb->before_expand()) {
// Previous incarnations of this buffer are held live, so that internal
// addresses constructed before expansions will not be confused.
@ -484,7 +486,7 @@ void CodeBuffer::compute_final_layout(CodeBuffer* dest) const {
// Done calculating sections; did it come out to the right end?
assert(buf_offset == total_content_size(), "sanity");
assert(dest->verify_section_allocation(), "final configuration works");
dest->verify_section_allocation();
}
csize_t CodeBuffer::total_offset_of(CodeSection* cs) const {
@ -810,7 +812,7 @@ void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) {
_decode_begin = NULL; // sanity
// Make certain that the new sections are all snugly inside the new blob.
assert(verify_section_allocation(), "expanded allocation is ship-shape");
verify_section_allocation();
#ifndef PRODUCT
if (PrintNMethods && (WizardMode || Verbose)) {
@ -839,35 +841,48 @@ void CodeBuffer::take_over_code_from(CodeBuffer* cb) {
DEBUG_ONLY(cb->_blob = (BufferBlob*)badAddress);
}
#ifdef ASSERT
bool CodeBuffer::verify_section_allocation() {
void CodeBuffer::verify_section_allocation() {
address tstart = _total_start;
if (tstart == badAddress) return true; // smashed by set_blob(NULL)
if (tstart == badAddress) return; // smashed by set_blob(NULL)
address tend = tstart + _total_size;
if (_blob != NULL) {
assert(tstart >= _blob->content_begin(), "sanity");
assert(tend <= _blob->content_end(), "sanity");
guarantee(tstart >= _blob->content_begin(), "sanity");
guarantee(tend <= _blob->content_end(), "sanity");
}
// Verify disjointness.
for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) {
CodeSection* sect = code_section(n);
if (!sect->is_allocated() || sect->is_empty()) continue;
assert((intptr_t)sect->start() % sect->alignment() == 0
guarantee((intptr_t)sect->start() % sect->alignment() == 0
|| sect->is_empty() || _blob == NULL,
"start is aligned");
for (int m = (int) SECT_FIRST; m < (int) SECT_LIMIT; m++) {
CodeSection* other = code_section(m);
if (!other->is_allocated() || other == sect) continue;
assert(!other->contains(sect->start() ), "sanity");
guarantee(!other->contains(sect->start() ), "sanity");
// limit is an exclusive address and can be the start of another
// section.
assert(!other->contains(sect->limit() - 1), "sanity");
guarantee(!other->contains(sect->limit() - 1), "sanity");
}
assert(sect->end() <= tend, "sanity");
guarantee(sect->end() <= tend, "sanity");
guarantee(sect->end() <= sect->limit(), "sanity");
}
}
void CodeBuffer::log_section_sizes(const char* name) {
if (xtty != NULL) {
// log info about buffer usage
xtty->print_cr("<blob name='%s' size='%d'>", name, _total_size);
for (int n = (int) CodeBuffer::SECT_FIRST; n < (int) CodeBuffer::SECT_LIMIT; n++) {
CodeSection* sect = code_section(n);
if (!sect->is_allocated() || sect->is_empty()) continue;
xtty->print_cr("<sect index='%d' size='" SIZE_FORMAT "' free='" SIZE_FORMAT "'/>",
n, sect->limit() - sect->start(), sect->limit() - sect->end());
}
xtty->print_cr("</blob>");
}
return true;
}
#endif //ASSERT
#ifndef PRODUCT
@ -895,7 +910,6 @@ void CodeBuffer::block_comment(intptr_t offset, const char * comment) {
_comments.add_comment(offset, comment);
}
class CodeComment: public CHeapObj {
private:
friend class CodeComments;