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,
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;
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
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(
{
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);
# 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
#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
/* 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 */
/* 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 */
}
# 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;
}