blob: d702f61eff1103862c444e461d2957bbc46f9e62 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation. Sun designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Sun in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
22 * have any questions.
23 */
24
25/* pngmem.c - stub functions for memory allocation
26 *
27 * This file is available under and governed by the GNU General Public
28 * License version 2 only, as published by the Free Software Foundation.
29 * However, the following notice accompanied the original version of this
30 * file and, per its terms, should not be removed:
31 *
32 * Last changed in libpng 1.2.13 November 13, 2006
33 * For conditions of distribution and use, see copyright notice in png.h
34 * Copyright (c) 1998-2006 Glenn Randers-Pehrson
35 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
36 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
37 *
38 * This file provides a location for all memory allocation. Users who
39 * need special memory handling are expected to supply replacement
40 * functions for png_malloc() and png_free(), and to use
41 * png_create_read_struct_2() and png_create_write_struct_2() to
42 * identify the replacement functions.
43 */
44
45#define PNG_INTERNAL
46#include "png.h"
47
48#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
49
50/* Borland DOS special memory handler */
51#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
52/* if you change this, be sure to change the one in png.h also */
53
54/* Allocate memory for a png_struct. The malloc and memset can be replaced
55 by a single call to calloc() if this is thought to improve performance. */
56png_voidp /* PRIVATE */
57png_create_struct(int type)
58{
59#ifdef PNG_USER_MEM_SUPPORTED
60 return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL));
61}
62
63/* Alternate version of png_create_struct, for use with user-defined malloc. */
64png_voidp /* PRIVATE */
65png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
66{
67#endif /* PNG_USER_MEM_SUPPORTED */
68 png_size_t size;
69 png_voidp struct_ptr;
70
71 if (type == PNG_STRUCT_INFO)
72 size = png_sizeof(png_info);
73 else if (type == PNG_STRUCT_PNG)
74 size = png_sizeof(png_struct);
75 else
76 return (png_get_copyright(NULL));
77
78#ifdef PNG_USER_MEM_SUPPORTED
79 if(malloc_fn != NULL)
80 {
81 png_struct dummy_struct;
82 png_structp png_ptr = &dummy_struct;
83 png_ptr->mem_ptr=mem_ptr;
84 struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size);
85 }
86 else
87#endif /* PNG_USER_MEM_SUPPORTED */
88 struct_ptr = (png_voidp)farmalloc(size);
89 if (struct_ptr != NULL)
90 png_memset(struct_ptr, 0, size);
91 return (struct_ptr);
92}
93
94/* Free memory allocated by a png_create_struct() call */
95void /* PRIVATE */
96png_destroy_struct(png_voidp struct_ptr)
97{
98#ifdef PNG_USER_MEM_SUPPORTED
99 png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL);
100}
101
102/* Free memory allocated by a png_create_struct() call */
103void /* PRIVATE */
104png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
105 png_voidp mem_ptr)
106{
107#endif
108 if (struct_ptr != NULL)
109 {
110#ifdef PNG_USER_MEM_SUPPORTED
111 if(free_fn != NULL)
112 {
113 png_struct dummy_struct;
114 png_structp png_ptr = &dummy_struct;
115 png_ptr->mem_ptr=mem_ptr;
116 (*(free_fn))(png_ptr, struct_ptr);
117 return;
118 }
119#endif /* PNG_USER_MEM_SUPPORTED */
120 farfree (struct_ptr);
121 }
122}
123
124/* Allocate memory. For reasonable files, size should never exceed
125 * 64K. However, zlib may allocate more then 64K if you don't tell
126 * it not to. See zconf.h and png.h for more information. zlib does
127 * need to allocate exactly 64K, so whatever you call here must
128 * have the ability to do that.
129 *
130 * Borland seems to have a problem in DOS mode for exactly 64K.
131 * It gives you a segment with an offset of 8 (perhaps to store its
132 * memory stuff). zlib doesn't like this at all, so we have to
133 * detect and deal with it. This code should not be needed in
134 * Windows or OS/2 modes, and only in 16 bit mode. This code has
135 * been updated by Alexander Lehmann for version 0.89 to waste less
136 * memory.
137 *
138 * Note that we can't use png_size_t for the "size" declaration,
139 * since on some systems a png_size_t is a 16-bit quantity, and as a
140 * result, we would be truncating potentially larger memory requests
141 * (which should cause a fatal error) and introducing major problems.
142 */
143
144png_voidp PNGAPI
145png_malloc(png_structp png_ptr, png_uint_32 size)
146{
147 png_voidp ret;
148
149 if (png_ptr == NULL || size == 0)
150 return (NULL);
151
152#ifdef PNG_USER_MEM_SUPPORTED
153 if(png_ptr->malloc_fn != NULL)
154 ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
155 else
156 ret = (png_malloc_default(png_ptr, size));
157 if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
158 png_error(png_ptr, "Out of memory!");
159 return (ret);
160}
161
162png_voidp PNGAPI
163png_malloc_default(png_structp png_ptr, png_uint_32 size)
164{
165 png_voidp ret;
166#endif /* PNG_USER_MEM_SUPPORTED */
167
168 if (png_ptr == NULL || size == 0)
169 return (NULL);
170
171#ifdef PNG_MAX_MALLOC_64K
172 if (size > (png_uint_32)65536L)
173 {
174 png_warning(png_ptr, "Cannot Allocate > 64K");
175 ret = NULL;
176 }
177 else
178#endif
179
180 if (size != (size_t)size)
181 ret = NULL;
182 else if (size == (png_uint_32)65536L)
183 {
184 if (png_ptr->offset_table == NULL)
185 {
186 /* try to see if we need to do any of this fancy stuff */
187 ret = farmalloc(size);
188 if (ret == NULL || ((png_size_t)ret & 0xffff))
189 {
190 int num_blocks;
191 png_uint_32 total_size;
192 png_bytep table;
193 int i;
194 png_byte huge * hptr;
195
196 if (ret != NULL)
197 {
198 farfree(ret);
199 ret = NULL;
200 }
201
202 if(png_ptr->zlib_window_bits > 14)
203 num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14));
204 else
205 num_blocks = 1;
206 if (png_ptr->zlib_mem_level >= 7)
207 num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7));
208 else
209 num_blocks++;
210
211 total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16;
212
213 table = farmalloc(total_size);
214
215 if (table == 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 if ((png_size_t)table & 0xfff0)
227 {
228#ifndef PNG_USER_MEM_SUPPORTED
229 if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
230 png_error(png_ptr,
231 "Farmalloc didn't return normalized pointer");
232 else
233 png_warning(png_ptr,
234 "Farmalloc didn't return normalized pointer");
235#endif
236 return (NULL);
237 }
238
239 png_ptr->offset_table = table;
240 png_ptr->offset_table_ptr = farmalloc(num_blocks *
241 png_sizeof (png_bytep));
242
243 if (png_ptr->offset_table_ptr == NULL)
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 hptr = (png_byte huge *)table;
255 if ((png_size_t)hptr & 0xf)
256 {
257 hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
258 hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */
259 }
260 for (i = 0; i < num_blocks; i++)
261 {
262 png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
263 hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */
264 }
265
266 png_ptr->offset_table_number = num_blocks;
267 png_ptr->offset_table_count = 0;
268 png_ptr->offset_table_count_free = 0;
269 }
270 }
271
272 if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
273 {
274#ifndef PNG_USER_MEM_SUPPORTED
275 if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
276 png_error(png_ptr, "Out of Memory."); /* Note "o" and "M" */
277 else
278 png_warning(png_ptr, "Out of Memory.");
279#endif
280 return (NULL);
281 }
282
283 ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
284 }
285 else
286 ret = farmalloc(size);
287
288#ifndef PNG_USER_MEM_SUPPORTED
289 if (ret == NULL)
290 {
291 if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
292 png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */
293 else
294 png_warning(png_ptr, "Out of memory."); /* Note "o" and "m" */
295 }
296#endif
297
298 return (ret);
299}
300
301/* free a pointer allocated by png_malloc(). In the default
302 configuration, png_ptr is not used, but is passed in case it
303 is needed. If ptr is NULL, return without taking any action. */
304void PNGAPI
305png_free(png_structp png_ptr, png_voidp ptr)
306{
307 if (png_ptr == NULL || ptr == NULL)
308 return;
309
310#ifdef PNG_USER_MEM_SUPPORTED
311 if (png_ptr->free_fn != NULL)
312 {
313 (*(png_ptr->free_fn))(png_ptr, ptr);
314 return;
315 }
316 else png_free_default(png_ptr, ptr);
317}
318
319void PNGAPI
320png_free_default(png_structp png_ptr, png_voidp ptr)
321{
322#endif /* PNG_USER_MEM_SUPPORTED */
323
324 if(png_ptr == NULL) return;
325
326 if (png_ptr->offset_table != NULL)
327 {
328 int i;
329
330 for (i = 0; i < png_ptr->offset_table_count; i++)
331 {
332 if (ptr == png_ptr->offset_table_ptr[i])
333 {
334 ptr = NULL;
335 png_ptr->offset_table_count_free++;
336 break;
337 }
338 }
339 if (png_ptr->offset_table_count_free == png_ptr->offset_table_count)
340 {
341 farfree(png_ptr->offset_table);
342 farfree(png_ptr->offset_table_ptr);
343 png_ptr->offset_table = NULL;
344 png_ptr->offset_table_ptr = NULL;
345 }
346 }
347
348 if (ptr != NULL)
349 {
350 farfree(ptr);
351 }
352}
353
354#else /* Not the Borland DOS special memory handler */
355
356/* Allocate memory for a png_struct or a png_info. The malloc and
357 memset can be replaced by a single call to calloc() if this is thought
358 to improve performance noticably. */
359png_voidp /* PRIVATE */
360png_create_struct(int type)
361{
362#ifdef PNG_USER_MEM_SUPPORTED
363 return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL));
364}
365
366/* Allocate memory for a png_struct or a png_info. The malloc and
367 memset can be replaced by a single call to calloc() if this is thought
368 to improve performance noticably. */
369png_voidp /* PRIVATE */
370png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
371{
372#endif /* PNG_USER_MEM_SUPPORTED */
373 png_size_t size;
374 png_voidp struct_ptr;
375
376 if (type == PNG_STRUCT_INFO)
377 size = png_sizeof(png_info);
378 else if (type == PNG_STRUCT_PNG)
379 size = png_sizeof(png_struct);
380 else
381 return (NULL);
382
383#ifdef PNG_USER_MEM_SUPPORTED
384 if(malloc_fn != NULL)
385 {
386 png_struct dummy_struct;
387 png_structp png_ptr = &dummy_struct;
388 png_ptr->mem_ptr=mem_ptr;
389 struct_ptr = (*(malloc_fn))(png_ptr, size);
390 if (struct_ptr != NULL)
391 png_memset(struct_ptr, 0, size);
392 return (struct_ptr);
393 }
394#endif /* PNG_USER_MEM_SUPPORTED */
395
396#if defined(__TURBOC__) && !defined(__FLAT__)
397 struct_ptr = (png_voidp)farmalloc(size);
398#else
399# if defined(_MSC_VER) && defined(MAXSEG_64K)
400 struct_ptr = (png_voidp)halloc(size,1);
401# else
402 struct_ptr = (png_voidp)malloc(size);
403# endif
404#endif
405 if (struct_ptr != NULL)
406 png_memset(struct_ptr, 0, size);
407
408 return (struct_ptr);
409}
410
411
412/* Free memory allocated by a png_create_struct() call */
413void /* PRIVATE */
414png_destroy_struct(png_voidp struct_ptr)
415{
416#ifdef PNG_USER_MEM_SUPPORTED
417 png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL);
418}
419
420/* Free memory allocated by a png_create_struct() call */
421void /* PRIVATE */
422png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
423 png_voidp mem_ptr)
424{
425#endif /* PNG_USER_MEM_SUPPORTED */
426 if (struct_ptr != NULL)
427 {
428#ifdef PNG_USER_MEM_SUPPORTED
429 if(free_fn != NULL)
430 {
431 png_struct dummy_struct;
432 png_structp png_ptr = &dummy_struct;
433 png_ptr->mem_ptr=mem_ptr;
434 (*(free_fn))(png_ptr, struct_ptr);
435 return;
436 }
437#endif /* PNG_USER_MEM_SUPPORTED */
438#if defined(__TURBOC__) && !defined(__FLAT__)
439 farfree(struct_ptr);
440#else
441# if defined(_MSC_VER) && defined(MAXSEG_64K)
442 hfree(struct_ptr);
443# else
444 free(struct_ptr);
445# endif
446#endif
447 }
448}
449
450/* Allocate memory. For reasonable files, size should never exceed
451 64K. However, zlib may allocate more then 64K if you don't tell
452 it not to. See zconf.h and png.h for more information. zlib does
453 need to allocate exactly 64K, so whatever you call here must
454 have the ability to do that. */
455
456png_voidp PNGAPI
457png_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
474png_voidp PNGAPI
475png_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. */
525void PNGAPI
526png_free(png_structp png_ptr, png_voidp ptr)
527{
528 if (png_ptr == NULL || ptr == NULL)
529 return;
530
531#ifdef PNG_USER_MEM_SUPPORTED
532 if (png_ptr->free_fn != NULL)
533 {
534 (*(png_ptr->free_fn))(png_ptr, ptr);
535 return;
536 }
537 else png_free_default(png_ptr, ptr);
538}
539void PNGAPI
540png_free_default(png_structp png_ptr, png_voidp ptr)
541{
542 if (png_ptr == NULL || ptr == NULL)
543 return;
544
545#endif /* PNG_USER_MEM_SUPPORTED */
546
547#if defined(__TURBOC__) && !defined(__FLAT__)
548 farfree(ptr);
549#else
550# if defined(_MSC_VER) && defined(MAXSEG_64K)
551 hfree(ptr);
552# else
553 free(ptr);
554# endif
555#endif
556}
557
558#endif /* Not Borland DOS special memory handler */
559
560#if defined(PNG_1_0_X)
561# define png_malloc_warn png_malloc
562#else
563/* This function was added at libpng version 1.2.3. The png_malloc_warn()
564 * function will set up png_malloc() to issue a png_warning and return NULL
565 * instead of issuing a png_error, if it fails to allocate the requested
566 * memory.
567 */
568png_voidp PNGAPI
569png_malloc_warn(png_structp png_ptr, png_uint_32 size)
570{
571 png_voidp ptr;
572 png_uint_32 save_flags;
573 if(png_ptr == NULL) return (NULL);
574
575 save_flags=png_ptr->flags;
576 png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK;
577 ptr = (png_voidp)png_malloc((png_structp)png_ptr, size);
578 png_ptr->flags=save_flags;
579 return(ptr);
580}
581#endif
582
583png_voidp PNGAPI
584png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2,
585 png_uint_32 length)
586{
587 png_size_t size;
588
589 size = (png_size_t)length;
590 if ((png_uint_32)size != length)
591 png_error(png_ptr,"Overflow in png_memcpy_check.");
592
593 return(png_memcpy (s1, s2, size));
594}
595
596png_voidp PNGAPI
597png_memset_check (png_structp png_ptr, png_voidp s1, int value,
598 png_uint_32 length)
599{
600 png_size_t size;
601
602 size = (png_size_t)length;
603 if ((png_uint_32)size != length)
604 png_error(png_ptr,"Overflow in png_memset_check.");
605
606 return (png_memset (s1, value, size));
607
608}
609
610#ifdef PNG_USER_MEM_SUPPORTED
611/* This function is called when the application wants to use another method
612 * of allocating and freeing memory.
613 */
614void PNGAPI
615png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
616 malloc_fn, png_free_ptr free_fn)
617{
618 if(png_ptr != NULL) {
619 png_ptr->mem_ptr = mem_ptr;
620 png_ptr->malloc_fn = malloc_fn;
621 png_ptr->free_fn = free_fn;
622 }
623}
624
625/* This function returns a pointer to the mem_ptr associated with the user
626 * functions. The application should free any memory associated with this
627 * pointer before png_write_destroy and png_read_destroy are called.
628 */
629png_voidp PNGAPI
630png_get_mem_ptr(png_structp png_ptr)
631{
632 if(png_ptr == NULL) return (NULL);
633 return ((png_voidp)png_ptr->mem_ptr);
634}
635#endif /* PNG_USER_MEM_SUPPORTED */
636#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */