11195Srgrimes/*	$OpenBSD: malloc0test.c,v 1.5 2008/04/13 00:22:17 djm Exp $	*/
250472Speter/*
337Srgrimes * Public domain.  2001, Theo de Raadt
438103Speter */
538103Speter#include <sys/types.h>
664618Sgshapiro#include <sys/signal.h>
755230Speter#include <stdio.h>
855230Speter#include <unistd.h>
955230Speter#include <stdlib.h>
1055230Speter#include <setjmp.h>
1155230Speter#include <limits.h>
1259257Siwasaki#include <errno.h>
1357954Sshin
1455230Spetervolatile sig_atomic_t got;
1557407Sshinjmp_buf jmp;
1655230Speter
1755230Speterstatic void
1855230Spetercatch(int signo)
1955230Speter{
201734Sjkh	got++;
2117639Swosch	longjmp(jmp, 1);
2217639Swosch}
2337Srgrimes
2457479Speterstatic int
2557488Spetertest(char *p, int size)
2657459Smarkm{
2757459Smarkm	signal(SIGSEGV, catch);
2857459Smarkm	got = 0;
2960677Skris	if (setjmp(jmp) == 0)
3060677Skris		*p = 0;
3160677Skris	if (setjmp(jmp) == 0)
3260677Skris		*(p+size-1) = 0;
331773Sjkh	return (got);
3448734Siwasaki}
35147Srgrimes
3627487Sasamichar *prot_table[] = {
3765168Sasami	"unprotected",
3835832Sache	"fuckup",
3943901Sbrian	"protected"
4049110Sbrian};
4164598Sgshapiro
4264598Sgshapiro#define SIZE	10
4337Srgrimes
4417639Swosch/*
45263Srgrimes * Do random memory allocations.
462779Srgrimes *
478857Srgrimes * For each one, ensure that it is at least 16 bytes in size (that
48993Srgrimes * being what our current malloc returns for the minsize of an
49263Srgrimes * object, alignment wise);
5038103Speter *
5137Srgrimes * For zero-byte allocations, check that they are still aligned.
524487Sphk *
536717Sphk * For each object, ensure that they are correctly protected or not
5439590Sjkh * protected.
5539636Sdima *
5639590Sjkh * Does not regress test malloc + free combinations ... it should.
5739590Sjkh */
585948Sjkhint
594487Sphkmain(int argc, char *argv[])
601759Sjkh{
619970Sbde	caddr_t blob;
6236902Sguido	int size, tsize;
6343832Sjkh	int prot;
6452609Sdillon	int rval = 0, fuckup = 0;
6558979Siwasaki	long limit = 200000, count;
6661981Sbrian	int ch, silent = 0;
679970Sbde	char *ep;
6851033Sn_hibma	extern char *__progname;
699970Sbde
701759Sjkh	while ((ch = getopt(argc, argv, "sn:")) != -1) {
7157488Speter		switch (ch) {
7257488Speter		case 's':
7317639Swosch			silent = 1;
7417639Swosch			break;
7517645Swosch		case 'n':
7638160Sjb			errno = 0;
7757488Speter			limit = strtol(optarg, &ep, 10);
781759Sjkh			if (optarg[0] == '\0' || *ep != '\0' ||
799970Sbde			    (errno == ERANGE &&
8053327Speter			     (limit == LONG_MAX || limit == LONG_MIN)))
8157488Speter				goto usage;
8257488Speter			break;
8357488Speter		default:
8457488Speterusage:
8560677Skris			fprintf(stderr, "Usage: %s [-s][-n <count>]\n",
8660677Skris			    __progname);
8760677Skris			exit(1);
8860677Skris		}
8957071Srwatson	}
9057488Speter
9157071Srwatson	if (limit == 0)
921731Sjkh		limit = LONG_MAX;
939970Sbde
9437Srgrimes	for (count = 0; count < limit; count++) {
959970Sbde		size = arc4random_uniform(SIZE);
9637Srgrimes		blob = malloc(size);
979970Sbde		if (blob == NULL) {
9837Srgrimes			fprintf(stderr, "success: out of memory\n");
999970Sbde			exit(rval);
10037Srgrimes		}
10137Srgrimes
10237Srgrimes		tsize = size == 0 ? 16 : size;
10337Srgrimes		fuckup = 0;
1049970Sbde		prot = test(blob, tsize);
1051731Sjkh
1069970Sbde		if (size == 0 && prot < 2)
1071731Sjkh			fuckup = 1;
1089970Sbde
1096177Samurai		if (fuckup) {
11049110Sbrian			printf("%8p %6d %20s %10s\n", blob, size,
11149110Sbrian			    prot_table[prot], fuckup ? "fuckup" : "");
11230589Sjmb			rval = 1;
11364598Sgshapiro		}
11464629Sgshapiro
11564629Sgshapiro		if (!silent && count % 100000 == 0 && count != 0)
11664629Sgshapiro			fprintf(stderr, "count = %ld\n", count);
11764629Sgshapiro	}
11864629Sgshapiro
1199970Sbde	return rval;
12037Srgrimes}
12163097Speter