Home | History | Annotate | Download | only in libpng-1.2.19
      1 
      2 /* pngmem.c - stub functions for memory allocation
      3  *
      4  * Last changed in libpng 1.2.13 November 13, 2006
      5  * For conditions of distribution and use, see copyright notice in png.h
      6  * Copyright (c) 1998-2006 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 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
     21 
     22 /* Borland DOS special memory handler */
     23 #if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
     24 /* if you change this, be sure to change the one in png.h also */
     25 
     26 /* Allocate memory for a png_struct.  The malloc and memset can be replaced
     27    by a single call to calloc() if this is thought to improve performance. */
     28 png_voidp /* PRIVATE */
     29 png_create_struct(int type)
     30 {
     31 #ifdef PNG_USER_MEM_SUPPORTED
     32    return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL));
     33 }
     34 
     35 /* Alternate version of png_create_struct, for use with user-defined malloc. */
     36 png_voidp /* PRIVATE */
     37 png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
     38 {
     39 #endif /* PNG_USER_MEM_SUPPORTED */
     40    png_size_t size;
     41    png_voidp struct_ptr;
     42 
     43    if (type == PNG_STRUCT_INFO)
     44      size = png_sizeof(png_info);
     45    else if (type == PNG_STRUCT_PNG)
     46      size = png_sizeof(png_struct);
     47    else
     48      return (png_get_copyright(NULL));
     49 
     50 #ifdef PNG_USER_MEM_SUPPORTED
     51    if(malloc_fn != NULL)
     52    {
     53       png_struct dummy_struct;
     54       png_structp png_ptr = &dummy_struct;
     55       png_ptr->mem_ptr=mem_ptr;
     56       struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size);
     57    }
     58    else
     59 #endif /* PNG_USER_MEM_SUPPORTED */
     60       struct_ptr = (png_voidp)farmalloc(size);
     61    if (struct_ptr != NULL)
     62       png_memset(struct_ptr, 0, size);
     63    return (struct_ptr);
     64 }
     65 
     66 /* Free memory allocated by a png_create_struct() call */
     67 void /* PRIVATE */
     68 png_destroy_struct(png_voidp struct_ptr)
     69 {
     70 #ifdef PNG_USER_MEM_SUPPORTED
     71    png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL);
     72 }
     73 
     74 /* Free memory allocated by a png_create_struct() call */
     75 void /* PRIVATE */
     76 png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
     77     png_voidp mem_ptr)
     78 {
     79 #endif
     80    if (struct_ptr != NULL)
     81    {
     82 #ifdef PNG_USER_MEM_SUPPORTED
     83       if(free_fn != NULL)
     84       {
     85          png_struct dummy_struct;
     86          png_structp png_ptr = &dummy_struct;
     87          png_ptr->mem_ptr=mem_ptr;
     88          (*(free_fn))(png_ptr, struct_ptr);
     89          return;
     90       }
     91 #endif /* PNG_USER_MEM_SUPPORTED */
     92       farfree (struct_ptr);
     93    }
     94 }
     95 
     96 /* Allocate memory.  For reasonable files, size should never exceed
     97  * 64K.  However, zlib may allocate more then 64K if you don't tell
     98  * it not to.  See zconf.h and png.h for more information. zlib does
     99  * need to allocate exactly 64K, so whatever you call here must
    100  * have the ability to do that.
    101  *
    102  * Borland seems to have a problem in DOS mode for exactly 64K.
    103  * It gives you a segment with an offset of 8 (perhaps to store its
    104  * memory stuff).  zlib doesn't like this at all, so we have to
    105  * detect and deal with it.  This code should not be needed in
    106  * Windows or OS/2 modes, and only in 16 bit mode.  This code has
    107  * been updated by Alexander Lehmann for version 0.89 to waste less
    108  * memory.
    109  *
    110  * Note that we can't use png_size_t for the "size" declaration,
    111  * since on some systems a png_size_t is a 16-bit quantity, and as a
    112  * result, we would be truncating potentially larger memory requests
    113  * (which should cause a fatal error) and introducing major problems.
    114  */
    115 
    116 png_voidp PNGAPI
    117 png_malloc(png_structp png_ptr, png_uint_32 size)
    118 {
    119    png_voidp ret;
    120 
    121    if (png_ptr == NULL || size == 0)
    122       return (NULL);
    123 
    124 #ifdef PNG_USER_MEM_SUPPORTED
    125    if(png_ptr->malloc_fn != NULL)
    126        ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
    127    else
    128        ret = (png_malloc_default(png_ptr, size));
    129    if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
    130        png_error(png_ptr, "Out of memory!");
    131    return (ret);
    132 }
    133 
    134 png_voidp PNGAPI
    135 png_malloc_default(png_structp png_ptr, png_uint_32 size)
    136 {
    137    png_voidp ret;
    138 #endif /* PNG_USER_MEM_SUPPORTED */
    139 
    140    if (png_ptr == NULL || size == 0)
    141       return (NULL);
    142 
    143 #ifdef PNG_MAX_MALLOC_64K
    144    if (size > (png_uint_32)65536L)
    145    {
    146       png_warning(png_ptr, "Cannot Allocate > 64K");
    147       ret = NULL;
    148    }
    149    else
    150 #endif
    151 
    152    if (size != (size_t)size)
    153      ret = NULL;
    154    else if (size == (png_uint_32)65536L)
    155    {
    156       if (png_ptr->offset_table == NULL)
    157       {
    158          /* try to see if we need to do any of this fancy stuff */
    159          ret = farmalloc(size);
    160          if (ret == NULL || ((png_size_t)ret & 0xffff))
    161          {
    162             int num_blocks;
    163             png_uint_32 total_size;
    164             png_bytep table;
    165             int i;
    166             png_byte huge * hptr;
    167 
    168             if (ret != NULL)
    169             {
    170                farfree(ret);
    171                ret = NULL;
    172             }
    173 
    174             if(png_ptr->zlib_window_bits > 14)
    175                num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14));
    176             else
    177                num_blocks = 1;
    178             if (png_ptr->zlib_mem_level >= 7)
    179                num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7));
    180             else
    181                num_blocks++;
    182 
    183             total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16;
    184 
    185             table = farmalloc(total_size);
    186 
    187             if (table == NULL)
    188             {
    189 #ifndef PNG_USER_MEM_SUPPORTED
    190                if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
    191                   png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */
    192                else
    193                   png_warning(png_ptr, "Out Of Memory.");
    194 #endif
    195                return (NULL);
    196             }
    197 
    198             if ((png_size_t)table & 0xfff0)
    199             {
    200 #ifndef PNG_USER_MEM_SUPPORTED
    201                if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
    202                   png_error(png_ptr,
    203                     "Farmalloc didn't return normalized pointer");
    204                else
    205                   png_warning(png_ptr,
    206                     "Farmalloc didn't return normalized pointer");
    207 #endif
    208                return (NULL);
    209             }
    210 
    211             png_ptr->offset_table = table;
    212             png_ptr->offset_table_ptr = farmalloc(num_blocks *
    213                png_sizeof (png_bytep));
    214 
    215             if (png_ptr->offset_table_ptr == NULL)
    216             {
    217 #ifndef PNG_USER_MEM_SUPPORTED
    218                if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
    219                   png_error(png_ptr, "Out Of memory."); /* Note "O" and "M" */
    220                else
    221                   png_warning(png_ptr, "Out Of memory.");
    222 #endif
    223                return (NULL);
    224             }
    225 
    226             hptr = (png_byte huge *)table;
    227             if ((png_size_t)hptr & 0xf)
    228             {
    229                hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
    230                hptr = hptr + 16L;  /* "hptr += 16L" fails on Turbo C++ 3.0 */
    231             }
    232             for (i = 0; i < num_blocks; i++)
    233             {
    234                png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
    235                hptr = hptr + (png_uint_32)65536L;  /* "+=" fails on TC++3.0 */
    236             }
    237 
    238             png_ptr->offset_table_number = num_blocks;
    239             png_ptr->offset_table_count = 0;
    240             png_ptr->offset_table_count_free = 0;
    241          }
    242       }
    243 
    244       if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
    245       {
    246 #ifndef PNG_USER_MEM_SUPPORTED
    247          if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
    248             png_error(png_ptr, "Out of Memory."); /* Note "o" and "M" */
    249          else
    250             png_warning(png_ptr, "Out of Memory.");
    251 #endif
    252          return (NULL);
    253       }
    254 
    255       ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
    256    }
    257    else
    258       ret = farmalloc(size);
    259 
    260 #ifndef PNG_USER_MEM_SUPPORTED
    261    if (ret == NULL)
    262    {
    263       if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
    264          png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */
    265       else
    266          png_warning(png_ptr, "Out of memory."); /* Note "o" and "m" */
    267    }
    268 #endif
    269 
    270    return (ret);
    271 }
    272 
    273 /* free a pointer allocated by png_malloc().  In the default
    274    configuration, png_ptr is not used, but is passed in case it
    275    is needed.  If ptr is NULL, return without taking any action. */
    276 void PNGAPI
    277 png_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 
    291 void PNGAPI
    292 png_free_default(png_structp png_ptr, png_voidp ptr)
    293 {
    294 #endif /* PNG_USER_MEM_SUPPORTED */
    295 
    296    if(png_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. */
    331 png_voidp /* PRIVATE */
    332 png_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. */
    341 png_voidp /* PRIVATE */
    342 png_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 */
    385 void /* PRIVATE */
    386 png_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 */
    393 void /* PRIVATE */
    394 png_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 
    428 png_voidp PNGAPI
    429 png_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 
    446 png_voidp PNGAPI
    447 png_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. */
    497 void PNGAPI
    498 png_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 }
    511 void PNGAPI
    512 png_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  */
    540 png_voidp PNGAPI
    541 png_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 
    555 png_voidp PNGAPI
    556 png_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 
    568 png_voidp PNGAPI
    569 png_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  */
    586 void PNGAPI
    587 png_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    png_ptr->mem_ptr = mem_ptr;
    592    png_ptr->malloc_fn = malloc_fn;
    593    png_ptr->free_fn = free_fn;
    594    }
    595 }
    596 
    597 /* This function returns a pointer to the mem_ptr associated with the user
    598  * functions.  The application should free any memory associated with this
    599  * pointer before png_write_destroy and png_read_destroy are called.
    600  */
    601 png_voidp PNGAPI
    602 png_get_mem_ptr(png_structp png_ptr)
    603 {
    604    if(png_ptr == NULL) return (NULL);
    605    return ((png_voidp)png_ptr->mem_ptr);
    606 }
    607 #endif /* PNG_USER_MEM_SUPPORTED */
    608 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
    609