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