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