#include <sys/resource.h>
#include <sys/wait.h>
#include <err.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <signal.h>
#include <unistd.h>
void
clearq(void *p)
{
int i;
void *q;
for (i = 0; i < 400; i++) {
q = malloc(100);
free(q);
if (p == q) {
fprintf(stderr, "Re-use\n");
abort();
}
}
}
void
t0(void)
{
abort();
}
void
t1(void)
{
void *p = malloc(10000);
free(p);
free(p);
}
void
t2(void)
{
void *p, *q;
int i;
p = malloc(100);
free(p);
clearq(p);
free(p);
}
void
t3(void)
{
void *p = malloc(100);
free(p);
free(p);
}
void
t4(void)
{
free((void*)1);
}
void
t5(void)
{
realloc((void*)1, 10);
}
void
t6(void)
{
char *p = malloc(32);
free(p);
p[0] = ~p[0];
clearq(NULL);
}
void
t7(void)
{
char *p, *q;
int i;
p = malloc(10000);
free(p);
p[0] = ~p[0];
for (i = 0; i < 100; i++) {
q = malloc(10000);
free(q);
}
}
void
t8(void)
{
char *p, *q;
p = malloc(32);
q = malloc(32);
free(p);
p[0] = ~p[0];
free(q);
}
void
t9(void)
{
char *p = malloc(100);
p[100] = 0;
free(p);
}
void
t11(void)
{
char *p = malloc(100);
free(p + 1);
}
void
t12(void)
{
char *p = malloc(16);
free(p + 16);
}
void
t13(void)
{
char *p = malloc(16);
freezero(p, 17);
}
void
t14(void)
{
char *p = malloc(15);
freezero(p, 16);
}
void
t15(void)
{
char *p = malloc(getpagesize());
freezero(p, getpagesize() + 1);
}
void
t16(void)
{
char *p = recallocarray(NULL, 0, 16, 1);
char *q = recallocarray(p, 2, 3, 16);
}
void
t17(void)
{
char *p = recallocarray(NULL, 0, 15, 1);
char *q = recallocarray(p, 2, 3, 15);
}
void
t18(void)
{
char *p = recallocarray(NULL, 0, 1, getpagesize());
char *q = recallocarray(p, 2, 3, getpagesize());
}
void
t19(void)
{
char *p = recallocarray(NULL, 0, 1, 10 * getpagesize());
char *q = recallocarray(p, 1, 2, 4 * getpagesize());
}
void
t20(void)
{
char *p = malloc(2*getpagesize() - 100);
p[2*getpagesize() - 100] = 0;
free(p);
}
void
t22(void)
{
int i, j;
unsigned char *p;
while (1) {
uintptr_t address;
p = malloc(32);
address = (uintptr_t)(void *)p;
if (address / getpagesize() == (address + 32) / getpagesize())
break;
free(p);
}
p[32] = 0;
for (i = 0; i < 10000; i++)
p = malloc(32);
}
struct test {
void (*test)(void);
const char *flags;
};
struct test tests[] = {
{ t0, "" },
{ t1, "" },
{ t2, "" },
{ t3, "F" },
{ t4, "" },
{ t5, "" },
{ t6, "J" },
{ t7, "JJ" },
{ t8, "FJ" },
{ t9, "C" },
{ t9, "JC" },
{ t11, "" },
{ t12, "" },
{ t13, "" },
{ t14, "C" },
{ t15, "" },
{ t16, "" },
{ t17, "C" },
{ t18, "" },
{ t19, "" },
{ t20, "C" },
{ t8, "FJD" },
{ t22, "J" },
{ t22, "JD" },
};
int main(int argc, char *argv[])
{
const struct rlimit lim = {0, 0};
int i, status;
pid_t pid;
char num[10];
char options[40];
char const *env[2];
if (argc == 2) {
setrlimit(RLIMIT_CORE, &lim);
i = atoi(argv[1]);
fprintf(stderr, "Test %d\n", i);
(*tests[i].test)();
return 0;
}
for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
pid = fork();
switch (pid) {
case 0:
snprintf(options, sizeof(options), "MALLOC_OPTIONS=us%s", tests[i].flags);
snprintf(num, sizeof(num), "%d", i);
env[0] = options;
env[1] = NULL;
execle(argv[0], argv[0], num, NULL, env);
err(1, "exec");
break;
case -1:
err(1, "fork");
break;
default:
if (waitpid(pid, &status, 0) == -1)
err(1, "wait");
if (!WIFSIGNALED(status) ||
WTERMSIG(status) != SIGABRT)
errx(1, "Test %d did not abort", i);
break;
}
}
return 0;
}