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