/libfido2/openbsd-compat/recallocarray.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /*      $OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $  */ | 
| 2 |  | /* | 
| 3 |  |  * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net> | 
| 4 |  |  * | 
| 5 |  |  * Permission to use, copy, modify, and distribute this software for any | 
| 6 |  |  * purpose with or without fee is hereby granted, provided that the above | 
| 7 |  |  * copyright notice and this permission notice appear in all copies. | 
| 8 |  |  * | 
| 9 |  |  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 
| 10 |  |  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 
| 11 |  |  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | 
| 12 |  |  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 
| 13 |  |  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 
| 14 |  |  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 
| 15 |  |  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 
| 16 |  |  */ | 
| 17 |  |  | 
| 18 |  | /* OPENBSD ORIGINAL: lib/libc/stdlib/recallocarray.c */ | 
| 19 |  |  | 
| 20 |  | #include "openbsd-compat.h" | 
| 21 |  |  | 
| 22 |  | #if !defined(HAVE_RECALLOCARRAY) | 
| 23 |  |  | 
| 24 |  | #include <errno.h> | 
| 25 |  | #include <stdlib.h> | 
| 26 |  | #include <stdint.h> | 
| 27 |  | #include <string.h> | 
| 28 |  | #ifdef HAVE_UNISTD_H | 
| 29 |  | #include <unistd.h> | 
| 30 |  | #endif | 
| 31 |  |  | 
| 32 |  | /* | 
| 33 |  |  * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX | 
| 34 |  |  * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW | 
| 35 |  |  */ | 
| 36 | 1.33M | #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) | 
| 37 |  |  | 
| 38 |  | void * | 
| 39 |  | recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size) | 
| 40 | 289k | { | 
| 41 | 289k |         size_t oldsize, newsize; | 
| 42 | 289k |         void *newptr; | 
| 43 |  |  | 
| 44 | 289k |         if (ptr == NULL) | 
| 45 | 67.3k |                 return calloc(newnmemb, size); | 
| 46 |  |  | 
| 47 | 221k |         if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && | 
| 48 | 221k |             newnmemb > 0 && SIZE_MAX / newnmemb < size) { | 
| 49 | 0 |                 errno = ENOMEM; | 
| 50 | 0 |                 return NULL; | 
| 51 | 0 |         } | 
| 52 | 221k |         newsize = newnmemb * size; | 
| 53 |  |  | 
| 54 | 221k |         if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && | 
| 55 | 221k |             oldnmemb > 0 && SIZE_MAX / oldnmemb < size) { | 
| 56 | 0 |                 errno = EINVAL; | 
| 57 | 0 |                 return NULL; | 
| 58 | 0 |         } | 
| 59 | 221k |         oldsize = oldnmemb * size; | 
| 60 |  |          | 
| 61 |  |         /* | 
| 62 |  |          * Don't bother too much if we're shrinking just a bit, | 
| 63 |  |          * we do not shrink for series of small steps, oh well. | 
| 64 |  |          */ | 
| 65 | 221k |         if (newsize <= oldsize) { | 
| 66 | 1 |                 size_t d = oldsize - newsize; | 
| 67 |  |  | 
| 68 | 1 |                 if (d < oldsize / 2 && d < (size_t)getpagesize()) { | 
| 69 | 1 |                         memset((char *)ptr + newsize, 0, d); | 
| 70 | 1 |                         return ptr; | 
| 71 | 1 |                 } | 
| 72 | 1 |         } | 
| 73 |  |  | 
| 74 | 221k |         newptr = malloc(newsize); | 
| 75 | 221k |         if (newptr == NULL) | 
| 76 | 625 |                 return NULL; | 
| 77 |  |  | 
| 78 | 221k |         if (newsize > oldsize) { | 
| 79 | 221k |                 memcpy(newptr, ptr, oldsize); | 
| 80 | 221k |                 memset((char *)newptr + oldsize, 0, newsize - oldsize); | 
| 81 | 221k |         } else | 
| 82 | 0 |                 memcpy(newptr, ptr, newsize); | 
| 83 |  |  | 
| 84 | 221k |         explicit_bzero(ptr, oldsize); | 
| 85 | 221k |         free(ptr); | 
| 86 |  |  | 
| 87 | 221k |         return newptr; | 
| 88 | 221k | } | 
| 89 |  | /* DEF_WEAK(recallocarray); */ | 
| 90 |  |  | 
| 91 |  | #endif /* !defined(HAVE_RECALLOCARRAY) */ |