2011-03-13 Ivan Maidanski <ivmai@mail.ru>
authorivmai <ivmai>
Sun, 13 Mar 2011 19:37:24 +0000 (19:37 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Jul 2011 17:06:56 +0000 (21:06 +0400)
* 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).

ChangeLog
dbg_mlc.c
include/private/gc_priv.h
misc.c
os_dep.c

index 0845128..03ea8c5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
 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).
+
+2011-03-13  Ivan Maidanski  <ivmai@mail.ru>
+
        * dbg_mlc.c (GC_make_closure): Fix SEGV in case GC_malloc returns
        NULL.
        * dbg_mlc.c (GC_debug_register_finalizer,
index 29e9a89..42561fc 100644 (file)
--- a/dbg_mlc.c
+++ b/dbg_mlc.c
@@ -101,6 +101,13 @@ GC_API void GC_CALL GC_register_finalizer_no_order(void * obj,
     oh * hdr = (oh *)GC_base(dest);
     ptr_t bp;
     ptr_t bp_base;
+
+#   ifdef LINT2
+      /* Explicitly instruct the code analysis tool that                */
+      /* GC_get_back_ptr_info is not expected to be called with an      */
+      /* incorrect "dest" value.                                        */
+      if (!hdr) ABORT("Invalid GC_get_back_ptr_info argument");
+#   endif
     if (!GC_HAS_DEBUG_INFO((ptr_t) hdr)) return GC_NO_SPACE;
     bp = GC_REVEAL_POINTER(hdr -> oh_back_ptr);
     if (MARKED_FOR_FINALIZATION == bp) return GC_FINALIZER_REFD;
@@ -386,6 +393,9 @@ STATIC void GC_print_obj(ptr_t p)
     oh * ohdr = (oh *)GC_base(p);
 
     GC_ASSERT(I_DONT_HOLD_LOCK());
+#   ifdef LINT2
+      if (!ohdr) ABORT("Invalid GC_print_obj argument");
+#   endif
     GC_err_printf("%p (", ((ptr_t)ohdr + sizeof(oh)));
     GC_err_puts(ohdr -> oh_string);
 #   ifdef SHORT_DBG_HDRS
@@ -418,6 +428,9 @@ STATIC void GC_debug_print_heap_obj_proc(ptr_t p)
     oh * ohdr = (oh *)GC_base(p);
 
     GC_ASSERT(I_DONT_HOLD_LOCK());
+#   ifdef LINT2
+      if (!ohdr) ABORT("Invalid GC_print_smashed_obj argument");
+#   endif
     if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz))
         || ohdr -> oh_string == 0) {
         GC_err_printf(
@@ -773,6 +786,9 @@ GC_API void GC_CALL GC_debug_free(void * p)
   {
     ptr_t base = GC_base(p);
     GC_ASSERT((ptr_t)p - (ptr_t)base == sizeof(oh));
+#   ifdef LINT2
+      if (!base) ABORT("Invalid GC_debug_free_inner argument");
+#   endif
 #   ifndef SHORT_DBG_HDRS
       /* Invalidate size */
       ((oh *)base) -> oh_sz = GC_size(base);
index 3d9bc64..d2c618a 100644 (file)
@@ -130,7 +130,7 @@ typedef char * ptr_t;   /* A generic pointer to which we can add        */
 # include "gc_hdrs.h"
 #endif
 
-#if __GNUC__ >= 3
+#if __GNUC__ >= 3 && !defined(LINT2)
 # define EXPECT(expr, outcome) __builtin_expect(expr,outcome)
   /* Equivalent to (expr), but predict that usually (expr)==outcome. */
 #else
@@ -241,7 +241,13 @@ typedef char * ptr_t;   /* A generic pointer to which we can add        */
 #define GC_INVOKE_FINALIZERS() GC_notify_or_invoke_finalizers()
 
 #if !defined(DONT_ADD_BYTE_AT_END)
-# define EXTRA_BYTES GC_all_interior_pointers
+# ifdef LINT2
+    /* Explicitly instruct the code analysis tool that                  */
+    /* GC_all_interior_pointers is assumed to have only 0 or 1 value.   */
+#   define EXTRA_BYTES (GC_all_interior_pointers? 1 : 0)
+# else
+#   define EXTRA_BYTES GC_all_interior_pointers
+# endif
 # define MAX_EXTRA_BYTES 1
 #else
 # define EXTRA_BYTES 0
diff --git a/misc.c b/misc.c
index b4e47b8..b058228 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -1381,7 +1381,9 @@ GC_API GC_warn_proc GC_CALL GC_get_warn_proc(void)
             /* about threads.                                           */
             for(;;) {}
     }
-    if (!msg) return; /* to suppress compiler warnings in ABORT callers. */
+#   ifndef LINT2
+      if (!msg) return; /* to suppress compiler warnings in ABORT callers. */
+#   endif
 #   if defined(MSWIN32) && defined(NO_DEBUGGING)
       /* A more user-friendly abort after showing fatal message.        */
         _exit(-1); /* exit on error without running "at-exit" callbacks */
index 0b9813e..c876a09 100644 (file)
--- 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;
   }