Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * memory.c: safer memory allocation |
3 | | * |
4 | | * Copyright (C) 2008-2016 Daniel P. Berrange |
5 | | * |
6 | | * This library is free software; you can redistribute it and/or |
7 | | * modify it under the terms of the GNU Lesser General Public |
8 | | * License as published by the Free Software Foundation; either |
9 | | * version 2.1 of the License, or (at your option) any later version. |
10 | | * |
11 | | * This library is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | | * Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public |
17 | | * License along with this library; if not, write to the Free Software |
18 | | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | | * |
20 | | */ |
21 | | |
22 | | #include <config.h> |
23 | | |
24 | | #include <stdlib.h> |
25 | | #include <stddef.h> |
26 | | |
27 | | #include "memory.h" |
28 | | |
29 | | |
30 | | /* Return 1 if an array of N objects, each of size S, cannot exist due |
31 | | to size arithmetic overflow. S must be positive and N must be |
32 | | nonnegative. This is a macro, not an inline function, so that it |
33 | | works correctly even when SIZE_MAX < N. |
34 | | |
35 | | By gnulib convention, SIZE_MAX represents overflow in size |
36 | | calculations, so the conservative dividend to use here is |
37 | | SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value. |
38 | | However, malloc (SIZE_MAX) fails on all known hosts where |
39 | | sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for |
40 | | exactly-SIZE_MAX allocations on such hosts; this avoids a test and |
41 | | branch when S is known to be 1. */ |
42 | | # define xalloc_oversized(n, s) \ |
43 | | ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) |
44 | | |
45 | | |
46 | | /** |
47 | | * mem_alloc_n: |
48 | | * @ptrptr: pointer to pointer for address of allocated memory |
49 | | * @size: number of bytes to allocate |
50 | | * @count: number of elements to allocate |
51 | | * |
52 | | * Allocate an array of memory 'count' elements long, |
53 | | * each with 'size' bytes. Return the address of the |
54 | | * allocated memory in 'ptrptr'. The newly allocated |
55 | | * memory is filled with zeros. |
56 | | * |
57 | | * Returns -1 on failure to allocate, zero on success |
58 | | */ |
59 | | int mem_alloc_n(void *ptrptr, size_t size, size_t count) |
60 | 11.2M | { |
61 | 11.2M | if (AUGEAS_UNLIKELY(size == 0 || count == 0)) { |
62 | 18 | *(void **)ptrptr = NULL; |
63 | 18 | return 0; |
64 | 18 | } |
65 | | |
66 | 11.2M | *(void**)ptrptr = calloc(count, size); |
67 | 11.2M | if (AUGEAS_UNLIKELY(*(void**)ptrptr == NULL)) |
68 | 0 | return -1; |
69 | 11.2M | return 0; |
70 | 11.2M | } |
71 | | |
72 | | /** |
73 | | * virReallocN: |
74 | | * @ptrptr: pointer to pointer for address of allocated memory |
75 | | * @size: number of bytes to allocate |
76 | | * @count: number of elements in array |
77 | | * |
78 | | * Resize the block of memory in 'ptrptr' to be an array of |
79 | | * 'count' elements, each 'size' bytes in length. Update 'ptrptr' |
80 | | * with the address of the newly allocated memory. On failure, |
81 | | * 'ptrptr' is not changed and still points to the original memory |
82 | | * block. The newly allocated memory is filled with zeros. |
83 | | * |
84 | | * Returns -1 on failure to allocate, zero on success |
85 | | */ |
86 | | int mem_realloc_n(void *ptrptr, size_t size, size_t count) |
87 | 527k | { |
88 | 527k | void *tmp; |
89 | 527k | if (AUGEAS_UNLIKELY(size == 0 || count == 0)) { |
90 | 0 | free(*(void **)ptrptr); |
91 | 0 | *(void **)ptrptr = NULL; |
92 | 0 | return 0; |
93 | 0 | } |
94 | 527k | if (AUGEAS_UNLIKELY(xalloc_oversized(count, size))) { |
95 | 0 | errno = ENOMEM; |
96 | 0 | return -1; |
97 | 0 | } |
98 | 527k | tmp = realloc(*(void**)ptrptr, size * count); |
99 | 527k | if (AUGEAS_UNLIKELY(!tmp)) |
100 | 0 | return -1; |
101 | 527k | *(void**)ptrptr = tmp; |
102 | 527k | return 0; |
103 | 527k | } |