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