Mercurial > hg > truffle
comparison src/share/vm/services/heapDumper.cpp @ 2143:17c778814856
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
author | coleenp |
---|---|
date | Fri, 14 Jan 2011 13:47:53 -0500 |
parents | f95d63e2154a |
children | 3582bf76420e |
comparison
equal
deleted
inserted
replaced
2142:8012aa3ccede | 2143:17c778814856 |
---|---|
451 } | 451 } |
452 } | 452 } |
453 | 453 |
454 DumpWriter::~DumpWriter() { | 454 DumpWriter::~DumpWriter() { |
455 // flush and close dump file | 455 // flush and close dump file |
456 if (file_descriptor() >= 0) { | 456 if (is_open()) { |
457 close(); | 457 close(); |
458 } | 458 } |
459 if (_buffer != NULL) os::free(_buffer); | 459 if (_buffer != NULL) os::free(_buffer); |
460 if (_error != NULL) os::free(_error); | 460 if (_error != NULL) os::free(_error); |
461 } | 461 } |
462 | 462 |
463 // closes dump file (if open) | 463 // closes dump file (if open) |
464 void DumpWriter::close() { | 464 void DumpWriter::close() { |
465 // flush and close dump file | 465 // flush and close dump file |
466 if (file_descriptor() >= 0) { | 466 if (is_open()) { |
467 flush(); | 467 flush(); |
468 ::close(file_descriptor()); | 468 ::close(file_descriptor()); |
469 set_file_descriptor(-1); | |
469 } | 470 } |
470 } | 471 } |
471 | 472 |
472 // write directly to the file | 473 // write directly to the file |
473 void DumpWriter::write_internal(void* s, int len) { | 474 void DumpWriter::write_internal(void* s, int len) { |
1933 } | 1934 } |
1934 | 1935 |
1935 void HeapDumper::dump_heap(bool oome) { | 1936 void HeapDumper::dump_heap(bool oome) { |
1936 static char base_path[JVM_MAXPATHLEN] = {'\0'}; | 1937 static char base_path[JVM_MAXPATHLEN] = {'\0'}; |
1937 static uint dump_file_seq = 0; | 1938 static uint dump_file_seq = 0; |
1938 char my_path[JVM_MAXPATHLEN] = {'\0'}; | 1939 char* my_path; |
1940 const int max_digit_chars = 20; | |
1941 | |
1942 const char* dump_file_name = "java_pid"; | |
1943 const char* dump_file_ext = ".hprof"; | |
1939 | 1944 |
1940 // The dump file defaults to java_pid<pid>.hprof in the current working | 1945 // The dump file defaults to java_pid<pid>.hprof in the current working |
1941 // directory. HeapDumpPath=<file> can be used to specify an alternative | 1946 // directory. HeapDumpPath=<file> can be used to specify an alternative |
1942 // dump file name or a directory where dump file is created. | 1947 // dump file name or a directory where dump file is created. |
1943 if (dump_file_seq == 0) { // first time in, we initialize base_path | 1948 if (dump_file_seq == 0) { // first time in, we initialize base_path |
1949 // Calculate potentially longest base path and check if we have enough | |
1950 // allocated statically. | |
1951 const size_t total_length = | |
1952 (HeapDumpPath == NULL ? 0 : strlen(HeapDumpPath)) + | |
1953 strlen(os::file_separator()) + max_digit_chars + | |
1954 strlen(dump_file_name) + strlen(dump_file_ext) + 1; | |
1955 if (total_length > sizeof(base_path)) { | |
1956 warning("Cannot create heap dump file. HeapDumpPath is too long."); | |
1957 return; | |
1958 } | |
1959 | |
1944 bool use_default_filename = true; | 1960 bool use_default_filename = true; |
1945 if (HeapDumpPath == NULL || HeapDumpPath[0] == '\0') { | 1961 if (HeapDumpPath == NULL || HeapDumpPath[0] == '\0') { |
1946 // HeapDumpPath=<file> not specified | 1962 // HeapDumpPath=<file> not specified |
1947 } else { | 1963 } else { |
1948 assert(strlen(HeapDumpPath) < sizeof(base_path), "HeapDumpPath too long"); | 1964 strncpy(base_path, HeapDumpPath, sizeof(base_path)); |
1949 strcpy(base_path, HeapDumpPath); | |
1950 // check if the path is a directory (must exist) | 1965 // check if the path is a directory (must exist) |
1951 DIR* dir = os::opendir(base_path); | 1966 DIR* dir = os::opendir(base_path); |
1952 if (dir == NULL) { | 1967 if (dir == NULL) { |
1953 use_default_filename = false; | 1968 use_default_filename = false; |
1954 } else { | 1969 } else { |
1958 size_t fs_len = strlen(os::file_separator()); | 1973 size_t fs_len = strlen(os::file_separator()); |
1959 if (strlen(base_path) >= fs_len) { | 1974 if (strlen(base_path) >= fs_len) { |
1960 char* end = base_path; | 1975 char* end = base_path; |
1961 end += (strlen(base_path) - fs_len); | 1976 end += (strlen(base_path) - fs_len); |
1962 if (strcmp(end, os::file_separator()) != 0) { | 1977 if (strcmp(end, os::file_separator()) != 0) { |
1963 assert(strlen(base_path) + strlen(os::file_separator()) < sizeof(base_path), | |
1964 "HeapDumpPath too long"); | |
1965 strcat(base_path, os::file_separator()); | 1978 strcat(base_path, os::file_separator()); |
1966 } | 1979 } |
1967 } | 1980 } |
1968 } | 1981 } |
1969 } | 1982 } |
1970 // If HeapDumpPath wasn't a file name then we append the default name | 1983 // If HeapDumpPath wasn't a file name then we append the default name |
1971 if (use_default_filename) { | 1984 if (use_default_filename) { |
1972 char fn[32]; | 1985 const size_t dlen = strlen(base_path); // if heap dump dir specified |
1973 sprintf(fn, "java_pid%d", os::current_process_id()); | 1986 jio_snprintf(&base_path[dlen], sizeof(base_path)-dlen, "%s%d%s", |
1974 assert(strlen(base_path) + strlen(fn) + strlen(".hprof") < sizeof(base_path), "HeapDumpPath too long"); | 1987 dump_file_name, os::current_process_id(), dump_file_ext); |
1975 strcat(base_path, fn); | 1988 } |
1976 strcat(base_path, ".hprof"); | 1989 const size_t len = strlen(base_path) + 1; |
1977 } | 1990 my_path = (char*)os::malloc(len); |
1978 assert(strlen(base_path) < sizeof(my_path), "Buffer too small"); | 1991 if (my_path == NULL) { |
1979 strcpy(my_path, base_path); | 1992 warning("Cannot create heap dump file. Out of system memory."); |
1993 return; | |
1994 } | |
1995 strncpy(my_path, base_path, len); | |
1980 } else { | 1996 } else { |
1981 // Append a sequence number id for dumps following the first | 1997 // Append a sequence number id for dumps following the first |
1982 char fn[33]; | 1998 const size_t len = strlen(base_path) + max_digit_chars + 2; // for '.' and \0 |
1983 sprintf(fn, ".%d", dump_file_seq); | 1999 my_path = (char*)os::malloc(len); |
1984 assert(strlen(base_path) + strlen(fn) < sizeof(my_path), "HeapDumpPath too long"); | 2000 if (my_path == NULL) { |
1985 strcpy(my_path, base_path); | 2001 warning("Cannot create heap dump file. Out of system memory."); |
1986 strcat(my_path, fn); | 2002 return; |
2003 } | |
2004 jio_snprintf(my_path, len, "%s.%d", base_path, dump_file_seq); | |
1987 } | 2005 } |
1988 dump_file_seq++; // increment seq number for next time we dump | 2006 dump_file_seq++; // increment seq number for next time we dump |
1989 | 2007 |
1990 HeapDumper dumper(false /* no GC before heap dump */, | 2008 HeapDumper dumper(false /* no GC before heap dump */, |
1991 true /* send to tty */, | 2009 true /* send to tty */, |
1992 oome /* pass along out-of-memory-error flag */); | 2010 oome /* pass along out-of-memory-error flag */); |
1993 dumper.dump(my_path); | 2011 dumper.dump(my_path); |
1994 } | 2012 os::free(my_path); |
2013 } |