1 2/* pngmem.c - stub functions for memory allocation 3 * 4 * Last changed in libpng 1.6.8 [December 19, 2013] 5 * Copyright (c) 1998-2013 Glenn Randers-Pehrson 6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 8 * 9 * This code is released under the libpng license. 10 * For conditions of distribution and use, see the disclaimer 11 * and license in png.h 12 * 13 * This file provides a location for all memory allocation. Users who 14 * need special memory handling are expected to supply replacement 15 * functions for png_malloc() and png_free(), and to use 16 * png_create_read_struct_2() and png_create_write_struct_2() to 17 * identify the replacement functions. 18 */ 19 20#include "pngpriv.h" 21 22#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) 23/* Free a png_struct */ 24void /* PRIVATE */ 25png_destroy_png_struct(png_structrp png_ptr) 26{ 27 if (png_ptr != NULL) 28 { 29 /* png_free might call png_error and may certainly call 30 * png_get_mem_ptr, so fake a temporary png_struct to support this. 31 */ 32 png_struct dummy_struct = *png_ptr; 33 memset(png_ptr, 0, (sizeof *png_ptr)); 34 png_free(&dummy_struct, png_ptr); 35 36# ifdef PNG_SETJMP_SUPPORTED 37 /* We may have a jmp_buf left to deallocate. */ 38 png_free_jmpbuf(&dummy_struct); 39# endif 40 } 41} 42 43/* Allocate memory. For reasonable files, size should never exceed 44 * 64K. However, zlib may allocate more then 64K if you don't tell 45 * it not to. See zconf.h and png.h for more information. zlib does 46 * need to allocate exactly 64K, so whatever you call here must 47 * have the ability to do that. 48 */ 49PNG_FUNCTION(png_voidp,PNGAPI 50png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) 51{ 52 png_voidp ret; 53 54 ret = png_malloc(png_ptr, size); 55 56 if (ret != NULL) 57 memset(ret, 0, size); 58 59 return ret; 60} 61 62/* png_malloc_base, an internal function added at libpng 1.6.0, does the work of 63 * allocating memory, taking into account limits and PNG_USER_MEM_SUPPORTED. 64 * Checking and error handling must happen outside this routine; it returns NULL 65 * if the allocation cannot be done (for any reason.) 66 */ 67PNG_FUNCTION(png_voidp /* PRIVATE */, 68png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size), 69 PNG_ALLOCATED) 70{ 71 /* Moved to png_malloc_base from png_malloc_default in 1.6.0; the DOS 72 * allocators have also been removed in 1.6.0, so any 16-bit system now has 73 * to implement a user memory handler. This checks to be sure it isn't 74 * called with big numbers. 75 */ 76#ifndef PNG_USER_MEM_SUPPORTED 77 PNG_UNUSED(png_ptr) 78#endif 79 80 if (size > 0 && size <= PNG_SIZE_MAX 81# ifdef PNG_MAX_MALLOC_64K 82 && size <= 65536U 83# endif 84 ) 85 { 86#ifdef PNG_USER_MEM_SUPPORTED 87 if (png_ptr != NULL && png_ptr->malloc_fn != NULL) 88 return png_ptr->malloc_fn(png_constcast(png_structrp,png_ptr), size); 89 90 else 91#endif 92 return malloc((size_t)size); /* checked for truncation above */ 93 } 94 95 else 96 return NULL; 97} 98 99#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\ 100 defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) 101/* This is really here only to work round a spurious warning in GCC 4.6 and 4.7 102 * that arises because of the checks in png_realloc_array that are repeated in 103 * png_malloc_array. 104 */ 105static png_voidp 106png_malloc_array_checked(png_const_structrp png_ptr, int nelements, 107 size_t element_size) 108{ 109 png_alloc_size_t req = nelements; /* known to be > 0 */ 110 111 if (req <= PNG_SIZE_MAX/element_size) 112 return png_malloc_base(png_ptr, req * element_size); 113 114 /* The failure case when the request is too large */ 115 return NULL; 116} 117 118PNG_FUNCTION(png_voidp /* PRIVATE */, 119png_malloc_array,(png_const_structrp png_ptr, int nelements, 120 size_t element_size),PNG_ALLOCATED) 121{ 122 if (nelements <= 0 || element_size == 0) 123 png_error(png_ptr, "internal error: array alloc"); 124 125 return png_malloc_array_checked(png_ptr, nelements, element_size); 126} 127 128PNG_FUNCTION(png_voidp /* PRIVATE */, 129png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array, 130 int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED) 131{ 132 /* These are internal errors: */ 133 if (add_elements <= 0 || element_size == 0 || old_elements < 0 || 134 (old_array == NULL && old_elements > 0)) 135 png_error(png_ptr, "internal error: array realloc"); 136 137 /* Check for overflow on the elements count (so the caller does not have to 138 * check.) 139 */ 140 if (add_elements <= INT_MAX - old_elements) 141 { 142 png_voidp new_array = png_malloc_array_checked(png_ptr, 143 old_elements+add_elements, element_size); 144 145 if (new_array != NULL) 146 { 147 /* Because png_malloc_array worked the size calculations below cannot 148 * overflow. 149 */ 150 if (old_elements > 0) 151 memcpy(new_array, old_array, element_size*(unsigned)old_elements); 152 153 memset((char*)new_array + element_size*(unsigned)old_elements, 0, 154 element_size*(unsigned)add_elements); 155 156 return new_array; 157 } 158 } 159 160 return NULL; /* error */ 161} 162#endif /* TEXT || sPLT || STORE_UNKNOWN_CHUNKS */ 163 164/* Various functions that have different error handling are derived from this. 165 * png_malloc always exists, but if PNG_USER_MEM_SUPPORTED is defined a separate 166 * function png_malloc_default is also provided. 167 */ 168PNG_FUNCTION(png_voidp,PNGAPI 169png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) 170{ 171 png_voidp ret; 172 173 if (png_ptr == NULL) 174 return NULL; 175 176 ret = png_malloc_base(png_ptr, size); 177 178 if (ret == NULL) 179 png_error(png_ptr, "Out of memory"); /* 'm' means png_malloc */ 180 181 return ret; 182} 183 184#ifdef PNG_USER_MEM_SUPPORTED 185PNG_FUNCTION(png_voidp,PNGAPI 186png_malloc_default,(png_const_structrp png_ptr, png_alloc_size_t size), 187 PNG_ALLOCATED PNG_DEPRECATED) 188{ 189 png_voidp ret; 190 191 if (png_ptr == NULL) 192 return NULL; 193 194 /* Passing 'NULL' here bypasses the application provided memory handler. */ 195 ret = png_malloc_base(NULL/*use malloc*/, size); 196 197 if (ret == NULL) 198 png_error(png_ptr, "Out of Memory"); /* 'M' means png_malloc_default */ 199 200 return ret; 201} 202#endif /* PNG_USER_MEM_SUPPORTED */ 203 204/* This function was added at libpng version 1.2.3. The png_malloc_warn() 205 * function will issue a png_warning and return NULL instead of issuing a 206 * png_error, if it fails to allocate the requested memory. 207 */ 208PNG_FUNCTION(png_voidp,PNGAPI 209png_malloc_warn,(png_const_structrp png_ptr, png_alloc_size_t size), 210 PNG_ALLOCATED) 211{ 212 if (png_ptr != NULL) 213 { 214 png_voidp ret = png_malloc_base(png_ptr, size); 215 216 if (ret != NULL) 217 return ret; 218 219 png_warning(png_ptr, "Out of memory"); 220 } 221 222 return NULL; 223} 224 225/* Free a pointer allocated by png_malloc(). If ptr is NULL, return 226 * without taking any action. 227 */ 228void PNGAPI 229png_free(png_const_structrp png_ptr, png_voidp ptr) 230{ 231 if (png_ptr == NULL || ptr == NULL) 232 return; 233 234#ifdef PNG_USER_MEM_SUPPORTED 235 if (png_ptr->free_fn != NULL) 236 png_ptr->free_fn(png_constcast(png_structrp,png_ptr), ptr); 237 238 else 239 png_free_default(png_ptr, ptr); 240} 241 242PNG_FUNCTION(void,PNGAPI 243png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED) 244{ 245 if (png_ptr == NULL || ptr == NULL) 246 return; 247#endif /* PNG_USER_MEM_SUPPORTED */ 248 249 free(ptr); 250} 251 252#ifdef PNG_USER_MEM_SUPPORTED 253/* This function is called when the application wants to use another method 254 * of allocating and freeing memory. 255 */ 256void PNGAPI 257png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr, png_malloc_ptr 258 malloc_fn, png_free_ptr free_fn) 259{ 260 if (png_ptr != NULL) 261 { 262 png_ptr->mem_ptr = mem_ptr; 263 png_ptr->malloc_fn = malloc_fn; 264 png_ptr->free_fn = free_fn; 265 } 266} 267 268/* This function returns a pointer to the mem_ptr associated with the user 269 * functions. The application should free any memory associated with this 270 * pointer before png_write_destroy and png_read_destroy are called. 271 */ 272png_voidp PNGAPI 273png_get_mem_ptr(png_const_structrp png_ptr) 274{ 275 if (png_ptr == NULL) 276 return NULL; 277 278 return png_ptr->mem_ptr; 279} 280#endif /* PNG_USER_MEM_SUPPORTED */ 281#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ 282