1570af302Sopenharmony_ci// commit: 3e936ce81bbbcc968f576aedbd5203621839f152 2014-09-19
2570af302Sopenharmony_ci// flockfile linked list handling was broken
3570af302Sopenharmony_ci#include <errno.h>
4570af302Sopenharmony_ci#include <stdio.h>
5570af302Sopenharmony_ci#include <stdlib.h>
6570af302Sopenharmony_ci#include <string.h>
7570af302Sopenharmony_ci#include "test.h"
8570af302Sopenharmony_ci
9570af302Sopenharmony_ci#define t_fatal(...) (t_error(__VA_ARGS__), _Exit(t_status))
10570af302Sopenharmony_ci#define length(a) (sizeof(a)/sizeof*(a))
11570af302Sopenharmony_ci
12570af302Sopenharmony_ci// interpose malloc functions
13570af302Sopenharmony_ci// freed memory is not reused, it is checked for clobber.
14570af302Sopenharmony_ci
15570af302Sopenharmony_cistatic unsigned char buf[1<<20];
16570af302Sopenharmony_cistatic size_t pos;
17570af302Sopenharmony_cistatic struct {
18570af302Sopenharmony_ci	size_t pos;
19570af302Sopenharmony_ci	size_t n;
20570af302Sopenharmony_ci	int freed;
21570af302Sopenharmony_ci} alloc[100];
22570af302Sopenharmony_cistatic int idx;
23570af302Sopenharmony_ci
24570af302Sopenharmony_civoid *malloc(size_t n)
25570af302Sopenharmony_ci{
26570af302Sopenharmony_ci	if (n == 0) n++;
27570af302Sopenharmony_ci	if (n > sizeof buf - pos)
28570af302Sopenharmony_ci		t_fatal("test buffer is small, pos: %zu, need: %zu\n", pos, n);
29570af302Sopenharmony_ci	if (idx >= length(alloc))
30570af302Sopenharmony_ci		t_fatal("test buffer is small, idx: %d\n", idx);
31570af302Sopenharmony_ci	void *p = buf + pos;
32570af302Sopenharmony_ci	alloc[idx].pos = pos;
33570af302Sopenharmony_ci	alloc[idx].n = n;
34570af302Sopenharmony_ci	pos += n;
35570af302Sopenharmony_ci	idx++;
36570af302Sopenharmony_ci	return p;
37570af302Sopenharmony_ci}
38570af302Sopenharmony_ci
39570af302Sopenharmony_civoid *calloc(size_t n, size_t m)
40570af302Sopenharmony_ci{
41570af302Sopenharmony_ci	return memset(malloc(n*m), 0, n*m);
42570af302Sopenharmony_ci}
43570af302Sopenharmony_ci
44570af302Sopenharmony_civoid *aligned_alloc(size_t a, size_t n)
45570af302Sopenharmony_ci{
46570af302Sopenharmony_ci	t_fatal("aligned_alloc is unsupported\n");
47570af302Sopenharmony_ci}
48570af302Sopenharmony_ci
49570af302Sopenharmony_cistatic int findidx(void *p)
50570af302Sopenharmony_ci{
51570af302Sopenharmony_ci	size_t pos = (unsigned char *)p - buf;
52570af302Sopenharmony_ci	for (int i=0; i<idx; i++)
53570af302Sopenharmony_ci		if (alloc[i].pos == pos)
54570af302Sopenharmony_ci			return i;
55570af302Sopenharmony_ci	t_fatal("%p is not an allocated pointer\n", p);
56570af302Sopenharmony_ci	return -1;
57570af302Sopenharmony_ci}
58570af302Sopenharmony_ci
59570af302Sopenharmony_civoid *realloc(void *p, size_t n)
60570af302Sopenharmony_ci{
61570af302Sopenharmony_ci	void *q = malloc(n);
62570af302Sopenharmony_ci	size_t m = alloc[findidx(p)].n;
63570af302Sopenharmony_ci	memcpy(q, p, m < n ? m : n);
64570af302Sopenharmony_ci	free(p);
65570af302Sopenharmony_ci	return q;
66570af302Sopenharmony_ci}
67570af302Sopenharmony_ci
68570af302Sopenharmony_civoid free(void *p)
69570af302Sopenharmony_ci{
70570af302Sopenharmony_ci	if (p == 0) return;
71570af302Sopenharmony_ci	int i = findidx(p);
72570af302Sopenharmony_ci	memset(p, 42, alloc[i].n);
73570af302Sopenharmony_ci	alloc[i].freed = 1;
74570af302Sopenharmony_ci}
75570af302Sopenharmony_ci
76570af302Sopenharmony_cistatic void checkfreed(void)
77570af302Sopenharmony_ci{
78570af302Sopenharmony_ci	for (int i=0; i<idx; i++)
79570af302Sopenharmony_ci		if (alloc[i].freed)
80570af302Sopenharmony_ci			for (size_t j=0; j<alloc[i].n; j++)
81570af302Sopenharmony_ci				if (buf[alloc[i].pos + j] != 42) {
82570af302Sopenharmony_ci					t_error("freed allocation %d (pos: %zu, len: %zu) is clobbered\n", i, alloc[i].pos, alloc[i].n);
83570af302Sopenharmony_ci					break;
84570af302Sopenharmony_ci				}
85570af302Sopenharmony_ci}
86570af302Sopenharmony_ci
87570af302Sopenharmony_ciint main()
88570af302Sopenharmony_ci{
89570af302Sopenharmony_ci	FILE *f = tmpfile();
90570af302Sopenharmony_ci	FILE *g = tmpfile();
91570af302Sopenharmony_ci	flockfile(g);
92570af302Sopenharmony_ci	flockfile(f);
93570af302Sopenharmony_ci	funlockfile(g);
94570af302Sopenharmony_ci	fclose(g);
95570af302Sopenharmony_ci	/* may corrupt memory */
96570af302Sopenharmony_ci	funlockfile(f);
97570af302Sopenharmony_ci	checkfreed();
98570af302Sopenharmony_ci	return t_status;
99570af302Sopenharmony_ci}
100