summaryrefslogtreecommitdiff
path: root/os_dep.c
diff options
context:
space:
mode:
authorivmai <ivmai>2011-03-13 20:37:24 +0100
committerIvan Maidanski <ivmai@mail.ru>2011-07-26 19:06:56 +0200
commit618a4c49d9c8c50e95f075e11e826aded68518cd (patch)
tree8c90cb5dd2fcf502fcdf9dde7f9ee6f5e6ad9276 /os_dep.c
parent667fb0512a70f7756a2c64f0e71c03e1e49a8a4c (diff)
2011-03-13 Ivan Maidanski <ivmai@mail.ru>
* dbg_mlc.c (GC_get_back_ptr_info, GC_print_obj, GC_print_smashed_obj, GC_debug_free_inner): Add a code for a LINT-like tool to instruct it that the function is invoked only with valid parameters (otherwise a SEGV is ok); recognize LINT2 new macro. * misc.c (GC_abort): Instruct a LINT-like tool that the function never returns in fact. * os_dep.c (GC_linux_stack_base): Check for read buffer overflow; close the file immediately after read; use STRTOULL() instead of decoding the address number manually. * include/private/gc_priv.h (EXPECT): Don't specify outcome for a LINT-like tool. * include/private/gc_priv.h (GC_all_interior_pointers): Instruct a LINT-like tool that the value is restricted to zero and one only (required since the variable is global and its value is used as a part of array index expression is some places).
Diffstat (limited to 'os_dep.c')
-rw-r--r--os_dep.c42
1 files changed, 27 insertions, 15 deletions
diff --git a/os_dep.c b/os_dep.c
index 0b9813e..c876a09 100644
--- a/os_dep.c
+++ b/os_dep.c
@@ -1046,9 +1046,8 @@ GC_INNER word GC_page_size = 0;
/* Should probably call the real read, if read is wrapped. */
char stat_buf[STAT_BUF_SIZE];
int f;
- char c;
- word result = 0;
- size_t i, buf_offset = 0;
+ word result;
+ size_t i, buf_offset = 0, len;
/* First try the easy way. This should work for glibc 2.2 */
/* This fails in a prelinked ("prelink" command) executable */
@@ -1077,24 +1076,37 @@ GC_INNER word GC_page_size = 0;
}
# endif
f = open("/proc/self/stat", O_RDONLY);
- if (f < 0 || STAT_READ(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) {
+ if (f < 0
+ || (int)(len = (size_t)STAT_READ(f, stat_buf, STAT_BUF_SIZE))
+ < 2 * STAT_SKIP) {
ABORT("Couldn't read /proc/self/stat");
}
- c = stat_buf[buf_offset++];
+ close(f);
+
/* Skip the required number of fields. This number is hopefully */
/* constant across all Linux implementations. */
- for (i = 0; i < STAT_SKIP; ++i) {
- while (isspace(c)) c = stat_buf[buf_offset++];
- while (!isspace(c)) c = stat_buf[buf_offset++];
+ for (i = 0; i < STAT_SKIP; ++i) {
+ while (buf_offset < len && isspace(stat_buf[buf_offset++])) {
+ /* empty */
+ }
+ while (buf_offset < len && !isspace(stat_buf[buf_offset++])) {
+ /* empty */
}
- while (isspace(c)) c = stat_buf[buf_offset++];
- while (isdigit(c)) {
- result *= 10;
- result += c - '0';
- c = stat_buf[buf_offset++];
}
- close(f);
- if (result < 0x100000) ABORT("Absurd stack bottom value");
+ /* Skip spaces. */
+ while (buf_offset < len && isspace(stat_buf[buf_offset])) {
+ buf_offset++;
+ }
+ /* Find the end of the number and cut the buffer there. */
+ for (i = 0; buf_offset + i < len; i++) {
+ if (!isdigit(stat_buf[buf_offset + i])) break;
+ }
+ if (buf_offset + i >= len) ABORT("Could not parse /proc/self/stat");
+ stat_buf[buf_offset + i] = '\0';
+
+ result = (word)STRTOULL(&stat_buf[buf_offset], NULL, 10);
+ if (result < 0x100000 || (result & (sizeof(word) - 1)) != 0)
+ ABORT("Absurd stack bottom value");
return (ptr_t)result;
}