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