forgot to add the chkalloc files
authorJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 14 Dec 2021 09:45:01 +0000 (11:45 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 14 Dec 2021 09:45:01 +0000 (11:45 +0200)
src/chkalloc.c [new file with mode: 0644]
src/chkalloc.h [new file with mode: 0644]

diff --git a/src/chkalloc.c b/src/chkalloc.c
new file mode 100644 (file)
index 0000000..70f3dfc
--- /dev/null
@@ -0,0 +1,239 @@
+#ifdef CHECK_ALLOC
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "chkalloc.h"
+#include "util.h"
+
+#define OFFSET 512
+
+struct allocation {
+       char *ptr;
+       char *file;
+       int fullsz, sz;
+       int lineno;
+       struct allocation *next;
+};
+
+static FILE *logfile;
+static struct allocation *alist, *atail;
+
+static void init_once(void)
+{
+       static int init_once_done;
+       if(!init_once_done) {
+               init_once_done = 1;
+               remove("chk.log");
+       }
+}
+
+static FILE *openlog(void)
+{
+       if(logfile) return logfile;
+       return (logfile = fopen("chk.log", "a"));
+}
+
+static void closelog(void)
+{
+       fclose(logfile);
+       logfile = 0;
+}
+
+static void mark_alloc(struct allocation *a)
+{
+       uintptr_t *left, *right, *end;
+
+       left = (uintptr_t*)(a + 1);
+       right = (uintptr_t*)((char*)a + a->fullsz) - 1;
+       end = (uintptr_t*)(a->ptr + a->sz);
+
+       while(left + 1 < (void*)a->ptr) {
+               *left = (uintptr_t)left;
+               left++;
+       }
+       while(right >= end) {
+               *right = (uintptr_t)right;
+               right--;
+       }
+}
+
+static int check_alloc(struct allocation *a, const char *reason)
+{
+       int i;
+       uintptr_t *left = (uintptr_t*)(a + 1);
+       uintptr_t *right = (uintptr_t*)((char*)a + a->fullsz) - 1;
+       void *end = a->ptr + a->sz;
+       int trash_left = 0, trash_right = 0;
+       char *last_trash_left = 0, *first_trash_right = 0;
+       char *first_trash_left = 0, *last_trash_right = 0;
+
+       init_once();
+       if(!openlog()) return -1;
+
+       while(left + 1 < (void*)a->ptr) {
+               if(*left != (uintptr_t)left) {
+                       fprintf(logfile, "@%p: %p\n", left, (void*)*left);
+               }
+               for(i=0; i<sizeof *left; i++) {
+                       int s = i << 3;
+                       if(((*left >> s) & 0xff) != (((uintptr_t)left >> s) & 0xff)) {
+                               if(!first_trash_left) first_trash_left = (char*)left;
+                               trash_left++;
+                               last_trash_left = (char*)left + i;
+                       }
+               }
+               left++;
+       }
+       while(right >= end) {
+               if(*right != (uintptr_t)right) {
+                       fprintf(logfile, "@%p: %p\n", right, (void*)*right);
+               }
+               for(i=0; i<sizeof *right; i++) {
+                       int s = i << 3;
+                       if(((*right >> s) & 0xff) != (((uintptr_t)right >> s) & 0xff)) {
+                               if(!last_trash_right) last_trash_right = (char*)right;
+                               trash_right++;
+                               first_trash_right = (char*)right + i;
+                       }
+               }
+               right--;
+       }
+
+       if(!(trash_left | trash_right)) return 0;
+
+       fprintf(logfile, "corrupted memory allocated from: %s:%d\n", a->file, a->lineno);
+       if(trash_left) {
+               fprintf(logfile, " %d bytes at offset %d before start (%p)\n",
+                               (int)(last_trash_left - first_trash_left),
+                               (int)(a->ptr - last_trash_left), a->ptr);
+       }
+       if(trash_right) {
+               fprintf(logfile, " %d bytes at offset %d after end (%p)\n",
+                               (int)(last_trash_right - first_trash_right),
+                               (int)(first_trash_right - end), end);
+       }
+       fprintf(logfile, " check due to %s\n", reason);
+       closelog();
+       return -1;
+}
+
+void chk_check(void)
+{
+       struct allocation *anode = alist;
+       while(anode) {
+               check_alloc(anode, "explicit check call");
+               anode = anode->next;
+       }
+}
+
+void *chk_malloc_impl(int sz, char *file, int line)
+{
+       int fullsz;
+       struct allocation *a;
+
+       init_once();
+
+       fullsz = sz + OFFSET * 2;
+       if(!(a = malloc(fullsz))) {
+               return 0;
+       }
+
+       a->ptr = (char*)a + OFFSET;
+       a->file = file;
+       a->lineno = line;
+       a->fullsz = fullsz;
+       a->sz = sz;
+       a->next = 0;
+
+       if(alist) {
+               atail->next = a;
+               atail = a;
+       } else {
+               alist = atail = a;
+       }
+
+       mark_alloc(a);
+
+       if(openlog()) {
+               fprintf(logfile, "alloc(%d) from %s:%d\n", sz, a->file, a->lineno);
+               closelog();
+       }
+       return a->ptr;
+}
+
+void *chk_realloc_impl(void *ptr, int sz, char *file, int line)
+{
+       int fullsz;
+       struct allocation *newptr;
+       struct allocation *a = (struct allocation*)((char*)ptr - OFFSET);
+       struct allocation *prev, dummy;
+
+       init_once();
+       if(ptr) {
+               check_alloc(a, "realloc");
+       }
+
+       fullsz = sz + OFFSET * 2;
+       if(!(newptr = realloc(a, fullsz))) {
+               return 0;
+       }
+
+       dummy.next = alist;
+       prev = &dummy;
+       while(prev->next) {
+               if(prev->next == a) {
+                       prev->next = newptr;
+                       break;
+               }
+               prev = prev->next;
+       }
+       alist = dummy.next;
+
+       a = newptr;
+       a->ptr = (char*)a + OFFSET;
+       a->sz = sz;
+       a->fullsz = fullsz;
+       a->file = file;
+       a->lineno = line;
+
+       mark_alloc(a);
+
+       if(openlog()) {
+               fprintf(logfile, "realloc(%d) from %s:%d\n", sz, a->file, a->lineno);
+               closelog();
+       }
+       return a->ptr;
+}
+
+void chk_free(void *p)
+{
+       struct allocation dummy, *prev, *a;
+
+       init_once();
+
+       if(!p) return;
+
+       a = (struct allocation*)((char*)p - OFFSET);
+       if(openlog()) {
+               fprintf(logfile, "free() %d allocated from %s:%d\n", a->sz, a->file, a->lineno);
+               closelog();
+       }
+
+       dummy.next = alist;
+       prev = &dummy;
+       while(prev->next) {
+               if(prev->next->ptr == p) {
+                       a = prev->next;
+                       prev->next = a->next;
+
+                       check_alloc(a, "free");
+                       free(a);
+                       break;
+               }
+               prev = prev->next;
+       }
+       alist = dummy.next;
+}
+
+#endif /* CHECK_ALLOC */
diff --git a/src/chkalloc.h b/src/chkalloc.h
new file mode 100644 (file)
index 0000000..4375d2c
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef CHKALLOC_H_
+#define CHKALLOC_H_
+
+#ifdef CHECK_ALLOC
+
+void chk_check(void);
+
+#define chk_malloc(sz)         chk_malloc_impl(sz, __FILE__, __LINE__)
+#define chk_realloc(p, sz)     chk_realloc_impl(p, sz, __FILE__, __LINE__)
+
+void *chk_malloc_impl(int sz, char *file, int line);
+void *chk_realloc_impl(void *ptr, int sz, char *file, int line);
+void chk_free(void *p);
+
+#else  /* !CHECK_ALLOC */
+
+#include <stdlib.h>
+
+#define chk_check()
+#define chk_malloc(sz)         malloc(sz)
+#define chk_realloc(p, sz)     realloc(p, sz)
+#define chk_free(p)                    free(p)
+
+#endif /* CHECK_ALLOC */
+
+#endif /* CHKALLOC_H_ */