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