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