]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - crypto/heimdal/lib/asn1/check-common.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / crypto / heimdal / lib / asn1 / check-common.c
1 /*
2  * Copyright (c) 1999 - 2006 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden). 
4  * All rights reserved. 
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met: 
9  *
10  * 1. Redistributions of source code must retain the above copyright 
11  *    notice, this list of conditions and the following disclaimer. 
12  *
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. 
16  *
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. 
20  *
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. 
32  */
33
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>
44
45 #include "check-common.h"
46
47 RCSID("$Id: check-common.c 18751 2006-10-21 14:49:13Z lha $");
48
49 struct map_page {
50     void *start;
51     size_t size;
52     void *data_start;
53     size_t data_size;
54     enum map_type type;
55 };
56
57 /* #undef HAVE_MMAP */
58
59 void *
60 map_alloc(enum map_type type, const void *buf, 
61           size_t size, struct map_page **map)
62 {
63 #ifndef HAVE_MMAP
64     unsigned char *p;
65     size_t len = size + sizeof(long) * 2;
66     int i;
67     
68     *map = ecalloc(1, sizeof(**map));
69
70     p = emalloc(len);
71     (*map)->type = type;
72     (*map)->start = p;
73     (*map)->size = len;
74     (*map)->data_start = p + sizeof(long);
75     for (i = sizeof(long); i > 0; i--)
76         p[sizeof(long) - i] = 0xff - i;
77     for (i = sizeof(long); i > 0; i--)
78         p[len - i] = 0xff - i;
79 #else
80     unsigned char *p;
81     int flags, ret, fd;
82     size_t pagesize = getpagesize();
83
84     *map = ecalloc(1, sizeof(**map));
85
86     (*map)->type = type;
87
88 #ifdef MAP_ANON
89     flags = MAP_ANON;
90     fd = -1;
91 #else
92     flags = 0;
93     fd = open ("/dev/zero", O_RDONLY);
94     if(fd < 0)
95         err (1, "open /dev/zero");
96 #endif
97     flags |= MAP_PRIVATE;
98
99     (*map)->size = size + pagesize - (size % pagesize) + pagesize * 2;
100
101     p = (unsigned char *)mmap(0, (*map)->size, PROT_READ | PROT_WRITE,
102                               flags, fd, 0);
103     if (p == (unsigned char *)MAP_FAILED)
104         err (1, "mmap");
105
106     (*map)->start = p;
107
108     ret = mprotect (p, pagesize, 0);
109     if (ret < 0)
110         err (1, "mprotect");
111
112     ret = mprotect (p + (*map)->size - pagesize, pagesize, 0);
113     if (ret < 0)
114         err (1, "mprotect");
115
116     switch (type) {
117     case OVERRUN:
118         (*map)->data_start = p + (*map)->size - pagesize - size;
119         break;
120     case UNDERRUN:
121         (*map)->data_start = p + pagesize;
122         break;
123    default:
124         abort();
125     }
126 #endif
127     (*map)->data_size = size;
128     if (buf)
129         memcpy((*map)->data_start, buf, size);
130     return (*map)->data_start;
131 }
132
133 void
134 map_free(struct map_page *map, const char *test_name, const char *map_name)
135 {
136 #ifndef HAVE_MMAP
137     unsigned char *p = map->start;
138     int i;
139     
140     for (i = sizeof(long); i > 0; i--)
141         if (p[sizeof(long) - i] != 0xff - i)
142             errx(1, "%s: %s underrun %d\n", test_name, map_name, i);
143     for (i = sizeof(long); i > 0; i--)
144         if (p[map->size - i] != 0xff - i)
145             errx(1, "%s: %s overrun %lu\n", test_name, map_name, 
146                  (unsigned long)map->size - i);
147     free(map->start);
148 #else
149     int ret;
150     
151     ret = munmap (map->start, map->size);
152     if (ret < 0)
153         err (1, "munmap");
154 #endif
155     free(map);
156 }
157
158 static void
159 print_bytes (unsigned const char *buf, size_t len)
160 {
161     int i;
162
163     for (i = 0; i < len; ++i)
164         printf ("%02x ", buf[i]);
165 }
166
167 #ifndef MAP_FAILED
168 #define MAP_FAILED (-1)
169 #endif
170
171 static char *current_test = "<uninit>";
172 static char *current_state = "<uninit>";
173
174 static RETSIGTYPE
175 segv_handler(int sig)
176 {
177     int fd;
178     char msg[] = "SIGSEGV i current test: ";
179     
180     fd = open("/dev/stdout", O_WRONLY, 0600);
181     if (fd >= 0) {
182         write(fd, msg, sizeof(msg));
183         write(fd, current_test, strlen(current_test));
184         write(fd, " ", 1);
185         write(fd, current_state, strlen(current_state));
186         write(fd, "\n", 1);
187         close(fd);
188     }
189     _exit(1);
190 }
191
192 int
193 generic_test (const struct test_case *tests,
194               unsigned ntests,
195               size_t data_size,
196               int (*encode)(unsigned char *, size_t, void *, size_t *),
197               int (*length)(void *),
198               int (*decode)(unsigned char *, size_t, void *, size_t *),
199               int (*free_data)(void *),
200               int (*cmp)(void *a, void *b))
201 {
202     unsigned char *buf, *buf2;
203     int i;
204     int failures = 0;
205     void *data;
206     struct map_page *data_map, *buf_map, *buf2_map;
207
208     struct sigaction sa, osa;
209
210     for (i = 0; i < ntests; ++i) {
211         int ret;
212         size_t sz, consumed_sz, length_sz, buf_sz;
213
214         current_test = tests[i].name;
215
216         current_state = "init";
217
218         sigemptyset (&sa.sa_mask);
219         sa.sa_flags = 0;
220 #ifdef SA_RESETHAND
221         sa.sa_flags |= SA_RESETHAND;
222 #endif
223         sa.sa_handler = segv_handler;
224         sigaction (SIGSEGV, &sa, &osa);
225
226         data = map_alloc(OVERRUN, NULL, data_size, &data_map);
227
228         buf_sz = tests[i].byte_len;
229         buf = map_alloc(UNDERRUN, NULL, buf_sz, &buf_map);
230
231         current_state = "encode";
232         ret = (*encode) (buf + buf_sz - 1, buf_sz,
233                          tests[i].val, &sz);
234         if (ret != 0) {
235             printf ("encoding of %s failed %d\n", tests[i].name, ret);
236             ++failures;
237             continue;
238         }
239         if (sz != tests[i].byte_len) {
240             printf ("encoding of %s has wrong len (%lu != %lu)\n",
241                     tests[i].name, 
242                     (unsigned long)sz, (unsigned long)tests[i].byte_len);
243             ++failures;
244             continue;
245         }
246
247         current_state = "length";
248         length_sz = (*length) (tests[i].val);
249         if (sz != length_sz) {
250             printf ("length for %s is bad (%lu != %lu)\n",
251                     tests[i].name, (unsigned long)length_sz, (unsigned long)sz);
252             ++failures;
253             continue;
254         }
255
256         current_state = "memcmp";
257         if (memcmp (buf, tests[i].bytes, tests[i].byte_len) != 0) {
258             printf ("encoding of %s has bad bytes:\n"
259                     "correct: ", tests[i].name);
260             print_bytes ((unsigned char *)tests[i].bytes, tests[i].byte_len);
261             printf ("\nactual:  ");
262             print_bytes (buf, sz);
263             printf ("\n");
264             ++failures;
265             continue;
266         }
267
268         buf2 = map_alloc(OVERRUN, buf, sz, &buf2_map);
269
270         current_state = "decode";
271         ret = (*decode) (buf2, sz, data, &consumed_sz);
272         if (ret != 0) {
273             printf ("decoding of %s failed %d\n", tests[i].name, ret);
274             ++failures;
275             continue;
276         }
277         if (sz != consumed_sz) {
278             printf ("different length decoding %s (%ld != %ld)\n",
279                     tests[i].name, 
280                     (unsigned long)sz, (unsigned long)consumed_sz);
281             ++failures;
282             continue;
283         }
284         current_state = "cmp";
285         if ((*cmp)(data, tests[i].val) != 0) {
286             printf ("%s: comparison failed\n", tests[i].name);
287             ++failures;
288             continue;
289         }
290         current_state = "free";
291         if (free_data)
292             (*free_data)(data);
293
294         current_state = "free";
295         map_free(buf_map, tests[i].name, "encode");
296         map_free(buf2_map, tests[i].name, "decode");
297         map_free(data_map, tests[i].name, "data");
298
299         sigaction (SIGSEGV, &osa, NULL);
300     }
301     current_state = "done";
302     return failures;
303 }
304
305 /*
306  * check for failures
307  * 
308  * a test size (byte_len) of -1 means that the test tries to trigger a
309  * integer overflow (and later a malloc of to little memory), just
310  * allocate some memory and hope that is enough for that test.
311  */
312
313 int
314 generic_decode_fail (const struct test_case *tests,
315                      unsigned ntests,
316                      size_t data_size,
317                      int (*decode)(unsigned char *, size_t, void *, size_t *))
318 {
319     unsigned char *buf;
320     int i;
321     int failures = 0;
322     void *data;
323     struct map_page *data_map, *buf_map;
324
325     struct sigaction sa, osa;
326
327     for (i = 0; i < ntests; ++i) {
328         int ret;
329         size_t sz;
330         const void *bytes;
331         
332         current_test = tests[i].name;
333
334         current_state = "init";
335
336         sigemptyset (&sa.sa_mask);
337         sa.sa_flags = 0;
338 #ifdef SA_RESETHAND
339         sa.sa_flags |= SA_RESETHAND;
340 #endif
341         sa.sa_handler = segv_handler;
342         sigaction (SIGSEGV, &sa, &osa);
343
344         data = map_alloc(OVERRUN, NULL, data_size, &data_map);
345
346         if (tests[i].byte_len < 0xffffff && tests[i].byte_len >= 0) {
347             sz = tests[i].byte_len;
348             bytes = tests[i].bytes;
349         } else {
350             sz = 4096;
351             bytes = NULL;
352         }
353                 
354         buf = map_alloc(OVERRUN, bytes, sz, &buf_map);
355
356         if (tests[i].byte_len == -1)
357             memset(buf, 0, sz);
358
359         current_state = "decode";
360         ret = (*decode) (buf, tests[i].byte_len, data, &sz);
361         if (ret == 0) {
362             printf ("sucessfully decoded %s\n", tests[i].name);
363             ++failures;
364             continue;
365         }
366
367         current_state = "free";
368         if (buf)
369             map_free(buf_map, tests[i].name, "encode");
370         map_free(data_map, tests[i].name, "data");
371
372         sigaction (SIGSEGV, &osa, NULL);
373     }
374     current_state = "done";
375     return failures;
376 }