Coverage Report

Created: 2025-03-01 02:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/libfido2/openbsd-compat/recallocarray.c
Line
Count
Source
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
3.84M
#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
830k
{
41
830k
        size_t oldsize, newsize;
42
830k
        void *newptr;
43
44
830k
        if (ptr == NULL)
45
188k
                return calloc(newnmemb, size);
46
47
641k
        if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
48
641k
            newnmemb > 0 && SIZE_MAX / newnmemb < size) {
49
0
                errno = ENOMEM;
50
0
                return NULL;
51
0
        }
52
641k
        newsize = newnmemb * size;
53
54
641k
        if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
55
641k
            oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
56
0
                errno = EINVAL;
57
0
                return NULL;
58
0
        }
59
641k
        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
641k
        if (newsize <= oldsize) {
66
3
                size_t d = oldsize - newsize;
67
68
3
                if (d < oldsize / 2 && d < (size_t)getpagesize()) {
69
3
                        memset((char *)ptr + newsize, 0, d);
70
3
                        return ptr;
71
3
                }
72
3
        }
73
74
641k
        newptr = malloc(newsize);
75
641k
        if (newptr == NULL)
76
1.68k
                return NULL;
77
78
639k
        if (newsize > oldsize) {
79
639k
                memcpy(newptr, ptr, oldsize);
80
639k
                memset((char *)newptr + oldsize, 0, newsize - oldsize);
81
639k
        } else
82
0
                memcpy(newptr, ptr, newsize);
83
84
639k
        explicit_bzero(ptr, oldsize);
85
639k
        free(ptr);
86
87
639k
        return newptr;
88
641k
}
89
/* DEF_WEAK(recallocarray); */
90
91
#endif /* !defined(HAVE_RECALLOCARRAY) */