提交 13b371c8 编写于 作者: C coleenp

6811367: Fix code in HeapDumper::dump_heap() to avoid buffer overrun

Summary: Check buffer size before using and use dynamic buffer sizes for subsequent calls.
Reviewed-by: kamg, dholmes
上级 35cd0661
...@@ -453,7 +453,7 @@ DumpWriter::DumpWriter(const char* path) { ...@@ -453,7 +453,7 @@ DumpWriter::DumpWriter(const char* path) {
DumpWriter::~DumpWriter() { DumpWriter::~DumpWriter() {
// flush and close dump file // flush and close dump file
if (file_descriptor() >= 0) { if (is_open()) {
close(); close();
} }
if (_buffer != NULL) os::free(_buffer); if (_buffer != NULL) os::free(_buffer);
...@@ -463,9 +463,10 @@ DumpWriter::~DumpWriter() { ...@@ -463,9 +463,10 @@ DumpWriter::~DumpWriter() {
// closes dump file (if open) // closes dump file (if open)
void DumpWriter::close() { void DumpWriter::close() {
// flush and close dump file // flush and close dump file
if (file_descriptor() >= 0) { if (is_open()) {
flush(); flush();
::close(file_descriptor()); ::close(file_descriptor());
set_file_descriptor(-1);
} }
} }
...@@ -1935,18 +1936,32 @@ void HeapDumper::dump_heap() { ...@@ -1935,18 +1936,32 @@ void HeapDumper::dump_heap() {
void HeapDumper::dump_heap(bool oome) { void HeapDumper::dump_heap(bool oome) {
static char base_path[JVM_MAXPATHLEN] = {'\0'}; static char base_path[JVM_MAXPATHLEN] = {'\0'};
static uint dump_file_seq = 0; static uint dump_file_seq = 0;
char my_path[JVM_MAXPATHLEN] = {'\0'}; char* my_path;
const int max_digit_chars = 20;
const char* dump_file_name = "java_pid";
const char* dump_file_ext = ".hprof";
// The dump file defaults to java_pid<pid>.hprof in the current working // The dump file defaults to java_pid<pid>.hprof in the current working
// directory. HeapDumpPath=<file> can be used to specify an alternative // directory. HeapDumpPath=<file> can be used to specify an alternative
// dump file name or a directory where dump file is created. // dump file name or a directory where dump file is created.
if (dump_file_seq == 0) { // first time in, we initialize base_path if (dump_file_seq == 0) { // first time in, we initialize base_path
// Calculate potentially longest base path and check if we have enough
// allocated statically.
const size_t total_length =
(HeapDumpPath == NULL ? 0 : strlen(HeapDumpPath)) +
strlen(os::file_separator()) + max_digit_chars +
strlen(dump_file_name) + strlen(dump_file_ext) + 1;
if (total_length > sizeof(base_path)) {
warning("Cannot create heap dump file. HeapDumpPath is too long.");
return;
}
bool use_default_filename = true; bool use_default_filename = true;
if (HeapDumpPath == NULL || HeapDumpPath[0] == '\0') { if (HeapDumpPath == NULL || HeapDumpPath[0] == '\0') {
// HeapDumpPath=<file> not specified // HeapDumpPath=<file> not specified
} else { } else {
assert(strlen(HeapDumpPath) < sizeof(base_path), "HeapDumpPath too long"); strncpy(base_path, HeapDumpPath, sizeof(base_path));
strcpy(base_path, HeapDumpPath);
// check if the path is a directory (must exist) // check if the path is a directory (must exist)
DIR* dir = os::opendir(base_path); DIR* dir = os::opendir(base_path);
if (dir == NULL) { if (dir == NULL) {
...@@ -1960,8 +1975,6 @@ void HeapDumper::dump_heap(bool oome) { ...@@ -1960,8 +1975,6 @@ void HeapDumper::dump_heap(bool oome) {
char* end = base_path; char* end = base_path;
end += (strlen(base_path) - fs_len); end += (strlen(base_path) - fs_len);
if (strcmp(end, os::file_separator()) != 0) { if (strcmp(end, os::file_separator()) != 0) {
assert(strlen(base_path) + strlen(os::file_separator()) < sizeof(base_path),
"HeapDumpPath too long");
strcat(base_path, os::file_separator()); strcat(base_path, os::file_separator());
} }
} }
...@@ -1969,21 +1982,26 @@ void HeapDumper::dump_heap(bool oome) { ...@@ -1969,21 +1982,26 @@ void HeapDumper::dump_heap(bool oome) {
} }
// If HeapDumpPath wasn't a file name then we append the default name // If HeapDumpPath wasn't a file name then we append the default name
if (use_default_filename) { if (use_default_filename) {
char fn[32]; const size_t dlen = strlen(base_path); // if heap dump dir specified
sprintf(fn, "java_pid%d", os::current_process_id()); jio_snprintf(&base_path[dlen], sizeof(base_path)-dlen, "%s%d%s",
assert(strlen(base_path) + strlen(fn) + strlen(".hprof") < sizeof(base_path), "HeapDumpPath too long"); dump_file_name, os::current_process_id(), dump_file_ext);
strcat(base_path, fn); }
strcat(base_path, ".hprof"); const size_t len = strlen(base_path) + 1;
} my_path = (char*)os::malloc(len);
assert(strlen(base_path) < sizeof(my_path), "Buffer too small"); if (my_path == NULL) {
strcpy(my_path, base_path); warning("Cannot create heap dump file. Out of system memory.");
return;
}
strncpy(my_path, base_path, len);
} else { } else {
// Append a sequence number id for dumps following the first // Append a sequence number id for dumps following the first
char fn[33]; const size_t len = strlen(base_path) + max_digit_chars + 2; // for '.' and \0
sprintf(fn, ".%d", dump_file_seq); my_path = (char*)os::malloc(len);
assert(strlen(base_path) + strlen(fn) < sizeof(my_path), "HeapDumpPath too long"); if (my_path == NULL) {
strcpy(my_path, base_path); warning("Cannot create heap dump file. Out of system memory.");
strcat(my_path, fn); return;
}
jio_snprintf(my_path, len, "%s.%d", base_path, dump_file_seq);
} }
dump_file_seq++; // increment seq number for next time we dump dump_file_seq++; // increment seq number for next time we dump
...@@ -1991,4 +2009,5 @@ void HeapDumper::dump_heap(bool oome) { ...@@ -1991,4 +2009,5 @@ void HeapDumper::dump_heap(bool oome) {
true /* send to tty */, true /* send to tty */,
oome /* pass along out-of-memory-error flag */); oome /* pass along out-of-memory-error flag */);
dumper.dump(my_path); dumper.dump(my_path);
os::free(my_path);
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册