merged libpng-1.2.7 to HEAD (1.2.6 contained serious bug that caused it to produce...
[wxWidgets.git] / src / png / pngmem.c
1
2 /* pngmem.c - stub functions for memory allocation
3 *
4 * libpng version 1.2.7 - September 12, 2004
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1998-2004 Glenn Randers-Pehrson
7 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9 *
10 * This file provides a location for all memory allocation. Users who
11 * need special memory handling are expected to supply replacement
12 * functions for png_malloc() and png_free(), and to use
13 * png_create_read_struct_2() and png_create_write_struct_2() to
14 * identify the replacement functions.
15 */
16
17 #define PNG_INTERNAL
18 #include "png.h"
19
20 /* Borland DOS special memory handler */
21 #if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
22 /* if you change this, be sure to change the one in png.h also */
23
24 /* Allocate memory for a png_struct. The malloc and memset can be replaced
25 by a single call to calloc() if this is thought to improve performance. */
26 png_voidp /* PRIVATE */
27 png_create_struct(int type)
28 {
29 #ifdef PNG_USER_MEM_SUPPORTED
30 return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL));
31 }
32
33 /* Alternate version of png_create_struct, for use with user-defined malloc. */
34 png_voidp /* PRIVATE */
35 png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
36 {
37 #endif /* PNG_USER_MEM_SUPPORTED */
38 png_size_t size;
39 png_voidp struct_ptr;
40
41 if (type == PNG_STRUCT_INFO)
42 size = png_sizeof(png_info);
43 else if (type == PNG_STRUCT_PNG)
44 size = png_sizeof(png_struct);
45 else
46 return (png_get_copyright(NULL));
47
48 #ifdef PNG_USER_MEM_SUPPORTED
49 if(malloc_fn != NULL)
50 {
51 png_struct dummy_struct;
52 png_structp png_ptr = &dummy_struct;
53 png_ptr->mem_ptr=mem_ptr;
54 struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size);
55 }
56 else
57 #endif /* PNG_USER_MEM_SUPPORTED */
58 struct_ptr = (png_voidp)farmalloc(size);
59 if (struct_ptr != NULL)
60 png_memset(struct_ptr, 0, size);
61 return (struct_ptr);
62 }
63
64 /* Free memory allocated by a png_create_struct() call */
65 void /* PRIVATE */
66 png_destroy_struct(png_voidp struct_ptr)
67 {
68 #ifdef PNG_USER_MEM_SUPPORTED
69 png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL);
70 }
71
72 /* Free memory allocated by a png_create_struct() call */
73 void /* PRIVATE */
74 png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
75 png_voidp mem_ptr)
76 {
77 #endif
78 if (struct_ptr != NULL)
79 {
80 #ifdef PNG_USER_MEM_SUPPORTED
81 if(free_fn != NULL)
82 {
83 png_struct dummy_struct;
84 png_structp png_ptr = &dummy_struct;
85 png_ptr->mem_ptr=mem_ptr;
86 (*(free_fn))(png_ptr, struct_ptr);
87 return;
88 }
89 #endif /* PNG_USER_MEM_SUPPORTED */
90 farfree (struct_ptr);
91 }
92 }
93
94 /* Allocate memory. For reasonable files, size should never exceed
95 * 64K. However, zlib may allocate more then 64K if you don't tell
96 * it not to. See zconf.h and png.h for more information. zlib does
97 * need to allocate exactly 64K, so whatever you call here must
98 * have the ability to do that.
99 *
100 * Borland seems to have a problem in DOS mode for exactly 64K.
101 * It gives you a segment with an offset of 8 (perhaps to store its
102 * memory stuff). zlib doesn't like this at all, so we have to
103 * detect and deal with it. This code should not be needed in
104 * Windows or OS/2 modes, and only in 16 bit mode. This code has
105 * been updated by Alexander Lehmann for version 0.89 to waste less
106 * memory.
107 *
108 * Note that we can't use png_size_t for the "size" declaration,
109 * since on some systems a png_size_t is a 16-bit quantity, and as a
110 * result, we would be truncating potentially larger memory requests
111 * (which should cause a fatal error) and introducing major problems.
112 */
113
114 png_voidp PNGAPI
115 png_malloc(png_structp png_ptr, png_uint_32 size)
116 {
117 png_voidp ret;
118
119 if (png_ptr == NULL || size == 0)
120 return (NULL);
121
122 #ifdef PNG_USER_MEM_SUPPORTED
123 if(png_ptr->malloc_fn != NULL)
124 ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
125 else
126 ret = (png_malloc_default(png_ptr, size));
127 if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
128 png_error(png_ptr, "Out of memory!");
129 return (ret);
130 }
131
132 png_voidp PNGAPI
133 png_malloc_default(png_structp png_ptr, png_uint_32 size)
134 {
135 png_voidp ret;
136 #endif /* PNG_USER_MEM_SUPPORTED */
137
138 #ifdef PNG_MAX_MALLOC_64K
139 if (size > (png_uint_32)65536L)
140 {
141 png_warning(png_ptr, "Cannot Allocate > 64K");
142 ret = NULL;
143 }
144 else
145 #endif
146
147 if (size != (size_t)size)
148 ret = NULL;
149 else if (size == (png_uint_32)65536L)
150 {
151 if (png_ptr->offset_table == NULL)
152 {
153 /* try to see if we need to do any of this fancy stuff */
154 ret = farmalloc(size);
155 if (ret == NULL || ((png_size_t)ret & 0xffff))
156 {
157 int num_blocks;
158 png_uint_32 total_size;
159 png_bytep table;
160 int i;
161 png_byte huge * hptr;
162
163 if (ret != NULL)
164 {
165 farfree(ret);
166 ret = NULL;
167 }
168
169 if(png_ptr->zlib_window_bits > 14)
170 num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14));
171 else
172 num_blocks = 1;
173 if (png_ptr->zlib_mem_level >= 7)
174 num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7));
175 else
176 num_blocks++;
177
178 total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16;
179
180 table = farmalloc(total_size);
181
182 if (table == NULL)
183 {
184 #ifndef PNG_USER_MEM_SUPPORTED
185 if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
186 png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */
187 else
188 png_warning(png_ptr, "Out Of Memory.");
189 #endif
190 return (NULL);
191 }
192
193 if ((png_size_t)table & 0xfff0)
194 {
195 #ifndef PNG_USER_MEM_SUPPORTED
196 if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
197 png_error(png_ptr,
198 "Farmalloc didn't return normalized pointer");
199 else
200 png_warning(png_ptr,
201 "Farmalloc didn't return normalized pointer");
202 #endif
203 return (NULL);
204 }
205
206 png_ptr->offset_table = table;
207 png_ptr->offset_table_ptr = farmalloc(num_blocks *
208 png_sizeof (png_bytep));
209
210 if (png_ptr->offset_table_ptr == NULL)
211 {
212 #ifndef PNG_USER_MEM_SUPPORTED
213 if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
214 png_error(png_ptr, "Out Of memory."); /* Note "O" and "M" */
215 else
216 png_warning(png_ptr, "Out Of memory.");
217 #endif
218 return (NULL);
219 }
220
221 hptr = (png_byte huge *)table;
222 if ((png_size_t)hptr & 0xf)
223 {
224 hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
225 hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */
226 }
227 for (i = 0; i < num_blocks; i++)
228 {
229 png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
230 hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */
231 }
232
233 png_ptr->offset_table_number = num_blocks;
234 png_ptr->offset_table_count = 0;
235 png_ptr->offset_table_count_free = 0;
236 }
237 }
238
239 if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
240 {
241 #ifndef PNG_USER_MEM_SUPPORTED
242 if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
243 png_error(png_ptr, "Out of Memory."); /* Note "o" and "M" */
244 else
245 png_warning(png_ptr, "Out of Memory.");
246 #endif
247 return (NULL);
248 }
249
250 ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
251 }
252 else
253 ret = farmalloc(size);
254
255 #ifndef PNG_USER_MEM_SUPPORTED
256 if (ret == NULL)
257 {
258 if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
259 png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */
260 else
261 png_warning(png_ptr, "Out of memory."); /* Note "o" and "m" */
262 }
263 #endif
264
265 return (ret);
266 }
267
268 /* free a pointer allocated by png_malloc(). In the default
269 configuration, png_ptr is not used, but is passed in case it
270 is needed. If ptr is NULL, return without taking any action. */
271 void PNGAPI
272 png_free(png_structp png_ptr, png_voidp ptr)
273 {
274 if (png_ptr == NULL || ptr == NULL)
275 return;
276
277 #ifdef PNG_USER_MEM_SUPPORTED
278 if (png_ptr->free_fn != NULL)
279 {
280 (*(png_ptr->free_fn))(png_ptr, ptr);
281 return;
282 }
283 else png_free_default(png_ptr, ptr);
284 }
285
286 void PNGAPI
287 png_free_default(png_structp png_ptr, png_voidp ptr)
288 {
289 #endif /* PNG_USER_MEM_SUPPORTED */
290
291 if (png_ptr->offset_table != NULL)
292 {
293 int i;
294
295 for (i = 0; i < png_ptr->offset_table_count; i++)
296 {
297 if (ptr == png_ptr->offset_table_ptr[i])
298 {
299 ptr = NULL;
300 png_ptr->offset_table_count_free++;
301 break;
302 }
303 }
304 if (png_ptr->offset_table_count_free == png_ptr->offset_table_count)
305 {
306 farfree(png_ptr->offset_table);
307 farfree(png_ptr->offset_table_ptr);
308 png_ptr->offset_table = NULL;
309 png_ptr->offset_table_ptr = NULL;
310 }
311 }
312
313 if (ptr != NULL)
314 {
315 farfree(ptr);
316 }
317 }
318
319 #else /* Not the Borland DOS special memory handler */
320
321 /* Allocate memory for a png_struct or a png_info. The malloc and
322 memset can be replaced by a single call to calloc() if this is thought
323 to improve performance noticably. */
324 png_voidp /* PRIVATE */
325 png_create_struct(int type)
326 {
327 #ifdef PNG_USER_MEM_SUPPORTED
328 return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL));
329 }
330
331 /* Allocate memory for a png_struct or a png_info. The malloc and
332 memset can be replaced by a single call to calloc() if this is thought
333 to improve performance noticably. */
334 png_voidp /* PRIVATE */
335 png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
336 {
337 #endif /* PNG_USER_MEM_SUPPORTED */
338 png_size_t size;
339 png_voidp struct_ptr;
340
341 if (type == PNG_STRUCT_INFO)
342 size = png_sizeof(png_info);
343 else if (type == PNG_STRUCT_PNG)
344 size = png_sizeof(png_struct);
345 else
346 return (NULL);
347
348 #ifdef PNG_USER_MEM_SUPPORTED
349 if(malloc_fn != NULL)
350 {
351 png_struct dummy_struct;
352 png_structp png_ptr = &dummy_struct;
353 png_ptr->mem_ptr=mem_ptr;
354 struct_ptr = (*(malloc_fn))(png_ptr, size);
355 if (struct_ptr != NULL)
356 png_memset(struct_ptr, 0, size);
357 return (struct_ptr);
358 }
359 #endif /* PNG_USER_MEM_SUPPORTED */
360
361 #if defined(__TURBOC__) && !defined(__FLAT__)
362 struct_ptr = (png_voidp)farmalloc(size);
363 #else
364 # if defined(_MSC_VER) && defined(MAXSEG_64K)
365 struct_ptr = (png_voidp)halloc(size,1);
366 # else
367 struct_ptr = (png_voidp)malloc(size);
368 # endif
369 #endif
370 if (struct_ptr != NULL)
371 png_memset(struct_ptr, 0, size);
372
373 return (struct_ptr);
374 }
375
376
377 /* Free memory allocated by a png_create_struct() call */
378 void /* PRIVATE */
379 png_destroy_struct(png_voidp struct_ptr)
380 {
381 #ifdef PNG_USER_MEM_SUPPORTED
382 png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL);
383 }
384
385 /* Free memory allocated by a png_create_struct() call */
386 void /* PRIVATE */
387 png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
388 png_voidp mem_ptr)
389 {
390 #endif /* PNG_USER_MEM_SUPPORTED */
391 if (struct_ptr != NULL)
392 {
393 #ifdef PNG_USER_MEM_SUPPORTED
394 if(free_fn != NULL)
395 {
396 png_struct dummy_struct;
397 png_structp png_ptr = &dummy_struct;
398 png_ptr->mem_ptr=mem_ptr;
399 (*(free_fn))(png_ptr, struct_ptr);
400 return;
401 }
402 #endif /* PNG_USER_MEM_SUPPORTED */
403 #if defined(__TURBOC__) && !defined(__FLAT__)
404 farfree(struct_ptr);
405 #else
406 # if defined(_MSC_VER) && defined(MAXSEG_64K)
407 hfree(struct_ptr);
408 # else
409 free(struct_ptr);
410 # endif
411 #endif
412 }
413 }
414
415 /* Allocate memory. For reasonable files, size should never exceed
416 64K. However, zlib may allocate more then 64K if you don't tell
417 it not to. See zconf.h and png.h for more information. zlib does
418 need to allocate exactly 64K, so whatever you call here must
419 have the ability to do that. */
420
421 png_voidp PNGAPI
422 png_malloc(png_structp png_ptr, png_uint_32 size)
423 {
424 png_voidp ret;
425
426 #ifdef PNG_USER_MEM_SUPPORTED
427 if (png_ptr == NULL || size == 0)
428 return (NULL);
429
430 if(png_ptr->malloc_fn != NULL)
431 ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
432 else
433 ret = (png_malloc_default(png_ptr, size));
434 if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
435 png_error(png_ptr, "Out of Memory!");
436 return (ret);
437 }
438
439 png_voidp PNGAPI
440 png_malloc_default(png_structp png_ptr, png_uint_32 size)
441 {
442 png_voidp ret;
443 #endif /* PNG_USER_MEM_SUPPORTED */
444
445 if (png_ptr == NULL || size == 0)
446 return (NULL);
447
448 #ifdef PNG_MAX_MALLOC_64K
449 if (size > (png_uint_32)65536L)
450 {
451 #ifndef PNG_USER_MEM_SUPPORTED
452 if(png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
453 png_error(png_ptr, "Cannot Allocate > 64K");
454 else
455 #endif
456 return NULL;
457 }
458 #endif
459
460 /* Check for overflow */
461 #if defined(__TURBOC__) && !defined(__FLAT__)
462 if (size != (unsigned long)size)
463 ret = NULL;
464 else
465 ret = farmalloc(size);
466 #else
467 # if defined(_MSC_VER) && defined(MAXSEG_64K)
468 if (size != (unsigned long)size)
469 ret = NULL;
470 else
471 ret = halloc(size, 1);
472 # else
473 if (size != (size_t)size)
474 ret = NULL;
475 else
476 ret = malloc((size_t)size);
477 # endif
478 #endif
479
480 #ifndef PNG_USER_MEM_SUPPORTED
481 if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
482 png_error(png_ptr, "Out of Memory");
483 #endif
484
485 return (ret);
486 }
487
488 /* Free a pointer allocated by png_malloc(). If ptr is NULL, return
489 without taking any action. */
490 void PNGAPI
491 png_free(png_structp png_ptr, png_voidp ptr)
492 {
493 if (png_ptr == NULL || ptr == NULL)
494 return;
495
496 #ifdef PNG_USER_MEM_SUPPORTED
497 if (png_ptr->free_fn != NULL)
498 {
499 (*(png_ptr->free_fn))(png_ptr, ptr);
500 return;
501 }
502 else png_free_default(png_ptr, ptr);
503 }
504 void PNGAPI
505 png_free_default(png_structp png_ptr, png_voidp ptr)
506 {
507 if (png_ptr == NULL || ptr == NULL)
508 return;
509
510 #endif /* PNG_USER_MEM_SUPPORTED */
511
512 #if defined(__TURBOC__) && !defined(__FLAT__)
513 farfree(ptr);
514 #else
515 # if defined(_MSC_VER) && defined(MAXSEG_64K)
516 hfree(ptr);
517 # else
518 free(ptr);
519 # endif
520 #endif
521 }
522
523 #endif /* Not Borland DOS special memory handler */
524
525 #if defined(PNG_1_0_X)
526 # define png_malloc_warn png_malloc
527 #else
528 /* This function was added at libpng version 1.2.3. The png_malloc_warn()
529 * function will set up png_malloc() to issue a png_warning and return NULL
530 * instead of issuing a png_error, if it fails to allocate the requested
531 * memory.
532 */
533 png_voidp PNGAPI
534 png_malloc_warn(png_structp png_ptr, png_uint_32 size)
535 {
536 png_voidp ptr;
537 png_uint_32 save_flags=png_ptr->flags;
538
539 png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK;
540 ptr = (png_voidp)png_malloc((png_structp)png_ptr, size);
541 png_ptr->flags=save_flags;
542 return(ptr);
543 }
544 #endif
545
546 png_voidp PNGAPI
547 png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2,
548 png_uint_32 length)
549 {
550 png_size_t size;
551
552 size = (png_size_t)length;
553 if ((png_uint_32)size != length)
554 png_error(png_ptr,"Overflow in png_memcpy_check.");
555
556 return(png_memcpy (s1, s2, size));
557 }
558
559 png_voidp PNGAPI
560 png_memset_check (png_structp png_ptr, png_voidp s1, int value,
561 png_uint_32 length)
562 {
563 png_size_t size;
564
565 size = (png_size_t)length;
566 if ((png_uint_32)size != length)
567 png_error(png_ptr,"Overflow in png_memset_check.");
568
569 return (png_memset (s1, value, size));
570
571 }
572
573 #ifdef PNG_USER_MEM_SUPPORTED
574 /* This function is called when the application wants to use another method
575 * of allocating and freeing memory.
576 */
577 void PNGAPI
578 png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
579 malloc_fn, png_free_ptr free_fn)
580 {
581 png_ptr->mem_ptr = mem_ptr;
582 png_ptr->malloc_fn = malloc_fn;
583 png_ptr->free_fn = free_fn;
584 }
585
586 /* This function returns a pointer to the mem_ptr associated with the user
587 * functions. The application should free any memory associated with this
588 * pointer before png_write_destroy and png_read_destroy are called.
589 */
590 png_voidp PNGAPI
591 png_get_mem_ptr(png_structp png_ptr)
592 {
593 return ((png_voidp)png_ptr->mem_ptr);
594 }
595 #endif /* PNG_USER_MEM_SUPPORTED */