xref: /openbsd-src/regress/lib/libc/mkstemp/mkstemp_test.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*
2  * Copyright (c) 2010  Philip Guenther <guenther@openbsd.org>
3  *
4  * Public domain.
5  *
6  * Verify that mkstemp() and mkstemps() doesn't overrun or underrun
7  * the template buffer and that it can generate names that don't
8  * contain any X's
9  */
10 
11 #include <sys/param.h>
12 
13 #include <err.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <sys/mman.h>
18 #include <sys/stat.h>
19 #include <unistd.h>
20 
21 #define MAX_TEMPLATE_LEN	10
22 #define MAX_TRIES		100
23 
24 #define SUFFIX	".suff"
25 #define SLEN	(sizeof SUFFIX - 1)
26 
27 long pg;
28 
29 /*
30  * verify that a path generated by mkstemp() or mkstemp() looks like a
31  * reasonable expansion of the template and matches the fd.  Returns true
32  * if all the X's were replaced with non-X's
33  */
34 int
35 check(int fd, char const *path, char const *prefix, size_t plen,
36     char const *suffix, size_t slen, int tlen)
37 {
38 	struct stat sb, fsb;
39 	char const *p;
40 
41 	if (fd < 0)
42 		err(1, "mkstemp");
43 	if (stat(path, &sb))
44 		err(1, "stat(%s)", path);
45 	if (fstat(fd, &fsb))
46 		err(1, "fstat(%d==%s)", fd, path);
47 	if (sb.st_dev != fsb.st_dev || sb.st_ino != fsb.st_ino)
48 		errx(1, "stat mismatch");
49 	close(fd);
50 	if (memcmp(path, prefix, plen) != 0)
51 		errx(1, "prefix changed!  %s vs %s", prefix, path);
52 	if (memcmp(path + plen + tlen, suffix, slen + 1) != 0)
53 		errx(1, "suffix changed!  %s vs %s", suffix, path);
54 	for (p = path + plen; p < path + plen + tlen; p++)
55 		if (*p == '\0')
56 			errx(1, "unexpected truncation");
57 		else if (*p == 'X')
58 			return 0;
59 	return 1;
60 }
61 
62 
63 void
64 try_mkstemp(char *p, char const *prefix, int len)
65 {
66 	char *q;
67 	size_t plen = strlen(prefix);
68 	int tries, fd;
69 
70 	for (tries = 0; tries < MAX_TRIES; tries++) {
71 		memcpy(p, prefix, plen);
72 		memset(p + plen, 'X', len);
73 		p[plen + len] = '\0';
74 		fd = mkstemp(p);
75 		if (check(fd, p, prefix, plen, "", 0, len))
76 			return;
77 	}
78 	errx(1, "exceeded MAX_TRIES");
79 }
80 
81 void
82 try_mkstemps(char *p, char const *prefix, int len, char const *suffix)
83 {
84 	char *q;
85 	size_t plen = strlen(prefix);
86 	size_t slen = strlen(suffix);
87 	int tries, fd;
88 
89 	for (tries = 0; tries < MAX_TRIES; tries++) {
90 		memcpy(p, prefix, plen);
91 		memset(p + plen, 'X', len);
92 		memcpy(p + plen + len, suffix, slen + 1);
93 		fd = mkstemps(p, slen);
94 		if (check(fd, p, prefix, plen, suffix, slen, len))
95 			return;
96 	}
97 	errx(1, "exceeded MAX_TRIES");
98 }
99 
100 int
101 main(void)
102 {
103 	struct stat sb, fsb;
104 	char cwd[MAXPATHLEN + 1];
105 	char *p;
106 	size_t clen;
107 	int i;
108 
109 	pg = sysconf(_SC_PAGESIZE);
110 	if (getcwd(cwd, sizeof cwd - 1) == NULL)
111 		err(1, "getcwd");
112 	clen = strlen(cwd);
113 	cwd[clen++] = '/';
114 	cwd[clen] = '\0';
115 	p = mmap(NULL, pg * 3, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0);
116 	if (p == NULL)
117 		err(1, "mmap");
118 	if (mprotect(p, pg, PROT_NONE) || mprotect(p + pg * 2, pg, PROT_NONE))
119 		err(1, "mprotect");
120 	p += pg;
121 
122 	i = MAX_TEMPLATE_LEN + 1;
123 	while (i-- > 1) {
124 		/* try first at the start of a page, no prefix */
125 		try_mkstemp(p, "", i);
126 		/* now at the end of the page, no prefix */
127 		try_mkstemp(p + pg - i - 1, "", i);
128 		/* start of the page, prefixed with the cwd */
129 		try_mkstemp(p, cwd, i);
130 		/* how about at the end of the page, prefixed with cwd? */
131 		try_mkstemp(p + pg - clen - i - 1, cwd, i);
132 
133 		/* again, with mkstemps() and an empty suffix */
134 		/* try first at the start of a page, no prefix */
135 		try_mkstemps(p, "", i, "");
136 		/* now at the end of the page, no prefix */
137 		try_mkstemps(p + pg - i - 1, "", i, "");
138 		/* start of the page, prefixed with the cwd */
139 		try_mkstemps(p, cwd, i, "");
140 		/* how about at the end of the page, prefixed with cwd? */
141 		try_mkstemps(p + pg - clen - i - 1, cwd, i, "");
142 
143 		/* mkstemps() and a non-empty suffix */
144 		/* try first at the start of a page, no prefix */
145 		try_mkstemps(p, "", i, SUFFIX);
146 		/* now at the end of the page, no prefix */
147 		try_mkstemps(p + pg - i - SLEN - 1, "", i, SUFFIX);
148 		/* start of the page, prefixed with the cwd */
149 		try_mkstemps(p, cwd, i, SUFFIX);
150 		/* how about at the end of the page, prefixed with cwd? */
151 		try_mkstemps(p + pg - clen - i - SLEN - 1, cwd, i, SUFFIX);
152 
153 	}
154 
155 	return 0;
156 }
157