1// commit: 3e936ce81bbbcc968f576aedbd5203621839f152 2014-09-19
2// flockfile linked list handling was broken
3#include <errno.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include "test.h"
8
9#define t_fatal(...) (t_error(__VA_ARGS__), _Exit(t_status))
10#define length(a) (sizeof(a)/sizeof*(a))
11
12// interpose malloc functions
13// freed memory is not reused, it is checked for clobber.
14
15static unsigned char buf[1<<20];
16static size_t pos;
17static struct {
18	size_t pos;
19	size_t n;
20	int freed;
21} alloc[100];
22static int idx;
23
24void *malloc(size_t n)
25{
26	if (n == 0) n++;
27	if (n > sizeof buf - pos)
28		t_fatal("test buffer is small, pos: %zu, need: %zu\n", pos, n);
29	if (idx >= length(alloc))
30		t_fatal("test buffer is small, idx: %d\n", idx);
31	void *p = buf + pos;
32	alloc[idx].pos = pos;
33	alloc[idx].n = n;
34	pos += n;
35	idx++;
36	return p;
37}
38
39void *calloc(size_t n, size_t m)
40{
41	return memset(malloc(n*m), 0, n*m);
42}
43
44void *aligned_alloc(size_t a, size_t n)
45{
46	t_fatal("aligned_alloc is unsupported\n");
47}
48
49static int findidx(void *p)
50{
51	size_t pos = (unsigned char *)p - buf;
52	for (int i=0; i<idx; i++)
53		if (alloc[i].pos == pos)
54			return i;
55	t_fatal("%p is not an allocated pointer\n", p);
56	return -1;
57}
58
59void *realloc(void *p, size_t n)
60{
61	void *q = malloc(n);
62	size_t m = alloc[findidx(p)].n;
63	memcpy(q, p, m < n ? m : n);
64	free(p);
65	return q;
66}
67
68void free(void *p)
69{
70	if (p == 0) return;
71	int i = findidx(p);
72	memset(p, 42, alloc[i].n);
73	alloc[i].freed = 1;
74}
75
76static void checkfreed(void)
77{
78	for (int i=0; i<idx; i++)
79		if (alloc[i].freed)
80			for (size_t j=0; j<alloc[i].n; j++)
81				if (buf[alloc[i].pos + j] != 42) {
82					t_error("freed allocation %d (pos: %zu, len: %zu) is clobbered\n", i, alloc[i].pos, alloc[i].n);
83					break;
84				}
85}
86
87int main()
88{
89	FILE *f = tmpfile();
90	FILE *g = tmpfile();
91	flockfile(g);
92	flockfile(f);
93	funlockfile(g);
94	fclose(g);
95	/* may corrupt memory */
96	funlockfile(f);
97	checkfreed();
98	return t_status;
99}
100