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 */
png_create_struct(int type)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 */
png_create_struct_2(int type,png_malloc_ptr malloc_fn,png_voidp mem_ptr)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 */
png_destroy_struct(png_voidp struct_ptr)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 */
png_destroy_struct_2(png_voidp struct_ptr,png_free_ptr free_fn,png_voidp mem_ptr)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
png_malloc(png_structp png_ptr,png_uint_32 size)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
png_malloc_default(png_structp png_ptr,png_uint_32 size)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
png_free(png_structp png_ptr,png_voidp ptr)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
png_free_default(png_structp png_ptr,png_voidp ptr)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 */
png_create_struct(int type)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 */
png_create_struct_2(int type,png_malloc_ptr malloc_fn,png_voidp mem_ptr)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 */
png_destroy_struct(png_voidp struct_ptr)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 */
png_destroy_struct_2(png_voidp struct_ptr,png_free_ptr free_fn,png_voidp mem_ptr)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
png_malloc(png_structp png_ptr,png_uint_32 size)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
png_malloc_default(png_structp png_ptr,png_uint_32 size)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
png_free(png_structp png_ptr,png_voidp ptr)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
png_free_default(png_structp png_ptr,png_voidp ptr)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
png_malloc_warn(png_structp png_ptr,png_uint_32 size)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
png_memcpy_check(png_structp png_ptr,png_voidp s1,png_voidp s2,png_uint_32 length)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
png_memset_check(png_structp png_ptr,png_voidp s1,int value,png_uint_32 length)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
png_set_mem_fn(png_structp png_ptr,png_voidp mem_ptr,png_malloc_ptr malloc_fn,png_free_ptr free_fn)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
png_get_mem_ptr(png_structp png_ptr)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 */
596