aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordsamersoff <none@none>2011-03-30 19:38:07 +0400
committerdsamersoff <none@none>2011-03-30 19:38:07 +0400
commit3b3c730997cbe9d901db0ca96ef82df9ffedd34c (patch)
tree74befcb6835f7c1baa66f22415168addb47da584 /src
parent5f4a77619ded261657dc385d260c6875081dbf5c (diff)
7017193: Small memory leak in get_stack_bounds os::create_stack_guard_pages
Summary: getline() returns -1 but still allocate memory for str Reviewed-by: dcubed, coleenp
Diffstat (limited to 'src')
-rw-r--r--src/os/linux/vm/os_linux.cpp56
-rw-r--r--src/share/vm/runtime/os.cpp38
-rw-r--r--src/share/vm/runtime/os.hpp4
3 files changed, 67 insertions, 31 deletions
diff --git a/src/os/linux/vm/os_linux.cpp b/src/os/linux/vm/os_linux.cpp
index a3975d898..19d87fe7f 100644
--- a/src/os/linux/vm/os_linux.cpp
+++ b/src/os/linux/vm/os_linux.cpp
@@ -2648,45 +2648,39 @@ bool os::uncommit_memory(char* addr, size_t size) {
// writing thread stacks don't use growable mappings (i.e. those
// creeated with MAP_GROWSDOWN), and aren't marked "[stack]", so this
// only applies to the main thread.
-static bool
-get_stack_bounds(uintptr_t *bottom, uintptr_t *top)
-{
- FILE *f = fopen("/proc/self/maps", "r");
- if (f == NULL)
- return false;
- while (!feof(f)) {
- size_t dummy;
- char *str = NULL;
- ssize_t len = getline(&str, &dummy, f);
- if (len == -1) {
- fclose(f);
- return false;
- }
+static
+bool get_stack_bounds(uintptr_t *bottom, uintptr_t *top) {
- if (len > 0 && str[len-1] == '\n') {
- str[len-1] = 0;
- len--;
- }
+ char buf[128];
+ int fd, sz;
+
+ if ((fd = ::open("/proc/self/maps", O_RDONLY)) < 0) {
+ return false;
+ }
- static const char *stack_str = "[stack]";
- if (len > (ssize_t)strlen(stack_str)
- && (strcmp(str + len - strlen(stack_str), stack_str) == 0)) {
- if (sscanf(str, "%" SCNxPTR "-%" SCNxPTR, bottom, top) == 2) {
- uintptr_t sp = (uintptr_t)__builtin_frame_address(0);
- if (sp >= *bottom && sp <= *top) {
- free(str);
- fclose(f);
- return true;
+ const char kw[] = "[stack]";
+ const int kwlen = sizeof(kw)-1;
+
+ // Address part of /proc/self/maps couldn't be more than 128 bytes
+ while ((sz = os::get_line_chars(fd, buf, sizeof(buf))) > 0) {
+ if (sz > kwlen && ::memcmp(buf+sz-kwlen, kw, kwlen) == 0) {
+ // Extract addresses
+ if (sscanf(buf, "%" SCNxPTR "-%" SCNxPTR, bottom, top) == 2) {
+ uintptr_t sp = (uintptr_t) __builtin_frame_address(0);
+ if (sp >= *bottom && sp <= *top) {
+ ::close(fd);
+ return true;
+ }
}
- }
- }
- free(str);
+ }
}
- fclose(f);
+
+ ::close(fd);
return false;
}
+
// If the (growable) stack mapping already extends beyond the point
// where we're going to put our guard pages, truncate the mapping at
// that point by munmap()ping it. This ensures that when we later
diff --git a/src/share/vm/runtime/os.cpp b/src/share/vm/runtime/os.cpp
index cf949071b..0f84de3d1 100644
--- a/src/share/vm/runtime/os.cpp
+++ b/src/share/vm/runtime/os.cpp
@@ -1291,3 +1291,41 @@ bool os::is_server_class_machine() {
}
return result;
}
+
+// Read file line by line, if line is longer than bsize,
+// skip rest of line.
+int os::get_line_chars(int fd, char* buf, const size_t bsize){
+ size_t sz, i = 0;
+
+ // read until EOF, EOL or buf is full
+ while ((sz = (int) read(fd, &buf[i], 1)) == 1 && i < (bsize-1) && buf[i] != '\n') {
+ ++i;
+ }
+
+ if (buf[i] == '\n') {
+ // EOL reached so ignore EOL character and return
+
+ buf[i] = 0;
+ return (int) i;
+ }
+
+ buf[i+1] = 0;
+
+ if (sz != 1) {
+ // EOF reached. if we read chars before EOF return them and
+ // return EOF on next call otherwise return EOF
+
+ return (i == 0) ? -1 : (int) i;
+ }
+
+ // line is longer than size of buf, skip to EOL
+ int ch;
+ while (read(fd, &ch, 1) == 1 && ch != '\n') {
+ // Do nothing
+ }
+
+ // return initial part of line that fits in buf.
+ // If we reached EOF, it will be returned on next call.
+
+ return (int) i;
+}
diff --git a/src/share/vm/runtime/os.hpp b/src/share/vm/runtime/os.hpp
index b9b9d0c05..13a266ea8 100644
--- a/src/share/vm/runtime/os.hpp
+++ b/src/share/vm/runtime/os.hpp
@@ -658,6 +658,10 @@ class os: AllStatic {
// Hook for os specific jvm options that we don't want to abort on seeing
static bool obsolete_option(const JavaVMOption *option);
+ // Read file line by line. If line is longer than bsize,
+ // rest of line is skipped. Returns number of bytes read or -1 on EOF
+ static int get_line_chars(int fd, char *buf, const size_t bsize);
+
// Platform dependent stuff
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.hpp"