/src/opencv/3rdparty/openjpeg/openjp2/opj_malloc.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * The copyright in this software is being made available under the 2-clauses |
3 | | * BSD License, included below. This software may be subject to other third |
4 | | * party and contributor rights, including patent rights, and no such rights |
5 | | * are granted under this license. |
6 | | * |
7 | | * Copyright (c) 2015, Mathieu Malaterre <mathieu.malaterre@gmail.com> |
8 | | * Copyright (c) 2015, Matthieu Darbois |
9 | | * All rights reserved. |
10 | | * |
11 | | * Redistribution and use in source and binary forms, with or without |
12 | | * modification, are permitted provided that the following conditions |
13 | | * are met: |
14 | | * 1. Redistributions of source code must retain the above copyright |
15 | | * notice, this list of conditions and the following disclaimer. |
16 | | * 2. Redistributions in binary form must reproduce the above copyright |
17 | | * notice, this list of conditions and the following disclaimer in the |
18 | | * documentation and/or other materials provided with the distribution. |
19 | | * |
20 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' |
21 | | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
22 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
23 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
24 | | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
25 | | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
26 | | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
27 | | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
29 | | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
30 | | * POSSIBILITY OF SUCH DAMAGE. |
31 | | */ |
32 | | #define OPJ_SKIP_POISON |
33 | | #include "opj_includes.h" |
34 | | |
35 | | #if defined(OPJ_HAVE_MALLOC_H) && defined(OPJ_HAVE_MEMALIGN) |
36 | | # include <malloc.h> |
37 | | #endif |
38 | | |
39 | | #ifndef SIZE_MAX |
40 | | # define SIZE_MAX ((size_t) -1) |
41 | | #endif |
42 | | |
43 | | static INLINE void *opj_aligned_alloc_n(size_t alignment, size_t size) |
44 | 180k | { |
45 | 180k | void* ptr; |
46 | | |
47 | | /* alignment shall be power of 2 */ |
48 | 180k | assert((alignment != 0U) && ((alignment & (alignment - 1U)) == 0U)); |
49 | | /* alignment shall be at least sizeof(void*) */ |
50 | 180k | assert(alignment >= sizeof(void*)); |
51 | | |
52 | 180k | if (size == 0U) { /* prevent implementation defined behavior of realloc */ |
53 | 93 | return NULL; |
54 | 93 | } |
55 | | |
56 | 180k | #if defined(OPJ_HAVE_POSIX_MEMALIGN) |
57 | | /* aligned_alloc requires c11, restrict to posix_memalign for now. Quote: |
58 | | * This function was introduced in POSIX 1003.1d. Although this function is |
59 | | * superseded by aligned_alloc, it is more portable to older POSIX systems |
60 | | * that do not support ISO C11. */ |
61 | 180k | if (posix_memalign(&ptr, alignment, size)) { |
62 | 0 | ptr = NULL; |
63 | 0 | } |
64 | | /* older linux */ |
65 | | #elif defined(OPJ_HAVE_MEMALIGN) |
66 | | ptr = memalign(alignment, size); |
67 | | /* _MSC_VER */ |
68 | | #elif defined(OPJ_HAVE__ALIGNED_MALLOC) |
69 | | ptr = _aligned_malloc(size, alignment); |
70 | | #else |
71 | | /* |
72 | | * Generic aligned malloc implementation. |
73 | | * Uses size_t offset for the integer manipulation of the pointer, |
74 | | * as uintptr_t is not available in C89 to do |
75 | | * bitwise operations on the pointer itself. |
76 | | */ |
77 | | alignment--; |
78 | | { |
79 | | size_t offset; |
80 | | OPJ_UINT8 *mem; |
81 | | |
82 | | /* Room for padding and extra pointer stored in front of allocated area */ |
83 | | size_t overhead = alignment + sizeof(void *); |
84 | | |
85 | | /* let's be extra careful */ |
86 | | assert(alignment <= (SIZE_MAX - sizeof(void *))); |
87 | | |
88 | | /* Avoid integer overflow */ |
89 | | if (size > (SIZE_MAX - overhead)) { |
90 | | return NULL; |
91 | | } |
92 | | |
93 | | mem = (OPJ_UINT8*)malloc(size + overhead); |
94 | | if (mem == NULL) { |
95 | | return mem; |
96 | | } |
97 | | /* offset = ((alignment + 1U) - ((size_t)(mem + sizeof(void*)) & alignment)) & alignment; */ |
98 | | /* Use the fact that alignment + 1U is a power of 2 */ |
99 | | offset = ((alignment ^ ((size_t)(mem + sizeof(void*)) & alignment)) + 1U) & |
100 | | alignment; |
101 | | ptr = (void *)(mem + sizeof(void*) + offset); |
102 | | ((void**) ptr)[-1] = mem; |
103 | | } |
104 | | #endif |
105 | 180k | return ptr; |
106 | 180k | } |
107 | | static INLINE void *opj_aligned_realloc_n(void *ptr, size_t alignment, |
108 | | size_t new_size) |
109 | 0 | { |
110 | 0 | void *r_ptr; |
111 | | |
112 | | /* alignment shall be power of 2 */ |
113 | 0 | assert((alignment != 0U) && ((alignment & (alignment - 1U)) == 0U)); |
114 | | /* alignment shall be at least sizeof(void*) */ |
115 | 0 | assert(alignment >= sizeof(void*)); |
116 | |
|
117 | 0 | if (new_size == 0U) { /* prevent implementation defined behavior of realloc */ |
118 | 0 | return NULL; |
119 | 0 | } |
120 | | |
121 | | /* no portable aligned realloc */ |
122 | 0 | #if defined(OPJ_HAVE_POSIX_MEMALIGN) || defined(OPJ_HAVE_MEMALIGN) |
123 | | /* glibc doc states one can mix aligned malloc with realloc */ |
124 | 0 | r_ptr = realloc(ptr, new_size); /* fast path */ |
125 | | /* we simply use `size_t` to cast, since we are only interest in binary AND |
126 | | * operator */ |
127 | 0 | if (((size_t)r_ptr & (alignment - 1U)) != 0U) { |
128 | | /* this is non-trivial to implement a portable aligned realloc, so use a |
129 | | * simple approach where we do not need a function that return the size of an |
130 | | * allocated array (eg. _msize on Windows, malloc_size on MacOS, |
131 | | * malloc_usable_size on systems with glibc) */ |
132 | 0 | void *a_ptr = opj_aligned_alloc_n(alignment, new_size); |
133 | 0 | if (a_ptr != NULL) { |
134 | 0 | memcpy(a_ptr, r_ptr, new_size); |
135 | 0 | } |
136 | 0 | free(r_ptr); |
137 | 0 | r_ptr = a_ptr; |
138 | 0 | } |
139 | | /* _MSC_VER */ |
140 | | #elif defined(OPJ_HAVE__ALIGNED_MALLOC) |
141 | | r_ptr = _aligned_realloc(ptr, new_size, alignment); |
142 | | #else |
143 | | if (ptr == NULL) { |
144 | | return opj_aligned_alloc_n(alignment, new_size); |
145 | | } |
146 | | alignment--; |
147 | | { |
148 | | void *oldmem; |
149 | | OPJ_UINT8 *newmem; |
150 | | size_t overhead = alignment + sizeof(void *); |
151 | | |
152 | | /* let's be extra careful */ |
153 | | assert(alignment <= (SIZE_MAX - sizeof(void *))); |
154 | | |
155 | | /* Avoid integer overflow */ |
156 | | if (new_size > SIZE_MAX - overhead) { |
157 | | return NULL; |
158 | | } |
159 | | |
160 | | oldmem = ((void**) ptr)[-1]; |
161 | | newmem = (OPJ_UINT8*)realloc(oldmem, new_size + overhead); |
162 | | if (newmem == NULL) { |
163 | | return newmem; |
164 | | } |
165 | | |
166 | | if (newmem == oldmem) { |
167 | | r_ptr = ptr; |
168 | | } else { |
169 | | size_t old_offset; |
170 | | size_t new_offset; |
171 | | |
172 | | /* realloc created a new copy, realign the copied memory block */ |
173 | | old_offset = (size_t)((OPJ_UINT8*)ptr - (OPJ_UINT8*)oldmem); |
174 | | |
175 | | /* offset = ((alignment + 1U) - ((size_t)(mem + sizeof(void*)) & alignment)) & alignment; */ |
176 | | /* Use the fact that alignment + 1U is a power of 2 */ |
177 | | new_offset = ((alignment ^ ((size_t)(newmem + sizeof(void*)) & alignment)) + |
178 | | 1U) & alignment; |
179 | | new_offset += sizeof(void*); |
180 | | r_ptr = (void *)(newmem + new_offset); |
181 | | |
182 | | if (new_offset != old_offset) { |
183 | | memmove(newmem + new_offset, newmem + old_offset, new_size); |
184 | | } |
185 | | ((void**) r_ptr)[-1] = newmem; |
186 | | } |
187 | | } |
188 | | #endif |
189 | 0 | return r_ptr; |
190 | 0 | } |
191 | | void * opj_malloc(size_t size) |
192 | 20.7M | { |
193 | 20.7M | if (size == 0U) { /* prevent implementation defined behavior of realloc */ |
194 | 0 | return NULL; |
195 | 0 | } |
196 | 20.7M | return malloc(size); |
197 | 20.7M | } |
198 | | void * opj_calloc(size_t num, size_t size) |
199 | 12.0M | { |
200 | 12.0M | if (num == 0 || size == 0) { |
201 | | /* prevent implementation defined behavior of realloc */ |
202 | 1 | return NULL; |
203 | 1 | } |
204 | 12.0M | return calloc(num, size); |
205 | 12.0M | } |
206 | | |
207 | | void *opj_aligned_malloc(size_t size) |
208 | 180k | { |
209 | 180k | return opj_aligned_alloc_n(16U, size); |
210 | 180k | } |
211 | | void * opj_aligned_realloc(void *ptr, size_t size) |
212 | 0 | { |
213 | 0 | return opj_aligned_realloc_n(ptr, 16U, size); |
214 | 0 | } |
215 | | |
216 | | void *opj_aligned_32_malloc(size_t size) |
217 | 191 | { |
218 | 191 | return opj_aligned_alloc_n(32U, size); |
219 | 191 | } |
220 | | void * opj_aligned_32_realloc(void *ptr, size_t size) |
221 | 0 | { |
222 | 0 | return opj_aligned_realloc_n(ptr, 32U, size); |
223 | 0 | } |
224 | | |
225 | | void opj_aligned_free(void* ptr) |
226 | 2.66M | { |
227 | 2.66M | #if defined(OPJ_HAVE_POSIX_MEMALIGN) || defined(OPJ_HAVE_MEMALIGN) |
228 | 2.66M | free(ptr); |
229 | | #elif defined(OPJ_HAVE__ALIGNED_MALLOC) |
230 | | _aligned_free(ptr); |
231 | | #else |
232 | | /* Generic implementation has malloced pointer stored in front of used area */ |
233 | | if (ptr != NULL) { |
234 | | free(((void**) ptr)[-1]); |
235 | | } |
236 | | #endif |
237 | 2.66M | } |
238 | | |
239 | | void * opj_realloc(void *ptr, size_t new_size) |
240 | 645k | { |
241 | 645k | if (new_size == 0U) { /* prevent implementation defined behavior of realloc */ |
242 | 0 | return NULL; |
243 | 0 | } |
244 | 645k | return realloc(ptr, new_size); |
245 | 645k | } |
246 | | void opj_free(void *ptr) |
247 | 33.2M | { |
248 | 33.2M | free(ptr); |
249 | 33.2M | } |