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