Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/openjpeg/src/lib/openjp2/opj_malloc.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 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 { | |
| 45 void* ptr; | |
| 46 | |
| 47 /* alignment shall be power of 2 */ | |
| 48 assert((alignment != 0U) && ((alignment & (alignment - 1U)) == 0U)); | |
| 49 /* alignment shall be at least sizeof(void*) */ | |
| 50 assert(alignment >= sizeof(void*)); | |
| 51 | |
| 52 if (size == 0U) { /* prevent implementation defined behavior of realloc */ | |
| 53 return NULL; | |
| 54 } | |
| 55 | |
| 56 #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 if (posix_memalign(&ptr, alignment, size)) { | |
| 62 ptr = NULL; | |
| 63 } | |
| 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 return ptr; | |
| 106 } | |
| 107 static INLINE void *opj_aligned_realloc_n(void *ptr, size_t alignment, | |
| 108 size_t new_size) | |
| 109 { | |
| 110 void *r_ptr; | |
| 111 | |
| 112 /* alignment shall be power of 2 */ | |
| 113 assert((alignment != 0U) && ((alignment & (alignment - 1U)) == 0U)); | |
| 114 /* alignment shall be at least sizeof(void*) */ | |
| 115 assert(alignment >= sizeof(void*)); | |
| 116 | |
| 117 if (new_size == 0U) { /* prevent implementation defined behavior of realloc */ | |
| 118 return NULL; | |
| 119 } | |
| 120 | |
| 121 /* no portable aligned realloc */ | |
| 122 #if defined(OPJ_HAVE_POSIX_MEMALIGN) || defined(OPJ_HAVE_MEMALIGN) | |
| 123 /* glibc doc states one can mix aligned malloc with realloc */ | |
| 124 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 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 void *a_ptr = opj_aligned_alloc_n(alignment, new_size); | |
| 133 if (a_ptr != NULL) { | |
| 134 memcpy(a_ptr, r_ptr, new_size); | |
| 135 } | |
| 136 free(r_ptr); | |
| 137 r_ptr = a_ptr; | |
| 138 } | |
| 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 return r_ptr; | |
| 190 } | |
| 191 void * opj_malloc(size_t size) | |
| 192 { | |
| 193 if (size == 0U) { /* prevent implementation defined behavior of realloc */ | |
| 194 return NULL; | |
| 195 } | |
| 196 return malloc(size); | |
| 197 } | |
| 198 void * opj_calloc(size_t num, size_t size) | |
| 199 { | |
| 200 if (num == 0 || size == 0) { | |
| 201 /* prevent implementation defined behavior of realloc */ | |
| 202 return NULL; | |
| 203 } | |
| 204 return calloc(num, size); | |
| 205 } | |
| 206 | |
| 207 void *opj_aligned_malloc(size_t size) | |
| 208 { | |
| 209 return opj_aligned_alloc_n(16U, size); | |
| 210 } | |
| 211 void * opj_aligned_realloc(void *ptr, size_t size) | |
| 212 { | |
| 213 return opj_aligned_realloc_n(ptr, 16U, size); | |
| 214 } | |
| 215 | |
| 216 void *opj_aligned_32_malloc(size_t size) | |
| 217 { | |
| 218 return opj_aligned_alloc_n(32U, size); | |
| 219 } | |
| 220 void * opj_aligned_32_realloc(void *ptr, size_t size) | |
| 221 { | |
| 222 return opj_aligned_realloc_n(ptr, 32U, size); | |
| 223 } | |
| 224 | |
| 225 void opj_aligned_free(void* ptr) | |
| 226 { | |
| 227 #if defined(OPJ_HAVE_POSIX_MEMALIGN) || defined(OPJ_HAVE_MEMALIGN) | |
| 228 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 } | |
| 238 | |
| 239 void * opj_realloc(void *ptr, size_t new_size) | |
| 240 { | |
| 241 if (new_size == 0U) { /* prevent implementation defined behavior of realloc */ | |
| 242 return NULL; | |
| 243 } | |
| 244 return realloc(ptr, new_size); | |
| 245 } | |
| 246 void opj_free(void *ptr) | |
| 247 { | |
| 248 free(ptr); | |
| 249 } |
