xref: /freebsd/crypto/heimdal/lib/asn1/check-common.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
1bbd80c28SJacques Vidrine /*
2*ae771770SStanislav Sedov  * Copyright (c) 1999 - 2006 Kungliga Tekniska Högskolan
3bbd80c28SJacques Vidrine  * (Royal Institute of Technology, Stockholm, Sweden).
4bbd80c28SJacques Vidrine  * All rights reserved.
5bbd80c28SJacques Vidrine  *
6*ae771770SStanislav Sedov  * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
7*ae771770SStanislav Sedov  *
8bbd80c28SJacques Vidrine  * Redistribution and use in source and binary forms, with or without
9bbd80c28SJacques Vidrine  * modification, are permitted provided that the following conditions
10bbd80c28SJacques Vidrine  * are met:
11bbd80c28SJacques Vidrine  *
12bbd80c28SJacques Vidrine  * 1. Redistributions of source code must retain the above copyright
13bbd80c28SJacques Vidrine  *    notice, this list of conditions and the following disclaimer.
14bbd80c28SJacques Vidrine  *
15bbd80c28SJacques Vidrine  * 2. Redistributions in binary form must reproduce the above copyright
16bbd80c28SJacques Vidrine  *    notice, this list of conditions and the following disclaimer in the
17bbd80c28SJacques Vidrine  *    documentation and/or other materials provided with the distribution.
18bbd80c28SJacques Vidrine  *
19bbd80c28SJacques Vidrine  * 3. Neither the name of the Institute nor the names of its contributors
20bbd80c28SJacques Vidrine  *    may be used to endorse or promote products derived from this software
21bbd80c28SJacques Vidrine  *    without specific prior written permission.
22bbd80c28SJacques Vidrine  *
23bbd80c28SJacques Vidrine  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24bbd80c28SJacques Vidrine  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25bbd80c28SJacques Vidrine  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26bbd80c28SJacques Vidrine  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27bbd80c28SJacques Vidrine  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28bbd80c28SJacques Vidrine  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29bbd80c28SJacques Vidrine  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30bbd80c28SJacques Vidrine  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31bbd80c28SJacques Vidrine  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32bbd80c28SJacques Vidrine  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33bbd80c28SJacques Vidrine  * SUCH DAMAGE.
34bbd80c28SJacques Vidrine  */
35bbd80c28SJacques Vidrine 
36bbd80c28SJacques Vidrine #ifdef HAVE_CONFIG_H
37bbd80c28SJacques Vidrine #include <config.h>
38bbd80c28SJacques Vidrine #endif
39c19800e8SDoug Rabson #ifdef HAVE_SYS_MMAN_H
40c19800e8SDoug Rabson #include <sys/mman.h>
41c19800e8SDoug Rabson #endif
42bbd80c28SJacques Vidrine #include <stdio.h>
43bbd80c28SJacques Vidrine #include <string.h>
44bbd80c28SJacques Vidrine #include <err.h>
45bbd80c28SJacques Vidrine #include <roken.h>
46bbd80c28SJacques Vidrine 
47*ae771770SStanislav Sedov #include "asn1-common.h"
48bbd80c28SJacques Vidrine #include "check-common.h"
49bbd80c28SJacques Vidrine 
50*ae771770SStanislav Sedov RCSID("$Id$");
51c19800e8SDoug Rabson 
52c19800e8SDoug Rabson struct map_page {
53c19800e8SDoug Rabson     void *start;
54c19800e8SDoug Rabson     size_t size;
55c19800e8SDoug Rabson     void *data_start;
56c19800e8SDoug Rabson     size_t data_size;
57c19800e8SDoug Rabson     enum map_type type;
58c19800e8SDoug Rabson };
59c19800e8SDoug Rabson 
60c19800e8SDoug Rabson /* #undef HAVE_MMAP */
61c19800e8SDoug Rabson 
62c19800e8SDoug Rabson void *
map_alloc(enum map_type type,const void * buf,size_t size,struct map_page ** map)63c19800e8SDoug Rabson map_alloc(enum map_type type, const void *buf,
64c19800e8SDoug Rabson 	  size_t size, struct map_page **map)
65c19800e8SDoug Rabson {
66c19800e8SDoug Rabson #ifndef HAVE_MMAP
67c19800e8SDoug Rabson     unsigned char *p;
68c19800e8SDoug Rabson     size_t len = size + sizeof(long) * 2;
69c19800e8SDoug Rabson     int i;
70c19800e8SDoug Rabson 
71c19800e8SDoug Rabson     *map = ecalloc(1, sizeof(**map));
72c19800e8SDoug Rabson 
73c19800e8SDoug Rabson     p = emalloc(len);
74c19800e8SDoug Rabson     (*map)->type = type;
75c19800e8SDoug Rabson     (*map)->start = p;
76c19800e8SDoug Rabson     (*map)->size = len;
77c19800e8SDoug Rabson     (*map)->data_start = p + sizeof(long);
78c19800e8SDoug Rabson     for (i = sizeof(long); i > 0; i--)
79c19800e8SDoug Rabson 	p[sizeof(long) - i] = 0xff - i;
80c19800e8SDoug Rabson     for (i = sizeof(long); i > 0; i--)
81c19800e8SDoug Rabson 	p[len - i] = 0xff - i;
82c19800e8SDoug Rabson #else
83c19800e8SDoug Rabson     unsigned char *p;
84c19800e8SDoug Rabson     int flags, ret, fd;
85c19800e8SDoug Rabson     size_t pagesize = getpagesize();
86c19800e8SDoug Rabson 
87c19800e8SDoug Rabson     *map = ecalloc(1, sizeof(**map));
88c19800e8SDoug Rabson 
89c19800e8SDoug Rabson     (*map)->type = type;
90c19800e8SDoug Rabson 
91c19800e8SDoug Rabson #ifdef MAP_ANON
92c19800e8SDoug Rabson     flags = MAP_ANON;
93c19800e8SDoug Rabson     fd = -1;
94c19800e8SDoug Rabson #else
95c19800e8SDoug Rabson     flags = 0;
96c19800e8SDoug Rabson     fd = open ("/dev/zero", O_RDONLY);
97c19800e8SDoug Rabson     if(fd < 0)
98c19800e8SDoug Rabson 	err (1, "open /dev/zero");
99c19800e8SDoug Rabson #endif
100c19800e8SDoug Rabson     flags |= MAP_PRIVATE;
101c19800e8SDoug Rabson 
102c19800e8SDoug Rabson     (*map)->size = size + pagesize - (size % pagesize) + pagesize * 2;
103c19800e8SDoug Rabson 
104c19800e8SDoug Rabson     p = (unsigned char *)mmap(0, (*map)->size, PROT_READ | PROT_WRITE,
105c19800e8SDoug Rabson 			      flags, fd, 0);
106c19800e8SDoug Rabson     if (p == (unsigned char *)MAP_FAILED)
107c19800e8SDoug Rabson 	err (1, "mmap");
108c19800e8SDoug Rabson 
109c19800e8SDoug Rabson     (*map)->start = p;
110c19800e8SDoug Rabson 
111c19800e8SDoug Rabson     ret = mprotect (p, pagesize, 0);
112c19800e8SDoug Rabson     if (ret < 0)
113c19800e8SDoug Rabson 	err (1, "mprotect");
114c19800e8SDoug Rabson 
115c19800e8SDoug Rabson     ret = mprotect (p + (*map)->size - pagesize, pagesize, 0);
116c19800e8SDoug Rabson     if (ret < 0)
117c19800e8SDoug Rabson 	err (1, "mprotect");
118c19800e8SDoug Rabson 
119c19800e8SDoug Rabson     switch (type) {
120c19800e8SDoug Rabson     case OVERRUN:
121c19800e8SDoug Rabson 	(*map)->data_start = p + (*map)->size - pagesize - size;
122c19800e8SDoug Rabson 	break;
123c19800e8SDoug Rabson     case UNDERRUN:
124c19800e8SDoug Rabson 	(*map)->data_start = p + pagesize;
125c19800e8SDoug Rabson 	break;
126c19800e8SDoug Rabson    default:
127c19800e8SDoug Rabson 	abort();
128c19800e8SDoug Rabson     }
129c19800e8SDoug Rabson #endif
130c19800e8SDoug Rabson     (*map)->data_size = size;
131c19800e8SDoug Rabson     if (buf)
132c19800e8SDoug Rabson 	memcpy((*map)->data_start, buf, size);
133c19800e8SDoug Rabson     return (*map)->data_start;
134c19800e8SDoug Rabson }
135c19800e8SDoug Rabson 
136c19800e8SDoug Rabson void
map_free(struct map_page * map,const char * test_name,const char * map_name)137c19800e8SDoug Rabson map_free(struct map_page *map, const char *test_name, const char *map_name)
138c19800e8SDoug Rabson {
139c19800e8SDoug Rabson #ifndef HAVE_MMAP
140c19800e8SDoug Rabson     unsigned char *p = map->start;
141c19800e8SDoug Rabson     int i;
142c19800e8SDoug Rabson 
143c19800e8SDoug Rabson     for (i = sizeof(long); i > 0; i--)
144c19800e8SDoug Rabson 	if (p[sizeof(long) - i] != 0xff - i)
145c19800e8SDoug Rabson 	    errx(1, "%s: %s underrun %d\n", test_name, map_name, i);
146c19800e8SDoug Rabson     for (i = sizeof(long); i > 0; i--)
147c19800e8SDoug Rabson 	if (p[map->size - i] != 0xff - i)
148c19800e8SDoug Rabson 	    errx(1, "%s: %s overrun %lu\n", test_name, map_name,
149c19800e8SDoug Rabson 		 (unsigned long)map->size - i);
150c19800e8SDoug Rabson     free(map->start);
151c19800e8SDoug Rabson #else
152c19800e8SDoug Rabson     int ret;
153c19800e8SDoug Rabson 
154c19800e8SDoug Rabson     ret = munmap (map->start, map->size);
155c19800e8SDoug Rabson     if (ret < 0)
156c19800e8SDoug Rabson 	err (1, "munmap");
157c19800e8SDoug Rabson #endif
158c19800e8SDoug Rabson     free(map);
159c19800e8SDoug Rabson }
160bbd80c28SJacques Vidrine 
161bbd80c28SJacques Vidrine static void
print_bytes(unsigned const char * buf,size_t len)162bbd80c28SJacques Vidrine print_bytes (unsigned const char *buf, size_t len)
163bbd80c28SJacques Vidrine {
164bbd80c28SJacques Vidrine     int i;
165bbd80c28SJacques Vidrine 
166bbd80c28SJacques Vidrine     for (i = 0; i < len; ++i)
167bbd80c28SJacques Vidrine 	printf ("%02x ", buf[i]);
168bbd80c28SJacques Vidrine }
169bbd80c28SJacques Vidrine 
170c19800e8SDoug Rabson #ifndef MAP_FAILED
171c19800e8SDoug Rabson #define MAP_FAILED (-1)
172c19800e8SDoug Rabson #endif
173c19800e8SDoug Rabson 
174c19800e8SDoug Rabson static char *current_test = "<uninit>";
175c19800e8SDoug Rabson static char *current_state = "<uninit>";
176c19800e8SDoug Rabson 
177c19800e8SDoug Rabson static RETSIGTYPE
segv_handler(int sig)178c19800e8SDoug Rabson segv_handler(int sig)
179c19800e8SDoug Rabson {
180c19800e8SDoug Rabson     int fd;
181c19800e8SDoug Rabson     char msg[] = "SIGSEGV i current test: ";
182c19800e8SDoug Rabson 
183c19800e8SDoug Rabson     fd = open("/dev/stdout", O_WRONLY, 0600);
184c19800e8SDoug Rabson     if (fd >= 0) {
185c19800e8SDoug Rabson 	write(fd, msg, sizeof(msg));
186c19800e8SDoug Rabson 	write(fd, current_test, strlen(current_test));
187c19800e8SDoug Rabson 	write(fd, " ", 1);
188c19800e8SDoug Rabson 	write(fd, current_state, strlen(current_state));
189c19800e8SDoug Rabson 	write(fd, "\n", 1);
190c19800e8SDoug Rabson 	close(fd);
191c19800e8SDoug Rabson     }
192c19800e8SDoug Rabson     _exit(1);
193c19800e8SDoug Rabson }
194c19800e8SDoug Rabson 
195bbd80c28SJacques Vidrine int
generic_test(const struct test_case * tests,unsigned ntests,size_t data_size,int (ASN1CALL * encode)(unsigned char *,size_t,void *,size_t *),int (ASN1CALL * length)(void *),int (ASN1CALL * decode)(unsigned char *,size_t,void *,size_t *),int (ASN1CALL * free_data)(void *),int (* cmp)(void * a,void * b),int (ASN1CALL * copy)(const void * from,void * to))196bbd80c28SJacques Vidrine generic_test (const struct test_case *tests,
197bbd80c28SJacques Vidrine 	      unsigned ntests,
198bbd80c28SJacques Vidrine 	      size_t data_size,
199*ae771770SStanislav Sedov 	      int (ASN1CALL *encode)(unsigned char *, size_t, void *, size_t *),
200*ae771770SStanislav Sedov 	      int (ASN1CALL *length)(void *),
201*ae771770SStanislav Sedov 	      int (ASN1CALL *decode)(unsigned char *, size_t, void *, size_t *),
202*ae771770SStanislav Sedov 	      int (ASN1CALL *free_data)(void *),
203*ae771770SStanislav Sedov 	      int (*cmp)(void *a, void *b),
204*ae771770SStanislav Sedov 	      int (ASN1CALL *copy)(const void *from, void *to))
205bbd80c28SJacques Vidrine {
206c19800e8SDoug Rabson     unsigned char *buf, *buf2;
207bbd80c28SJacques Vidrine     int i;
208bbd80c28SJacques Vidrine     int failures = 0;
209c19800e8SDoug Rabson     void *data;
210c19800e8SDoug Rabson     struct map_page *data_map, *buf_map, *buf2_map;
211bbd80c28SJacques Vidrine 
212*ae771770SStanislav Sedov #ifdef HAVE_SIGACTION
213c19800e8SDoug Rabson     struct sigaction sa, osa;
214*ae771770SStanislav Sedov #endif
215bbd80c28SJacques Vidrine 
216bbd80c28SJacques Vidrine     for (i = 0; i < ntests; ++i) {
217bbd80c28SJacques Vidrine 	int ret;
218c19800e8SDoug Rabson 	size_t sz, consumed_sz, length_sz, buf_sz;
219*ae771770SStanislav Sedov 	void *to = NULL;
220bbd80c28SJacques Vidrine 
221c19800e8SDoug Rabson 	current_test = tests[i].name;
222c19800e8SDoug Rabson 
223c19800e8SDoug Rabson 	current_state = "init";
224c19800e8SDoug Rabson 
225*ae771770SStanislav Sedov #ifdef HAVE_SIGACTION
226c19800e8SDoug Rabson 	sigemptyset (&sa.sa_mask);
227c19800e8SDoug Rabson 	sa.sa_flags = 0;
228c19800e8SDoug Rabson #ifdef SA_RESETHAND
229c19800e8SDoug Rabson 	sa.sa_flags |= SA_RESETHAND;
230c19800e8SDoug Rabson #endif
231c19800e8SDoug Rabson 	sa.sa_handler = segv_handler;
232c19800e8SDoug Rabson 	sigaction (SIGSEGV, &sa, &osa);
233*ae771770SStanislav Sedov #endif
234c19800e8SDoug Rabson 
235c19800e8SDoug Rabson 	data = map_alloc(OVERRUN, NULL, data_size, &data_map);
236c19800e8SDoug Rabson 
237c19800e8SDoug Rabson 	buf_sz = tests[i].byte_len;
238c19800e8SDoug Rabson 	buf = map_alloc(UNDERRUN, NULL, buf_sz, &buf_map);
239c19800e8SDoug Rabson 
240c19800e8SDoug Rabson 	current_state = "encode";
241c19800e8SDoug Rabson 	ret = (*encode) (buf + buf_sz - 1, buf_sz,
242bbd80c28SJacques Vidrine 			 tests[i].val, &sz);
243bbd80c28SJacques Vidrine 	if (ret != 0) {
244c19800e8SDoug Rabson 	    printf ("encoding of %s failed %d\n", tests[i].name, ret);
245bbd80c28SJacques Vidrine 	    ++failures;
246c19800e8SDoug Rabson 	    continue;
247bbd80c28SJacques Vidrine 	}
248bbd80c28SJacques Vidrine 	if (sz != tests[i].byte_len) {
249bbd80c28SJacques Vidrine  	    printf ("encoding of %s has wrong len (%lu != %lu)\n",
250bbd80c28SJacques Vidrine 		    tests[i].name,
251bbd80c28SJacques Vidrine 		    (unsigned long)sz, (unsigned long)tests[i].byte_len);
252bbd80c28SJacques Vidrine 	    ++failures;
253c19800e8SDoug Rabson 	    continue;
254bbd80c28SJacques Vidrine 	}
255bbd80c28SJacques Vidrine 
256c19800e8SDoug Rabson 	current_state = "length";
257bbd80c28SJacques Vidrine 	length_sz = (*length) (tests[i].val);
258bbd80c28SJacques Vidrine 	if (sz != length_sz) {
259bbd80c28SJacques Vidrine 	    printf ("length for %s is bad (%lu != %lu)\n",
260bbd80c28SJacques Vidrine 		    tests[i].name, (unsigned long)length_sz, (unsigned long)sz);
261bbd80c28SJacques Vidrine 	    ++failures;
262c19800e8SDoug Rabson 	    continue;
263bbd80c28SJacques Vidrine 	}
264bbd80c28SJacques Vidrine 
265c19800e8SDoug Rabson 	current_state = "memcmp";
266c19800e8SDoug Rabson 	if (memcmp (buf, tests[i].bytes, tests[i].byte_len) != 0) {
267bbd80c28SJacques Vidrine 	    printf ("encoding of %s has bad bytes:\n"
268bbd80c28SJacques Vidrine 		    "correct: ", tests[i].name);
269c19800e8SDoug Rabson 	    print_bytes ((unsigned char *)tests[i].bytes, tests[i].byte_len);
270bbd80c28SJacques Vidrine 	    printf ("\nactual:  ");
271c19800e8SDoug Rabson 	    print_bytes (buf, sz);
272bbd80c28SJacques Vidrine 	    printf ("\n");
273*ae771770SStanislav Sedov #if 0
274*ae771770SStanislav Sedov 	    rk_dumpdata("correct", tests[i].bytes, tests[i].byte_len);
275*ae771770SStanislav Sedov 	    rk_dumpdata("actual", buf, sz);
276*ae771770SStanislav Sedov 	    exit (1);
277*ae771770SStanislav Sedov #endif
278bbd80c28SJacques Vidrine 	    ++failures;
279c19800e8SDoug Rabson 	    continue;
280bbd80c28SJacques Vidrine 	}
281c19800e8SDoug Rabson 
282c19800e8SDoug Rabson 	buf2 = map_alloc(OVERRUN, buf, sz, &buf2_map);
283c19800e8SDoug Rabson 
284c19800e8SDoug Rabson 	current_state = "decode";
285c19800e8SDoug Rabson 	ret = (*decode) (buf2, sz, data, &consumed_sz);
286bbd80c28SJacques Vidrine 	if (ret != 0) {
287c19800e8SDoug Rabson 	    printf ("decoding of %s failed %d\n", tests[i].name, ret);
288bbd80c28SJacques Vidrine 	    ++failures;
289c19800e8SDoug Rabson 	    continue;
290bbd80c28SJacques Vidrine 	}
291bbd80c28SJacques Vidrine 	if (sz != consumed_sz) {
292bbd80c28SJacques Vidrine 	    printf ("different length decoding %s (%ld != %ld)\n",
293bbd80c28SJacques Vidrine 		    tests[i].name,
294bbd80c28SJacques Vidrine 		    (unsigned long)sz, (unsigned long)consumed_sz);
295bbd80c28SJacques Vidrine 	    ++failures;
296c19800e8SDoug Rabson 	    continue;
297bbd80c28SJacques Vidrine 	}
298c19800e8SDoug Rabson 	current_state = "cmp";
299c19800e8SDoug Rabson 	if ((*cmp)(data, tests[i].val) != 0) {
300bbd80c28SJacques Vidrine 	    printf ("%s: comparison failed\n", tests[i].name);
301bbd80c28SJacques Vidrine 	    ++failures;
302c19800e8SDoug Rabson 	    continue;
303bbd80c28SJacques Vidrine 	}
304*ae771770SStanislav Sedov 
305*ae771770SStanislav Sedov 	current_state = "copy";
306*ae771770SStanislav Sedov 	if (copy) {
307*ae771770SStanislav Sedov 	    to = emalloc(data_size);
308*ae771770SStanislav Sedov 	    ret = (*copy)(data, to);
309*ae771770SStanislav Sedov 	    if (ret != 0) {
310*ae771770SStanislav Sedov 		printf ("copy of %s failed %d\n", tests[i].name, ret);
311*ae771770SStanislav Sedov 		++failures;
312*ae771770SStanislav Sedov 		continue;
313*ae771770SStanislav Sedov 	    }
314*ae771770SStanislav Sedov 
315*ae771770SStanislav Sedov 	    current_state = "cmp-copy";
316*ae771770SStanislav Sedov 	    if ((*cmp)(data, to) != 0) {
317*ae771770SStanislav Sedov 		printf ("%s: copy comparison failed\n", tests[i].name);
318*ae771770SStanislav Sedov 		++failures;
319*ae771770SStanislav Sedov 		continue;
320*ae771770SStanislav Sedov 	    }
321*ae771770SStanislav Sedov 	}
322*ae771770SStanislav Sedov 
323c19800e8SDoug Rabson 	current_state = "free";
324*ae771770SStanislav Sedov 	if (free_data) {
325c19800e8SDoug Rabson 	    (*free_data)(data);
326*ae771770SStanislav Sedov 	    if (to) {
327*ae771770SStanislav Sedov 		(*free_data)(to);
328*ae771770SStanislav Sedov 		free(to);
329*ae771770SStanislav Sedov 	    }
330*ae771770SStanislav Sedov 	}
331c19800e8SDoug Rabson 
332c19800e8SDoug Rabson 	current_state = "free";
333c19800e8SDoug Rabson 	map_free(buf_map, tests[i].name, "encode");
334c19800e8SDoug Rabson 	map_free(buf2_map, tests[i].name, "decode");
335c19800e8SDoug Rabson 	map_free(data_map, tests[i].name, "data");
336c19800e8SDoug Rabson 
337*ae771770SStanislav Sedov #ifdef HAVE_SIGACTION
338c19800e8SDoug Rabson 	sigaction (SIGSEGV, &osa, NULL);
339*ae771770SStanislav Sedov #endif
340bbd80c28SJacques Vidrine     }
341c19800e8SDoug Rabson     current_state = "done";
342c19800e8SDoug Rabson     return failures;
343c19800e8SDoug Rabson }
344c19800e8SDoug Rabson 
345c19800e8SDoug Rabson /*
346c19800e8SDoug Rabson  * check for failures
347c19800e8SDoug Rabson  *
348c19800e8SDoug Rabson  * a test size (byte_len) of -1 means that the test tries to trigger a
349c19800e8SDoug Rabson  * integer overflow (and later a malloc of to little memory), just
350c19800e8SDoug Rabson  * allocate some memory and hope that is enough for that test.
351c19800e8SDoug Rabson  */
352c19800e8SDoug Rabson 
353c19800e8SDoug Rabson int
generic_decode_fail(const struct test_case * tests,unsigned ntests,size_t data_size,int (ASN1CALL * decode)(unsigned char *,size_t,void *,size_t *))354c19800e8SDoug Rabson generic_decode_fail (const struct test_case *tests,
355c19800e8SDoug Rabson 		     unsigned ntests,
356c19800e8SDoug Rabson 		     size_t data_size,
357*ae771770SStanislav Sedov 		     int (ASN1CALL *decode)(unsigned char *, size_t, void *, size_t *))
358c19800e8SDoug Rabson {
359c19800e8SDoug Rabson     unsigned char *buf;
360c19800e8SDoug Rabson     int i;
361c19800e8SDoug Rabson     int failures = 0;
362c19800e8SDoug Rabson     void *data;
363c19800e8SDoug Rabson     struct map_page *data_map, *buf_map;
364c19800e8SDoug Rabson 
365*ae771770SStanislav Sedov #ifdef HAVE_SIGACTION
366c19800e8SDoug Rabson     struct sigaction sa, osa;
367*ae771770SStanislav Sedov #endif
368c19800e8SDoug Rabson 
369c19800e8SDoug Rabson     for (i = 0; i < ntests; ++i) {
370c19800e8SDoug Rabson 	int ret;
371c19800e8SDoug Rabson 	size_t sz;
372c19800e8SDoug Rabson 	const void *bytes;
373c19800e8SDoug Rabson 
374c19800e8SDoug Rabson 	current_test = tests[i].name;
375c19800e8SDoug Rabson 
376c19800e8SDoug Rabson 	current_state = "init";
377c19800e8SDoug Rabson 
378*ae771770SStanislav Sedov #ifdef HAVE_SIGACTION
379c19800e8SDoug Rabson 	sigemptyset (&sa.sa_mask);
380c19800e8SDoug Rabson 	sa.sa_flags = 0;
381c19800e8SDoug Rabson #ifdef SA_RESETHAND
382c19800e8SDoug Rabson 	sa.sa_flags |= SA_RESETHAND;
383c19800e8SDoug Rabson #endif
384c19800e8SDoug Rabson 	sa.sa_handler = segv_handler;
385c19800e8SDoug Rabson 	sigaction (SIGSEGV, &sa, &osa);
386*ae771770SStanislav Sedov #endif
387c19800e8SDoug Rabson 
388c19800e8SDoug Rabson 	data = map_alloc(OVERRUN, NULL, data_size, &data_map);
389c19800e8SDoug Rabson 
390c19800e8SDoug Rabson 	if (tests[i].byte_len < 0xffffff && tests[i].byte_len >= 0) {
391c19800e8SDoug Rabson 	    sz = tests[i].byte_len;
392c19800e8SDoug Rabson 	    bytes = tests[i].bytes;
393c19800e8SDoug Rabson 	} else {
394c19800e8SDoug Rabson 	    sz = 4096;
395c19800e8SDoug Rabson 	    bytes = NULL;
396c19800e8SDoug Rabson 	}
397c19800e8SDoug Rabson 
398c19800e8SDoug Rabson 	buf = map_alloc(OVERRUN, bytes, sz, &buf_map);
399c19800e8SDoug Rabson 
400c19800e8SDoug Rabson 	if (tests[i].byte_len == -1)
401c19800e8SDoug Rabson 	    memset(buf, 0, sz);
402c19800e8SDoug Rabson 
403c19800e8SDoug Rabson 	current_state = "decode";
404c19800e8SDoug Rabson 	ret = (*decode) (buf, tests[i].byte_len, data, &sz);
405c19800e8SDoug Rabson 	if (ret == 0) {
406c19800e8SDoug Rabson 	    printf ("sucessfully decoded %s\n", tests[i].name);
407c19800e8SDoug Rabson 	    ++failures;
408c19800e8SDoug Rabson 	    continue;
409c19800e8SDoug Rabson 	}
410c19800e8SDoug Rabson 
411c19800e8SDoug Rabson 	current_state = "free";
412c19800e8SDoug Rabson 	if (buf)
413c19800e8SDoug Rabson 	    map_free(buf_map, tests[i].name, "encode");
414c19800e8SDoug Rabson 	map_free(data_map, tests[i].name, "data");
415c19800e8SDoug Rabson 
416*ae771770SStanislav Sedov #ifdef HAVE_SIGACTION
417c19800e8SDoug Rabson 	sigaction (SIGSEGV, &osa, NULL);
418*ae771770SStanislav Sedov #endif
419c19800e8SDoug Rabson     }
420c19800e8SDoug Rabson     current_state = "done";
421bbd80c28SJacques Vidrine     return failures;
422bbd80c28SJacques Vidrine }
423