Changeset: 0dbae9ab7c5f for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=0dbae9ab7c5f
Modified Files:
        gdk/gdk_heap.c
        gdk/gdk_private.h
        gdk/gdk_utils.c
Branch: default
Log Message:

Check for writes beyond the malloced area (in debug builds only).


diffs (truncated from 653 to 300 lines):

diff --git a/gdk/gdk_heap.c b/gdk/gdk_heap.c
--- a/gdk/gdk_heap.c
+++ b/gdk/gdk_heap.c
@@ -105,7 +105,7 @@ HEAPalloc(Heap *h, size_t nitems, size_t
            (GDKmem_cursize() + h->size < GDK_mem_maxsize &&
             h->size < (h->farmid == 0 ? GDK_mmap_minsize_persistent : 
GDK_mmap_minsize_transient))) {
                h->storage = STORE_MEM;
-               h->base = (char *) GDKmallocmax(h->size, &h->size, 0);
+               h->base = (char *) GDKmalloc(h->size);
                HEAPDEBUG fprintf(stderr, "#HEAPalloc " SZFMT " " PTRFMT "\n", 
h->size, PTRFMTCAST h->base);
        }
        if (h->filename && h->base == NULL) {
@@ -218,8 +218,9 @@ HEAPextend(Heap *h, size_t size, int may
                if (!must_mmap) {
                        void *p = h->base;
                        h->newstorage = h->storage = STORE_MEM;
-                       h->base = GDKreallocmax(h->base, size, &h->size, 0);
+                       h->base = GDKrealloc(h->base, size);
                        HEAPDEBUG fprintf(stderr, "#HEAPextend: extending 
malloced heap " SZFMT " " SZFMT " " PTRFMT " " PTRFMT "\n", size, h->size, 
PTRFMTCAST p, PTRFMTCAST h->base);
+                       h->size = size;
                        if (h->base)
                                return GDK_SUCCEED; /* success */
                        failure = "h->storage == STORE_MEM && !must_map && 
!h->base";
@@ -319,7 +320,7 @@ HEAPshrink(Heap *h, size_t size)
        assert(size >= h->free);
        assert(size <= h->size);
        if (h->storage == STORE_MEM) {
-               p = GDKreallocmax(h->base, size, &size, 0);
+               p = GDKrealloc(h->base, size);
                HEAPDEBUG fprintf(stderr, "#HEAPshrink: shrinking malloced "
                                  "heap " SZFMT " " SZFMT " " PTRFMT " "
                                  PTRFMT "\n", h->size, size,
diff --git a/gdk/gdk_private.h b/gdk/gdk_private.h
--- a/gdk/gdk_private.h
+++ b/gdk/gdk_private.h
@@ -129,16 +129,12 @@ void BBPdump(void);               /* never called: fo
 __hidden void GDKlog(_In_z_ _Printf_format_string_ const char *format, ...)
        __attribute__((__format__(__printf__, 1, 2)))
        __attribute__((__visibility__("hidden")));
-__hidden void *GDKmallocmax(size_t size, size_t *maxsize, int emergency)
-       __attribute__((__visibility__("hidden")));
 __hidden gdk_return GDKmove(int farmid, const char *dir1, const char *nme1, 
const char *ext1, const char *dir2, const char *nme2, const char *ext2)
        __attribute__((__visibility__("hidden")));
 __hidden void *GDKmremap(const char *path, int mode, void *old_address, size_t 
old_size, size_t *new_size)
        __attribute__((__visibility__("hidden")));
 __hidden gdk_return GDKmunmap(void *addr, size_t len)
        __attribute__((__visibility__("hidden")));
-__hidden void *GDKreallocmax(void *pold, size_t size, size_t *maxsize, int 
emergency)
-       __attribute__((__visibility__("hidden")));
 __hidden gdk_return GDKremovedir(int farmid, const char *nme)
        __attribute__((__visibility__("hidden")));
 __hidden gdk_return GDKsave(int farmid, const char *nme, const char *ext, void 
*buf, size_t size, storage_t mode, int dosync)
@@ -323,19 +319,6 @@ extern MT_Lock MT_system_lock;
 #if !defined(NDEBUG) && !defined(STATIC_CODE_ANALYSIS)
 /* see comment in gdk.h */
 #ifdef __GNUC__
-#define GDKmallocmax(s,ps,e)                                           \
-       ({                                                              \
-               size_t _size = (s);                                     \
-               size_t *_psize  = (ps);                                 \
-               void *_res = GDKmallocmax(_size,_psize,e);              \
-               ALLOCDEBUG                                              \
-                       fprintf(stderr,                                 \
-                               "#GDKmallocmax(" SZFMT ",(" SZFMT ")) -> " \
-                               PTRFMT " %s[%s:%d]\n",                  \
-                               _size, *_psize, PTRFMTCAST _res,        \
-                               __func__, __FILE__, __LINE__);          \
-               _res;                                                   \
-        })
 #define GDKmunmap(p, l)                                                        
\
        ({      void *_ptr = (p);                                       \
                size_t _len = (l);                                      \
@@ -348,21 +331,6 @@ extern MT_Lock MT_system_lock;
                                __func__, __FILE__, __LINE__);          \
                _res;                                                   \
        })
-#define GDKreallocmax(p,s,ps,e)                                                
\
-       ({                                                              \
-               void *_ptr = (p);                                       \
-               size_t _size = (s);                                     \
-               size_t *_psize  = (ps);                                 \
-               void *_res = GDKreallocmax(_ptr,_size,_psize,e);        \
-               ALLOCDEBUG                                              \
-                       fprintf(stderr,                                 \
-                               "#GDKreallocmax(" PTRFMT "," SZFMT \
-                               ",(" SZFMT ")) -> " PTRFMT              \
-                               " %s[%s:%d]\n", PTRFMTCAST _ptr,        \
-                               _size, *_psize, PTRFMTCAST _res,        \
-                               __func__, __FILE__, __LINE__);          \
-               _res;                                                   \
-        })
 #define GDKmremap(p, m, oa, os, ns)                                    \
        ({                                                              \
                const char *_path = (p);                                \
@@ -383,18 +351,6 @@ extern MT_Lock MT_system_lock;
                _res;                                                   \
         })
 #else
-static inline void *
-GDKmallocmax_debug(size_t size, size_t *psize, int emergency,
-                  const char *filename, int lineno)
-{
-       void *res = GDKmallocmax(size, psize, emergency);
-       ALLOCDEBUG fprintf(stderr,
-                          "#GDKmallocmax(" SZFMT ",(" SZFMT ")) -> "
-                          PTRFMT " [%s:%d]\n",
-                          size, *psize, PTRFMTCAST res, filename, lineno);
-       return res;
-}
-#define GDKmallocmax(s, ps, e) GDKmallocmax_debug((s), (ps), (e), __FILE__, 
__LINE__)
 static inline gdk_return
 GDKmunmap_debug(void *ptr, size_t len, const char *filename, int lineno)
 {
@@ -406,19 +362,6 @@ GDKmunmap_debug(void *ptr, size_t len, c
 }
 #define GDKmunmap(p, l)                GDKmunmap_debug((p), (l), __FILE__, 
__LINE__)
 static inline void *
-GDKreallocmax_debug(void *ptr, size_t size, size_t *psize, int emergency,
-                   const char *filename, int lineno)
-{
-       void *res = GDKreallocmax(ptr, size, psize, emergency);
-       ALLOCDEBUG fprintf(stderr,
-                          "#GDKreallocmax(" PTRFMT "," SZFMT
-                          ",(" SZFMT ")) -> " PTRFMT " [%s:%d]\n",
-                          PTRFMTCAST ptr, size, *psize, PTRFMTCAST res,
-                          filename, lineno);
-       return res;
-}
-#define GDKreallocmax(p, s, ps, e)     GDKreallocmax_debug((p), (s), (ps), 
(e), __FILE__, __LINE__)
-static inline void *
 GDKmremap_debug(const char *path, int mode, void *old_address, size_t 
old_size, size_t *new_size, const char *filename, int lineno)
 {
        size_t orig_new_size = *new_size;
diff --git a/gdk/gdk_utils.c b/gdk/gdk_utils.c
--- a/gdk/gdk_utils.c
+++ b/gdk/gdk_utils.c
@@ -1228,7 +1228,7 @@ THRnew(const char *name)
                        return NULL;
                }
                tid = s->tid;
-               memset((char *) s, 0, sizeof(*s));
+               memset(s, 0, sizeof(*s));
                s->pid = pid;
                s->tid = tid;
                s->data[1] = THRdata[1];
@@ -1557,45 +1557,6 @@ GDKmemdump(void)
 }
 
 
-/*
- * @+ Malloc
- * Malloc normally maps through directly to the OS provided
- * malloc/free/realloc calls. Where possible, we want to use the
- * -lmalloc library on Unix systems, because it allows to influence
- * the memory allocation strategy. This can prevent fragmentation and
- * greatly help enhance performance.
- *
- * The "added-value" of the GDKmalloc/GDKfree/GDKrealloc over the
- * standard OS primitives is that additional information on block
- * sizes is kept (helping efficient reallocations) as well as some
- * debugging that guards against duplicate frees.
- *
- * A number of different strategies are available using different
- * switches, however:
- *
- * - zero sized blocks
- *   Normally, GDK gives fatal errors on illegal block sizes.
- *   This can be overridden with  GDK_MEM_NULLALLOWED.
- *
- * - resource tracking
- *   Many malloc interfaces lack a routine that tells the size of a
- *   block by the pointer. We need this information for correct malloc
- *   statistics.
- *
- * - outstanding block histograms
- *   In order to solve the problem, we allocate extra memory in front
- *   of the returned block. With the resource tracking in place, we
- *   keep a total of allocated bytes.  Also, if GDK_MEM_KEEPHISTO is
- *   defined, we keep a histogram of the outstanding blocks on the
- *   log2 of the block size (similarly for virtual.  memory blocks;
- *   define GDK_VM_KEEPHISTO).
- *
- * 64-bits update: Some 64-bit implementations (Linux) of mallinfo is
- * severely broken, as they use int-s for memory sizes!!  This causes
- * corruption of mallinfo stats. As we depend on those, we should keep
- * the malloc arena small. Thus, VM redirection is now quickly
- * applied: for all mallocs > 1MB.
- */
 static void
 GDKmemfail(const char *s, size_t len)
 {
@@ -1619,51 +1580,40 @@ GDKmemfail(const char *s, size_t len)
        GDKmemdump();
 }
 
-/* the blocksize is stored in the ssize_t before it. Negative size <=>
- * VM memory */
-#define GDK_MEM_BLKSIZE(p) ((ssize_t*) (p))[-1]
-#ifdef __GLIBC__
-#define GLIBC_BUG 8
-#else
-#define GLIBC_BUG 0
-#endif
+/* Memory allocation
+ *
+ * The functions GDKmalloc, GDKzalloc, GDKrealloc, GDKstrdup, and
+ * GDKfree are used throughout to allocate and free memory.  These
+ * functions are almost directly mapped onto the system
+ * malloc/realloc/free functions, but they give us some extra
+ * debugging hooks.
+ *
+ * When allocating memory, we allocate a bit more than was asked for.
+ * The extra space is added onto the front of the memory area that is
+ * returned, and in debug builds also some at the end.  The area in
+ * front is used to store the actual size of the allocated area.  The
+ * most important use is to be able to keep statistics on how much
+ * memory is being used.  In debug builds, the size is also used to
+ * make sure that we don't write outside of the allocated arena.  This
+ * is also where the extra space at the end comes in.
+ */
 
 /* we allocate extra space and return a pointer offset by this amount */
 #define MALLOC_EXTRA_SPACE     (2 * SIZEOF_VOID_P)
 
-/* allocate 8 bytes extra (so it stays 8-bytes aligned) and put
- * realsize in front */
-static inline void *
-GDKmalloc_prefixsize(size_t size)
-{
-       ssize_t *s;
+#ifdef NDEBUG
+#define DEBUG_SPACE    0
+#else
+#define DEBUG_SPACE    16
+#endif
 
-       if ((s = malloc(size + MALLOC_EXTRA_SPACE + GLIBC_BUG)) != NULL) {
-               assert((((uintptr_t) s) & 7) == 0); /* no MISALIGN */
-               s = (ssize_t*) ((char*) s + MALLOC_EXTRA_SPACE);
-               s[-1] = (ssize_t) (size + MALLOC_EXTRA_SPACE);
-       }
-       return s;
-}
-
-
-/*
- * The emergency flag can be set to force a fatal error if needed.
- * Otherwise, the caller is able to deal with the lack of memory.
- */
-#undef GDKmallocmax
-void *
-GDKmallocmax(size_t size, size_t *maxsize, int emergency)
+static void *
+GDKmalloc_internal(size_t size)
 {
        void *s;
+       size_t nsize;
 
-       if (size == 0) {
-#ifdef GDK_MEM_NULLALLOWED
-               return NULL;
-#else
-               GDKfatal("GDKmallocmax: called with size " SZFMT "", size);
-#endif
-       }
+       assert(size != 0);
 #ifndef NDEBUG
        /* fail malloc for testing purposes depending on set limit */
        if (GDK_malloc_success_count > 0) {
@@ -1675,20 +1625,30 @@ GDKmallocmax(size_t size, size_t *maxsiz
        if (GDK_malloc_success_count == 0) {
                return NULL;
        }
+#endif
 
+       /* pad to multiple of eight bytes and add some extra space to
+        * write real size in front; when debugging, also allocate
+        * extra space for check bytes */
+       nsize = (size + 7) & ~7;
+       if ((s = malloc(nsize + MALLOC_EXTRA_SPACE + DEBUG_SPACE)) == NULL) {
+               GDKmemfail("GDKmalloc", size);
+               GDKerror("GDKmalloc_internal: failed for " SZFMT " bytes", 
size);
+               return NULL;
+       }
+       s = (void *) ((char *) s + MALLOC_EXTRA_SPACE);
+
+       heapinc(nsize + MALLOC_EXTRA_SPACE + DEBUG_SPACE);
+
+       /* just before the pointer that we return, write how much we
+        * asked of malloc */
+       ((size_t *) s)[-1] = nsize + MALLOC_EXTRA_SPACE + DEBUG_SPACE;
+#ifndef NDEBUG
+       /* just before that, write how much was asked of us */
+       ((size_t *) s)[-2] = size;
+       /* write pattern to help find out-of-bounds writes */
+       memset((char *) s + size, '\xBD', nsize + DEBUG_SPACE - size);
 #endif
-       size = (size + 7) & ~7; /* round up to a multiple of eight */
-       s = GDKmalloc_prefixsize(size);
-       if (s == NULL) {
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to