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 }