No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / heimdal / lib / asn1 / check-common.c
blob177ea4443c5d6f7ad70e8316736cc79bd93bf37b
1 /*
2 * Copyright (c) 1999 - 2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37 #ifdef HAVE_SYS_MMAN_H
38 #include <sys/mman.h>
39 #endif
40 #include <stdio.h>
41 #include <string.h>
42 #include <err.h>
43 #include <roken.h>
45 #include "check-common.h"
47 __RCSID("$Heimdal: check-common.c 18751 2006-10-21 14:49:13Z lha $"
48 "$NetBSD$");
50 struct map_page {
51 void *start;
52 size_t size;
53 void *data_start;
54 size_t data_size;
55 enum map_type type;
58 /* #undef HAVE_MMAP */
60 void *
61 map_alloc(enum map_type type, const void *buf,
62 size_t size, struct map_page **map)
64 #ifndef HAVE_MMAP
65 unsigned char *p;
66 size_t len = size + sizeof(long) * 2;
67 int i;
69 *map = ecalloc(1, sizeof(**map));
71 p = emalloc(len);
72 (*map)->type = type;
73 (*map)->start = p;
74 (*map)->size = len;
75 (*map)->data_start = p + sizeof(long);
76 for (i = sizeof(long); i > 0; i--)
77 p[sizeof(long) - i] = 0xff - i;
78 for (i = sizeof(long); i > 0; i--)
79 p[len - i] = 0xff - i;
80 #else
81 unsigned char *p;
82 int flags, ret, fd;
83 size_t pagesize = getpagesize();
85 *map = ecalloc(1, sizeof(**map));
87 (*map)->type = type;
89 #ifdef MAP_ANON
90 flags = MAP_ANON;
91 fd = -1;
92 #else
93 flags = 0;
94 fd = open ("/dev/zero", O_RDONLY);
95 if(fd < 0)
96 err (1, "open /dev/zero");
97 #endif
98 flags |= MAP_PRIVATE;
100 (*map)->size = size + pagesize - (size % pagesize) + pagesize * 2;
102 p = (unsigned char *)mmap(0, (*map)->size, PROT_READ | PROT_WRITE,
103 flags, fd, 0);
104 if (p == (unsigned char *)MAP_FAILED)
105 err (1, "mmap");
107 (*map)->start = p;
109 ret = mprotect (p, pagesize, 0);
110 if (ret < 0)
111 err (1, "mprotect");
113 ret = mprotect (p + (*map)->size - pagesize, pagesize, 0);
114 if (ret < 0)
115 err (1, "mprotect");
117 switch (type) {
118 case OVERRUN:
119 (*map)->data_start = p + (*map)->size - pagesize - size;
120 break;
121 case UNDERRUN:
122 (*map)->data_start = p + pagesize;
123 break;
124 default:
125 abort();
127 #endif
128 (*map)->data_size = size;
129 if (buf)
130 memcpy((*map)->data_start, buf, size);
131 return (*map)->data_start;
134 void
135 map_free(struct map_page *map, const char *test_name, const char *map_name)
137 #ifndef HAVE_MMAP
138 unsigned char *p = map->start;
139 int i;
141 for (i = sizeof(long); i > 0; i--)
142 if (p[sizeof(long) - i] != 0xff - i)
143 errx(1, "%s: %s underrun %d\n", test_name, map_name, i);
144 for (i = sizeof(long); i > 0; i--)
145 if (p[map->size - i] != 0xff - i)
146 errx(1, "%s: %s overrun %lu\n", test_name, map_name,
147 (unsigned long)map->size - i);
148 free(map->start);
149 #else
150 int ret;
152 ret = munmap (map->start, map->size);
153 if (ret < 0)
154 err (1, "munmap");
155 #endif
156 free(map);
159 static void
160 print_bytes (unsigned const char *buf, size_t len)
162 int i;
164 for (i = 0; i < len; ++i)
165 printf ("%02x ", buf[i]);
168 #ifndef MAP_FAILED
169 #define MAP_FAILED (-1)
170 #endif
172 static char *current_test = "<uninit>";
173 static char *current_state = "<uninit>";
175 static RETSIGTYPE
176 segv_handler(int sig)
178 int fd;
179 char msg[] = "SIGSEGV i current test: ";
181 fd = open("/dev/stdout", O_WRONLY, 0600);
182 if (fd >= 0) {
183 write(fd, msg, sizeof(msg));
184 write(fd, current_test, strlen(current_test));
185 write(fd, " ", 1);
186 write(fd, current_state, strlen(current_state));
187 write(fd, "\n", 1);
188 close(fd);
190 _exit(1);
194 generic_test (const struct test_case *tests,
195 unsigned ntests,
196 size_t data_size,
197 int (*encode)(unsigned char *, size_t, void *, size_t *),
198 int (*length)(void *),
199 int (*decode)(unsigned char *, size_t, void *, size_t *),
200 int (*free_data)(void *),
201 int (*cmp)(void *a, void *b))
203 unsigned char *buf, *buf2;
204 int i;
205 int failures = 0;
206 void *data;
207 struct map_page *data_map, *buf_map, *buf2_map;
209 struct sigaction sa, osa;
211 for (i = 0; i < ntests; ++i) {
212 int ret;
213 size_t sz, consumed_sz, length_sz, buf_sz;
215 current_test = tests[i].name;
217 current_state = "init";
219 sigemptyset (&sa.sa_mask);
220 sa.sa_flags = 0;
221 #ifdef SA_RESETHAND
222 sa.sa_flags |= SA_RESETHAND;
223 #endif
224 sa.sa_handler = segv_handler;
225 sigaction (SIGSEGV, &sa, &osa);
227 data = map_alloc(OVERRUN, NULL, data_size, &data_map);
229 buf_sz = tests[i].byte_len;
230 buf = map_alloc(UNDERRUN, NULL, buf_sz, &buf_map);
232 current_state = "encode";
233 ret = (*encode) (buf + buf_sz - 1, buf_sz,
234 tests[i].val, &sz);
235 if (ret != 0) {
236 printf ("encoding of %s failed %d\n", tests[i].name, ret);
237 ++failures;
238 continue;
240 if (sz != tests[i].byte_len) {
241 printf ("encoding of %s has wrong len (%lu != %lu)\n",
242 tests[i].name,
243 (unsigned long)sz, (unsigned long)tests[i].byte_len);
244 ++failures;
245 continue;
248 current_state = "length";
249 length_sz = (*length) (tests[i].val);
250 if (sz != length_sz) {
251 printf ("length for %s is bad (%lu != %lu)\n",
252 tests[i].name, (unsigned long)length_sz, (unsigned long)sz);
253 ++failures;
254 continue;
257 current_state = "memcmp";
258 if (memcmp (buf, tests[i].bytes, tests[i].byte_len) != 0) {
259 printf ("encoding of %s has bad bytes:\n"
260 "correct: ", tests[i].name);
261 print_bytes ((unsigned char *)tests[i].bytes, tests[i].byte_len);
262 printf ("\nactual: ");
263 print_bytes (buf, sz);
264 printf ("\n");
265 ++failures;
266 continue;
269 buf2 = map_alloc(OVERRUN, buf, sz, &buf2_map);
271 current_state = "decode";
272 ret = (*decode) (buf2, sz, data, &consumed_sz);
273 if (ret != 0) {
274 printf ("decoding of %s failed %d\n", tests[i].name, ret);
275 ++failures;
276 continue;
278 if (sz != consumed_sz) {
279 printf ("different length decoding %s (%ld != %ld)\n",
280 tests[i].name,
281 (unsigned long)sz, (unsigned long)consumed_sz);
282 ++failures;
283 continue;
285 current_state = "cmp";
286 if ((*cmp)(data, tests[i].val) != 0) {
287 printf ("%s: comparison failed\n", tests[i].name);
288 ++failures;
289 continue;
291 current_state = "free";
292 if (free_data)
293 (*free_data)(data);
295 current_state = "free";
296 map_free(buf_map, tests[i].name, "encode");
297 map_free(buf2_map, tests[i].name, "decode");
298 map_free(data_map, tests[i].name, "data");
300 sigaction (SIGSEGV, &osa, NULL);
302 current_state = "done";
303 return failures;
307 * check for failures
309 * a test size (byte_len) of -1 means that the test tries to trigger a
310 * integer overflow (and later a malloc of to little memory), just
311 * allocate some memory and hope that is enough for that test.
315 generic_decode_fail (const struct test_case *tests,
316 unsigned ntests,
317 size_t data_size,
318 int (*decode)(unsigned char *, size_t, void *, size_t *))
320 unsigned char *buf;
321 int i;
322 int failures = 0;
323 void *data;
324 struct map_page *data_map, *buf_map;
326 struct sigaction sa, osa;
328 for (i = 0; i < ntests; ++i) {
329 int ret;
330 size_t sz;
331 const void *bytes;
333 current_test = tests[i].name;
335 current_state = "init";
337 sigemptyset (&sa.sa_mask);
338 sa.sa_flags = 0;
339 #ifdef SA_RESETHAND
340 sa.sa_flags |= SA_RESETHAND;
341 #endif
342 sa.sa_handler = segv_handler;
343 sigaction (SIGSEGV, &sa, &osa);
345 data = map_alloc(OVERRUN, NULL, data_size, &data_map);
347 if (tests[i].byte_len < 0xffffff && tests[i].byte_len >= 0) {
348 sz = tests[i].byte_len;
349 bytes = tests[i].bytes;
350 } else {
351 sz = 4096;
352 bytes = NULL;
355 buf = map_alloc(OVERRUN, bytes, sz, &buf_map);
357 if (tests[i].byte_len == -1)
358 memset(buf, 0, sz);
360 current_state = "decode";
361 ret = (*decode) (buf, tests[i].byte_len, data, &sz);
362 if (ret == 0) {
363 printf ("sucessfully decoded %s\n", tests[i].name);
364 ++failures;
365 continue;
368 current_state = "free";
369 if (buf)
370 map_free(buf_map, tests[i].name, "encode");
371 map_free(data_map, tests[i].name, "data");
373 sigaction (SIGSEGV, &osa, NULL);
375 current_state = "done";
376 return failures;