#include <string.h>
#include "test.h"
+#define t_fatal(...) (t_error(__VA_ARGS__), _Exit(t_status))
+#define length(a) (sizeof(a)/sizeof*(a))
+
+// interpose malloc functions
+// freed memory is not reused, it is checked for clobber.
+
+static unsigned char buf[1<<20];
+static size_t pos;
+static struct {
+ size_t pos;
+ size_t n;
+ int freed;
+} alloc[100];
+static int idx;
+
+void *malloc(size_t n)
+{
+ if (n == 0) n++;
+ if (n > sizeof buf - pos)
+ t_fatal("test buffer is small, pos: %zu, need: %zu\n", pos, n);
+ if (idx >= length(alloc))
+ t_fatal("test buffer is small, idx: %d\n", idx);
+ void *p = buf + pos;
+ alloc[idx].pos = pos;
+ alloc[idx].n = n;
+ pos += n;
+ idx++;
+ return p;
+}
+
+void *calloc(size_t n, size_t m)
+{
+ return memset(malloc(n*m), 0, n*m);
+}
+
+void *aligned_alloc(size_t a, size_t n)
+{
+ t_fatal("aligned_alloc is unsupported\n");
+}
+
+static int findidx(void *p)
+{
+ size_t pos = (unsigned char *)p - buf;
+ for (int i=0; i<idx; i++)
+ if (alloc[i].pos == pos)
+ return i;
+ t_fatal("%p is not an allocated pointer\n", p);
+ return -1;
+}
+
+void *realloc(void *p, size_t n)
+{
+ void *q = malloc(n);
+ size_t m = alloc[findidx(p)].n;
+ memcpy(q, p, m < n ? m : n);
+ free(p);
+ return q;
+}
+
+void free(void *p)
+{
+ if (p == 0) return;
+ int i = findidx(p);
+ memset(p, 42, alloc[i].n);
+ alloc[i].freed = 1;
+}
+
+static void checkfreed(void)
+{
+ for (int i=0; i<idx; i++)
+ if (alloc[i].freed)
+ for (size_t j=0; j<alloc[i].n; j++)
+ if (buf[alloc[i].pos + j] != 42) {
+ t_error("freed allocation %d (pos: %zu, len: %zu) is clobbered\n", i, alloc[i].pos, alloc[i].n);
+ break;
+ }
+}
+
int main()
{
FILE *f = tmpfile();
flockfile(f);
funlockfile(g);
fclose(g);
-
- /* fill memory */
- if (t_vmfill(0,0,0) < 0)
- t_error("vmfill failed: %s\n", strerror(errno));
- size_t i,n;
- unsigned char *p;
- for (n = 1; n < 10000; n++) {
- if (!(p=malloc(n))) break;
- free(p);
- }
- n--;
- if (!(p=malloc(n))) {
- t_error("bad malloc fragmentation\n");
- return t_status;
- }
- memset(p, 0xff, n);
-
/* may corrupt memory */
funlockfile(f);
- for (i=0; i<n; i++) {
- if (p[i]!=0xff) {
- t_error("p[%zu] = %.2x\n", i, p[i]);
- }
- }
+ checkfreed();
return t_status;
}