diff dcclib/heap_debug.c @ 0:c7f6b056b673

First import of vendor version
author Peter Gervai <grin@grin.hu>
date Tue, 10 Mar 2009 13:49:58 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcclib/heap_debug.c	Tue Mar 10 13:49:58 2009 +0100
@@ -0,0 +1,232 @@
+/* Distributed Checksum Clearinghouse heap debugging
+ *
+ * Copyright (c) 2008 by Rhyolite Software, LLC
+ *
+ * This agreement is not applicable to any entity which sells anti-spam
+ * solutions to others or provides an anti-spam solution as part of a
+ * security solution sold to other entities, or to a private network
+ * which employs the DCC or uses data provided by operation of the DCC
+ * but does not provide corresponding data to other users.
+ *
+ * Permission to use, copy, modify, and distribute this software without
+ * changes for any purpose with or without fee is hereby granted, provided
+ * that the above copyright notice and this permission notice appear in all
+ * copies and any distributed versions or copies are either unchanged
+ * or not called anything similar to "DCC" or "Distributed Checksum
+ * Clearinghouse".
+ *
+ * Parties not eligible to receive a license under this agreement can
+ * obtain a commercial license to use DCC by contacting Rhyolite Software
+ * at sales@rhyolite.com.
+ *
+ * A commercial license would be for Distributed Checksum and Reputation
+ * Clearinghouse software.  That software includes additional features.  This
+ * free license for Distributed ChecksumClearinghouse Software does not in any
+ * way grant permision to use Distributed Checksum and Reputation Clearinghouse
+ * software
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC
+ * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ *
+ * Rhyolite Software DCC 1.3.103-1.20 $Revision$
+ */
+
+#include "dcc_defs.h"
+#include "dcc_heap_debug.h"
+#include <stdio.h>
+
+void dcc_malloc_lock(void);
+void dcc_malloc_unlock(void);
+
+#ifdef UNIX
+#include <unistd.h>
+#else /* !UNIX */
+#include "malloc.h"
+#endif /* !UNIX */
+
+
+typedef u_long SENTINEL;
+#define HEAD_SENTINEL_VALUE 0xdeadbeaf
+#define TAIL_SENTINEL_VALUE 0xbeafdead
+
+typedef struct mdbg{
+    SENTINEL	head;
+    struct mdbg *fwd, *bak;
+    SENTINEL	*tail;
+} MDBG;
+
+u_int dcc_num_mdbg;			/* global to suppress warnings */
+MDBG *dcc_mdbg_chain;			/*	when not used */
+MDBG *bad_mp;
+int bad_i;
+
+/* leave a few names outside to make some `ar`s happy */
+#ifdef DCC_DEBUG_HEAP
+
+
+/* this needs to do as little as possible to avoid calling malloc()
+ *	global and no NRATTRIB to avoid confusion in dumps */
+void
+dcc_heap_abort(const char *m)
+{
+#ifdef UNIX
+	static int die;			/* suppress no-retun warning */
+
+	write(STDERR_FILENO, m, strlen(m));
+	if (++die)
+		abort();
+#else
+	bad_message_box("heap_debug", 1, m);
+#endif
+}
+
+
+
+char *
+dcc_strdup(const char *s)
+{
+	char *p;
+
+	p = dcc_malloc(strlen(s)+1);
+	strcpy(p, s);
+	return p;
+}
+
+
+
+void
+dcc_malloc_check(void)
+{
+	MDBG *mp;
+	u_int i;
+
+	i = dcc_num_mdbg;
+	if (!i)
+		return;
+
+	mp = dcc_mdbg_chain;
+	for (;;) {
+		if (mp->head != HEAD_SENTINEL_VALUE
+		    || *mp->tail != TAIL_SENTINEL_VALUE)
+			dcc_heap_abort("trashed heap sentinel");
+		if (mp->bak->fwd != mp
+		    || mp->fwd->bak != mp) {
+			bad_mp = mp;
+			bad_i = i;
+			dcc_heap_abort("malloc chain trashed");
+		}
+		if (--i == 0) {
+			if (mp->fwd != dcc_mdbg_chain) {
+				bad_mp = mp;
+				bad_i = i;
+				dcc_heap_abort("wrong malloc chain too long");
+			}
+#ifndef UNIX
+			i = _heapchk();
+			if (i != _HEAPOK && i != _HEAPEMPTY)
+				dcc_heap_abort("heapchk() failed");
+#endif
+			return;
+		} else if (mp->fwd == dcc_mdbg_chain) {
+			bad_mp = mp;
+			bad_i = i;
+			dcc_heap_abort("wrong malloc chain too short");
+		}
+		mp = mp->fwd;
+	}
+}
+
+
+
+void *
+dcc_malloc(size_t len)
+{
+	MDBG *mp;
+
+	dcc_malloc_lock();
+	dcc_malloc_check();
+
+	if (!len)
+		dcc_heap_abort("malloc(0)");
+
+	len += sizeof(MDBG) + sizeof(mp->tail);
+	len += (sizeof(mp->tail) - len) & (sizeof(mp->tail)-1); /* align tail */
+
+	mp = malloc(len);
+	if (!mp)
+		return mp;
+
+	if (!dcc_num_mdbg) {
+		mp->fwd = mp->bak = mp;
+	} else {
+		mp->bak = dcc_mdbg_chain;
+		mp->fwd = dcc_mdbg_chain->fwd;
+		mp->bak->fwd = mp;
+		mp->fwd->bak = mp;
+	}
+	dcc_mdbg_chain = mp;
+	mp->head = HEAD_SENTINEL_VALUE;
+	mp->tail = (SENTINEL *)((u_char *)mp+len-sizeof(mp->tail));
+	*mp->tail = TAIL_SENTINEL_VALUE;
+	dcc_num_mdbg++;
+	dcc_malloc_unlock();
+
+	return (mp+1);
+}
+
+
+
+void *
+dcc_calloc(size_t n, size_t s)
+{
+	void *p;
+
+	s *= n;
+	if (s == 0)
+		dcc_heap_abort("zero calloc() size");
+	p = dcc_malloc(s);
+	if (!p)
+		return p;
+	memset(p, 0, s);
+	return p;
+}
+
+
+
+void
+dcc_free(void *p)
+{
+	int i;
+	MDBG *mp;
+
+	dcc_malloc_lock();
+	dcc_malloc_check();
+	i = dcc_num_mdbg;
+	mp = dcc_mdbg_chain;
+	for (;;) {
+		if (!i)
+			dcc_heap_abort("freeing non-free");
+		if (mp+1 == p)
+			break;
+		mp = mp->fwd;
+		i--;
+	}
+
+	if (dcc_mdbg_chain == mp)
+		dcc_mdbg_chain = mp->fwd;
+	mp->bak->fwd = mp->fwd;
+	mp->fwd->bak = mp->bak;
+	dcc_num_mdbg--;
+	memset(mp, 0xf1, (u_char *)mp->tail+sizeof(mp->tail)-(u_char *)mp);
+	dcc_malloc_check();
+	dcc_malloc_unlock();
+
+	free(mp);
+}
+#endif /* DCC_DEBUG_HEAP */