]> granicus.if.org Git - imagemagick/blob - MagickCore/memory.c
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10005
[imagemagick] / MagickCore / memory.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                    M   M  EEEEE  M   M   OOO   RRRR   Y   Y                 %
7 %                    MM MM  E      MM MM  O   O  R   R   Y Y                  %
8 %                    M M M  EEE    M M M  O   O  RRRR     Y                   %
9 %                    M   M  E      M   M  O   O  R R      Y                   %
10 %                    M   M  EEEEE  M   M   OOO   R  R     Y                   %
11 %                                                                             %
12 %                                                                             %
13 %                     MagickCore Memory Allocation Methods                    %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                   Cristy                                    %
17 %                                 July 1998                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2018 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    https://www.imagemagick.org/script/license.php                           %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %  Segregate our memory requirements from any program that calls our API.  This
37 %  should help reduce the risk of others changing our program state or causing
38 %  memory corruption.
39 %
40 %  Our custom memory allocation manager implements a best-fit allocation policy
41 %  using segregated free lists.  It uses a linear distribution of size classes
42 %  for lower sizes and a power of two distribution of size classes at higher
43 %  sizes.  It is based on the paper, "Fast Memory Allocation using Lazy Fits."
44 %  written by Yoo C. Chung.
45 %
46 %  By default, ANSI memory methods are called (e.g. malloc).  Use the
47 %  custom memory allocator by defining MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT
48 %  to allocate memory with private anonymous mapping rather than from the
49 %  heap.
50 %
51 */
52 \f
53 /*
54   Include declarations.
55 */
56 #include "MagickCore/studio.h"
57 #include "MagickCore/blob.h"
58 #include "MagickCore/blob-private.h"
59 #include "MagickCore/exception.h"
60 #include "MagickCore/exception-private.h"
61 #include "MagickCore/memory_.h"
62 #include "MagickCore/memory-private.h"
63 #include "MagickCore/policy.h"
64 #include "MagickCore/resource_.h"
65 #include "MagickCore/semaphore.h"
66 #include "MagickCore/string_.h"
67 #include "MagickCore/string-private.h"
68 #include "MagickCore/utility-private.h"
69 \f
70 /*
71   Define declarations.
72 */
73 #define BlockFooter(block,size) \
74   ((size_t *) ((char *) (block)+(size)-2*sizeof(size_t)))
75 #define BlockHeader(block)  ((size_t *) (block)-1)
76 #define BlockSize  4096
77 #define BlockThreshold  1024
78 #define MaxBlockExponent  16
79 #define MaxBlocks ((BlockThreshold/(4*sizeof(size_t)))+MaxBlockExponent+1)
80 #define MaxSegments  1024
81 #define MemoryGuard  ((0xdeadbeef << 31)+0xdeafdeed)
82 #define NextBlock(block)  ((char *) (block)+SizeOfBlock(block))
83 #define NextBlockInList(block)  (*(void **) (block))
84 #define PreviousBlock(block)  ((char *) (block)-(*((size_t *) (block)-2)))
85 #define PreviousBlockBit  0x01
86 #define PreviousBlockInList(block)  (*((void **) (block)+1))
87 #define SegmentSize  (2*1024*1024)
88 #define SizeMask  (~0x01)
89 #define SizeOfBlock(block)  (*BlockHeader(block) & SizeMask)
90 \f
91 /*
92   Typedef declarations.
93 */
94 typedef enum
95 {
96   UndefinedVirtualMemory,
97   AlignedVirtualMemory,
98   MapVirtualMemory,
99   UnalignedVirtualMemory
100 } VirtualMemoryType;
101
102 typedef struct _DataSegmentInfo
103 {
104   void
105     *allocation,
106     *bound;
107
108   MagickBooleanType
109     mapped;
110
111   size_t
112     length;
113
114   struct _DataSegmentInfo
115     *previous,
116     *next;
117 } DataSegmentInfo;
118
119 typedef struct _MagickMemoryMethods
120 {
121   AcquireMemoryHandler
122     acquire_memory_handler;
123
124   ResizeMemoryHandler
125     resize_memory_handler;
126
127   DestroyMemoryHandler
128     destroy_memory_handler;
129 } MagickMemoryMethods;
130
131 struct _MemoryInfo
132 {
133   char
134     filename[MagickPathExtent];
135
136   VirtualMemoryType
137     type;
138
139   size_t
140     length;
141
142   void
143     *blob;
144
145   size_t
146     signature;
147 };
148
149 typedef struct _MemoryPool
150 {
151   size_t
152     allocation;
153
154   void
155     *blocks[MaxBlocks+1];
156
157   size_t
158     number_segments;
159
160   DataSegmentInfo
161     *segments[MaxSegments],
162     segment_pool[MaxSegments];
163 } MemoryPool;
164 \f
165 /*
166   Global declarations.
167 */
168 static size_t
169   max_memory_request = 0,
170   virtual_anonymous_memory = 0;
171
172 #if defined _MSC_VER
173 static void* MSCMalloc(size_t size)
174 {
175   return malloc(size);
176 }
177 static void* MSCRealloc(void* ptr, size_t size)
178 {
179   return realloc(ptr, size);
180 }
181 static void MSCFree(void* ptr)
182 {
183   free(ptr);
184 }
185 #endif
186
187 static MagickMemoryMethods
188   memory_methods =
189   {
190 #if defined _MSC_VER
191     (AcquireMemoryHandler) MSCMalloc,
192     (ResizeMemoryHandler) MSCRealloc,
193     (DestroyMemoryHandler) MSCFree
194 #else
195     (AcquireMemoryHandler) malloc,
196     (ResizeMemoryHandler) realloc,
197     (DestroyMemoryHandler) free
198 #endif
199   };
200 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
201 static MemoryPool
202   memory_pool;
203
204 static SemaphoreInfo
205   *memory_semaphore = (SemaphoreInfo *) NULL;
206
207 static volatile DataSegmentInfo
208   *free_segments = (DataSegmentInfo *) NULL;
209 \f
210 /*
211   Forward declarations.
212 */
213 static MagickBooleanType
214   ExpandHeap(size_t);
215 #endif
216 \f
217 /*
218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
219 %                                                                             %
220 %                                                                             %
221 %                                                                             %
222 %   A c q u i r e A l i g n e d M e m o r y                                   %
223 %                                                                             %
224 %                                                                             %
225 %                                                                             %
226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227 %
228 %  AcquireAlignedMemory() returns a pointer to a block of memory at least size
229 %  bytes whose address is aligned on a cache line or page boundary.
230 %
231 %  The format of the AcquireAlignedMemory method is:
232 %
233 %      void *AcquireAlignedMemory(const size_t count,const size_t quantum)
234 %
235 %  A description of each parameter follows:
236 %
237 %    o count: the number of quantum elements to allocate.
238 %
239 %    o quantum: the number of bytes in each quantum.
240 %
241 */
242 MagickExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
243 {
244 #define AlignedExtent(size,alignment) \
245   (((size)+((alignment)-1)) & ~((alignment)-1))
246
247   size_t
248     alignment,
249     extent,
250     size;
251
252   void
253     *memory;
254
255   if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
256     return((void *) NULL);
257   memory=NULL;
258   size=count*quantum;
259   alignment=CACHE_LINE_SIZE;
260   if (size > (size_t) (GetMagickPageSize() >> 1))
261     alignment=(size_t) GetMagickPageSize();
262   extent=AlignedExtent(size,CACHE_LINE_SIZE);
263   if ((size == 0) || (extent < size))
264     return((void *) NULL);
265 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
266   if (posix_memalign(&memory,alignment,extent) != 0)
267     memory=NULL;
268 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
269   memory=_aligned_malloc(extent,alignment);
270 #else
271   {
272     void
273       *p;
274
275     extent=(size+alignment-1)+sizeof(void *);
276     if (extent > size)
277       {
278         p=malloc(extent);
279         if (p != NULL)
280           {
281             memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
282             *((void **) memory-1)=p;
283           }
284       }
285   }
286 #endif
287   return(memory);
288 }
289 \f
290 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
291 /*
292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
293 %                                                                             %
294 %                                                                             %
295 %                                                                             %
296 +   A c q u i r e B l o c k                                                   %
297 %                                                                             %
298 %                                                                             %
299 %                                                                             %
300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
301 %
302 %  AcquireBlock() returns a pointer to a block of memory at least size bytes
303 %  suitably aligned for any use.
304 %
305 %  The format of the AcquireBlock method is:
306 %
307 %      void *AcquireBlock(const size_t size)
308 %
309 %  A description of each parameter follows:
310 %
311 %    o size: the size of the memory in bytes to allocate.
312 %
313 */
314
315 static inline size_t AllocationPolicy(size_t size)
316 {
317   register size_t
318     blocksize;
319
320   /*
321     The linear distribution.
322   */
323   assert(size != 0);
324   assert(size % (4*sizeof(size_t)) == 0);
325   if (size <= BlockThreshold)
326     return(size/(4*sizeof(size_t)));
327   /*
328     Check for the largest block size.
329   */
330   if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
331     return(MaxBlocks-1L);
332   /*
333     Otherwise use a power of two distribution.
334   */
335   blocksize=BlockThreshold/(4*sizeof(size_t));
336   for ( ; size > BlockThreshold; size/=2)
337     blocksize++;
338   assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
339   assert(blocksize < (MaxBlocks-1L));
340   return(blocksize);
341 }
342
343 static inline void InsertFreeBlock(void *block,const size_t i)
344 {
345   register void
346     *next,
347     *previous;
348
349   size_t
350     size;
351
352   size=SizeOfBlock(block);
353   previous=(void *) NULL;
354   next=memory_pool.blocks[i];
355   while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
356   {
357     previous=next;
358     next=NextBlockInList(next);
359   }
360   PreviousBlockInList(block)=previous;
361   NextBlockInList(block)=next;
362   if (previous != (void *) NULL)
363     NextBlockInList(previous)=block;
364   else
365     memory_pool.blocks[i]=block;
366   if (next != (void *) NULL)
367     PreviousBlockInList(next)=block;
368 }
369
370 static inline void RemoveFreeBlock(void *block,const size_t i)
371 {
372   register void
373     *next,
374     *previous;
375
376   next=NextBlockInList(block);
377   previous=PreviousBlockInList(block);
378   if (previous == (void *) NULL)
379     memory_pool.blocks[i]=next;
380   else
381     NextBlockInList(previous)=next;
382   if (next != (void *) NULL)
383     PreviousBlockInList(next)=previous;
384 }
385
386 static void *AcquireBlock(size_t size)
387 {
388   register size_t
389     i;
390
391   register void
392     *block;
393
394   /*
395     Find free block.
396   */
397   size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
398   i=AllocationPolicy(size);
399   block=memory_pool.blocks[i];
400   while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
401     block=NextBlockInList(block);
402   if (block == (void *) NULL)
403     {
404       i++;
405       while (memory_pool.blocks[i] == (void *) NULL)
406         i++;
407       block=memory_pool.blocks[i];
408       if (i >= MaxBlocks)
409         return((void *) NULL);
410     }
411   assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
412   assert(SizeOfBlock(block) >= size);
413   RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
414   if (SizeOfBlock(block) > size)
415     {
416       size_t
417         blocksize;
418
419       void
420         *next;
421
422       /*
423         Split block.
424       */
425       next=(char *) block+size;
426       blocksize=SizeOfBlock(block)-size;
427       *BlockHeader(next)=blocksize;
428       *BlockFooter(next,blocksize)=blocksize;
429       InsertFreeBlock(next,AllocationPolicy(blocksize));
430       *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
431     }
432   assert(size == SizeOfBlock(block));
433   *BlockHeader(NextBlock(block))|=PreviousBlockBit;
434   memory_pool.allocation+=size;
435   return(block);
436 }
437 #endif
438 \f
439 /*
440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
441 %                                                                             %
442 %                                                                             %
443 %                                                                             %
444 %   A c q u i r e M a g i c k M e m o r y                                     %
445 %                                                                             %
446 %                                                                             %
447 %                                                                             %
448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
449 %
450 %  AcquireMagickMemory() returns a pointer to a block of memory at least size
451 %  bytes suitably aligned for any use.
452 %
453 %  The format of the AcquireMagickMemory method is:
454 %
455 %      void *AcquireMagickMemory(const size_t size)
456 %
457 %  A description of each parameter follows:
458 %
459 %    o size: the size of the memory in bytes to allocate.
460 %
461 */
462 MagickExport void *AcquireMagickMemory(const size_t size)
463 {
464   register void
465     *memory;
466
467 #if !defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
468   memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
469 #else
470   if (memory_semaphore == (SemaphoreInfo *) NULL)
471     ActivateSemaphoreInfo(&memory_semaphore);
472   if (free_segments == (DataSegmentInfo *) NULL)
473     {
474       LockSemaphoreInfo(memory_semaphore);
475       if (free_segments == (DataSegmentInfo *) NULL)
476         {
477           register ssize_t
478             i;
479
480           assert(2*sizeof(size_t) > (size_t) (~SizeMask));
481           (void) memset(&memory_pool,0,sizeof(memory_pool));
482           memory_pool.allocation=SegmentSize;
483           memory_pool.blocks[MaxBlocks]=(void *) (-1);
484           for (i=0; i < MaxSegments; i++)
485           {
486             if (i != 0)
487               memory_pool.segment_pool[i].previous=
488                 (&memory_pool.segment_pool[i-1]);
489             if (i != (MaxSegments-1))
490               memory_pool.segment_pool[i].next=(&memory_pool.segment_pool[i+1]);
491           }
492           free_segments=(&memory_pool.segment_pool[0]);
493         }
494       UnlockSemaphoreInfo(memory_semaphore);
495     }
496   LockSemaphoreInfo(memory_semaphore);
497   memory=AcquireBlock(size == 0 ? 1UL : size);
498   if (memory == (void *) NULL)
499     {
500       if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
501         memory=AcquireBlock(size == 0 ? 1UL : size);
502     }
503   UnlockSemaphoreInfo(memory_semaphore);
504 #endif
505   return(memory);
506 }
507 \f
508 /*
509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
510 %                                                                             %
511 %                                                                             %
512 %                                                                             %
513 %   A c q u i r e Q u a n t u m M e m o r y                                   %
514 %                                                                             %
515 %                                                                             %
516 %                                                                             %
517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
518 %
519 %  AcquireQuantumMemory() returns a pointer to a block of memory at least
520 %  count * quantum bytes suitably aligned for any use.
521 %
522 %  The format of the AcquireQuantumMemory method is:
523 %
524 %      void *AcquireQuantumMemory(const size_t count,const size_t quantum)
525 %
526 %  A description of each parameter follows:
527 %
528 %    o count: the number of quantum elements to allocate.
529 %
530 %    o quantum: the number of bytes in each quantum.
531 %
532 */
533 MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
534 {
535   size_t
536     extent;
537
538   if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
539     return((void *) NULL);
540   extent=count*quantum;
541   return(AcquireMagickMemory(extent));
542 }
543 \f
544 /*
545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
546 %                                                                             %
547 %                                                                             %
548 %                                                                             %
549 %   A c q u i r e V i r t u a l M e m o r y                                   %
550 %                                                                             %
551 %                                                                             %
552 %                                                                             %
553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
554 %
555 %  AcquireVirtualMemory() allocates a pointer to a block of memory at least
556 %  size bytes suitably aligned for any use. In addition to heap, it also
557 %  supports memory-mapped and file-based memory-mapped memory requests.
558 %
559 %  The format of the AcquireVirtualMemory method is:
560 %
561 %      MemoryInfo *AcquireVirtualMemory(const size_t count,const size_t quantum)
562 %
563 %  A description of each parameter follows:
564 %
565 %    o count: the number of quantum elements to allocate.
566 %
567 %    o quantum: the number of bytes in each quantum.
568 %
569 */
570
571 MagickExport MemoryInfo *AcquireVirtualMemory(const size_t count,
572   const size_t quantum)
573 {
574   char
575     *value;
576
577   MemoryInfo
578     *memory_info;
579
580   size_t
581     extent;
582
583   if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
584     return((MemoryInfo *) NULL);
585   if (virtual_anonymous_memory == 0)
586     {
587       virtual_anonymous_memory=1;
588       value=GetPolicyValue("system:memory-map");
589       if (LocaleCompare(value,"anonymous") == 0)
590         {
591           /*
592             The security policy sets anonymous mapping for the memory request.
593           */
594 #if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
595           virtual_anonymous_memory=2;
596 #endif
597         }
598       value=DestroyString(value);
599     }
600   memory_info=(MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1,
601     sizeof(*memory_info)));
602   if (memory_info == (MemoryInfo *) NULL)
603     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
604   (void) memset(memory_info,0,sizeof(*memory_info));
605   extent=count*quantum;
606   memory_info->length=extent;
607   memory_info->signature=MagickCoreSignature;
608   if ((virtual_anonymous_memory == 1) &&
609       ((count*quantum) <= GetMaxMemoryRequest()))
610     {
611       memory_info->blob=AcquireAlignedMemory(1,extent);
612       if (memory_info->blob != NULL)
613         memory_info->type=AlignedVirtualMemory;
614     }
615   if (memory_info->blob == NULL)
616     {
617       /*
618         Acquire anonymous memory map.
619       */
620       memory_info->blob=NULL;
621       if ((count*quantum) <= GetMaxMemoryRequest())
622         memory_info->blob=MapBlob(-1,IOMode,0,extent);
623       if (memory_info->blob != NULL)
624         memory_info->type=MapVirtualMemory;
625       else
626         {
627           int
628             file;
629
630           /*
631             Anonymous memory mapping failed, try file-backed memory mapping.
632           */
633           file=AcquireUniqueFileResource(memory_info->filename);
634           if (file != -1)
635             {
636               MagickOffsetType
637                 offset;
638
639               offset=(MagickOffsetType) lseek(file,extent-1,SEEK_SET);
640               if ((offset == (MagickOffsetType) (extent-1)) &&
641                   (write(file,"",1) == 1))
642                 {
643                   memory_info->blob=MapBlob(file,IOMode,0,extent);
644                   if (memory_info->blob != NULL)
645                     memory_info->type=MapVirtualMemory;
646                   else
647                     {
648                       (void) RelinquishUniqueFileResource(
649                         memory_info->filename);
650                       *memory_info->filename='\0';
651                     }
652                 }
653               (void) close(file);
654             }
655         }
656     }
657   if (memory_info->blob == NULL)
658     {
659       memory_info->blob=AcquireQuantumMemory(1,extent);
660       if (memory_info->blob != NULL)
661         memory_info->type=UnalignedVirtualMemory;
662     }
663   if (memory_info->blob == NULL)
664     memory_info=RelinquishVirtualMemory(memory_info);
665   return(memory_info);
666 }
667 \f
668 /*
669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670 %                                                                             %
671 %                                                                             %
672 %                                                                             %
673 %   C o p y M a g i c k M e m o r y                                           %
674 %                                                                             %
675 %                                                                             %
676 %                                                                             %
677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
678 %
679 %  CopyMagickMemory() copies size bytes from memory area source to the
680 %  destination.  Copying between objects that overlap will take place
681 %  correctly.  It returns destination.
682 %
683 %  The format of the CopyMagickMemory method is:
684 %
685 %      void *CopyMagickMemory(void *destination,const void *source,
686 %        const size_t size)
687 %
688 %  A description of each parameter follows:
689 %
690 %    o destination: the destination.
691 %
692 %    o source: the source.
693 %
694 %    o size: the size of the memory in bytes to allocate.
695 %
696 */
697 MagickExport void *CopyMagickMemory(void *destination,const void *source,
698   const size_t size)
699 {
700   register const unsigned char
701     *p;
702
703   register unsigned char
704     *q;
705
706   assert(destination != (void *) NULL);
707   assert(source != (const void *) NULL);
708   p=(const unsigned char *) source;
709   q=(unsigned char *) destination;
710   if (((q+size) < p) || (q > (p+size)))
711     switch (size)
712     {
713       default: return(memcpy(destination,source,size));
714       case 8: *q++=(*p++);
715       case 7: *q++=(*p++);
716       case 6: *q++=(*p++);
717       case 5: *q++=(*p++);
718       case 4: *q++=(*p++);
719       case 3: *q++=(*p++);
720       case 2: *q++=(*p++);
721       case 1: *q++=(*p++);
722       case 0: return(destination);
723     }
724   return(memmove(destination,source,size));
725 }
726 \f
727 /*
728 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
729 %                                                                             %
730 %                                                                             %
731 %                                                                             %
732 +   D e s t r o y M a g i c k M e m o r y                                     %
733 %                                                                             %
734 %                                                                             %
735 %                                                                             %
736 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
737 %
738 %  DestroyMagickMemory() deallocates memory associated with the memory manager.
739 %
740 %  The format of the DestroyMagickMemory method is:
741 %
742 %      DestroyMagickMemory(void)
743 %
744 */
745 MagickExport void DestroyMagickMemory(void)
746 {
747 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
748   register ssize_t
749     i;
750
751   if (memory_semaphore == (SemaphoreInfo *) NULL)
752     ActivateSemaphoreInfo(&memory_semaphore);
753   LockSemaphoreInfo(memory_semaphore);
754   for (i=0; i < (ssize_t) memory_pool.number_segments; i++)
755     if (memory_pool.segments[i]->mapped == MagickFalse)
756       memory_methods.destroy_memory_handler(
757         memory_pool.segments[i]->allocation);
758     else
759       (void) UnmapBlob(memory_pool.segments[i]->allocation,
760         memory_pool.segments[i]->length);
761   free_segments=(DataSegmentInfo *) NULL;
762   (void) memset(&memory_pool,0,sizeof(memory_pool));
763   UnlockSemaphoreInfo(memory_semaphore);
764   RelinquishSemaphoreInfo(&memory_semaphore);
765 #endif
766 }
767 \f
768 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
769 /*
770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
771 %                                                                             %
772 %                                                                             %
773 %                                                                             %
774 +   E x p a n d H e a p                                                       %
775 %                                                                             %
776 %                                                                             %
777 %                                                                             %
778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
779 %
780 %  ExpandHeap() get more memory from the system.  It returns MagickTrue on
781 %  success otherwise MagickFalse.
782 %
783 %  The format of the ExpandHeap method is:
784 %
785 %      MagickBooleanType ExpandHeap(size_t size)
786 %
787 %  A description of each parameter follows:
788 %
789 %    o size: the size of the memory in bytes we require.
790 %
791 */
792 static MagickBooleanType ExpandHeap(size_t size)
793 {
794   DataSegmentInfo
795     *segment_info;
796
797   MagickBooleanType
798     mapped;
799
800   register ssize_t
801     i;
802
803   register void
804     *block;
805
806   size_t
807     blocksize;
808
809   void
810     *segment;
811
812   blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
813   assert(memory_pool.number_segments < MaxSegments);
814   segment=MapBlob(-1,IOMode,0,blocksize);
815   mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
816   if (segment == (void *) NULL)
817     segment=(void *) memory_methods.acquire_memory_handler(blocksize);
818   if (segment == (void *) NULL)
819     return(MagickFalse);
820   segment_info=(DataSegmentInfo *) free_segments;
821   free_segments=segment_info->next;
822   segment_info->mapped=mapped;
823   segment_info->length=blocksize;
824   segment_info->allocation=segment;
825   segment_info->bound=(char *) segment+blocksize;
826   i=(ssize_t) memory_pool.number_segments-1;
827   for ( ; (i >= 0) && (memory_pool.segments[i]->allocation > segment); i--)
828     memory_pool.segments[i+1]=memory_pool.segments[i];
829   memory_pool.segments[i+1]=segment_info;
830   memory_pool.number_segments++;
831   size=blocksize-12*sizeof(size_t);
832   block=(char *) segment_info->allocation+4*sizeof(size_t);
833   *BlockHeader(block)=size | PreviousBlockBit;
834   *BlockFooter(block,size)=size;
835   InsertFreeBlock(block,AllocationPolicy(size));
836   block=NextBlock(block);
837   assert(block < segment_info->bound);
838   *BlockHeader(block)=2*sizeof(size_t);
839   *BlockHeader(NextBlock(block))=PreviousBlockBit;
840   return(MagickTrue);
841 }
842 #endif
843 \f
844 /*
845 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
846 %                                                                             %
847 %                                                                             %
848 %                                                                             %
849 %   G e t M a g i c k M e m o r y M e t h o d s                               %
850 %                                                                             %
851 %                                                                             %
852 %                                                                             %
853 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
854 %
855 %  GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
856 %  memory.
857 %
858 %  The format of the GetMagickMemoryMethods() method is:
859 %
860 %      void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
861 %        ResizeMemoryHandler *resize_memory_handler,
862 %        DestroyMemoryHandler *destroy_memory_handler)
863 %
864 %  A description of each parameter follows:
865 %
866 %    o acquire_memory_handler: method to acquire memory (e.g. malloc).
867 %
868 %    o resize_memory_handler: method to resize memory (e.g. realloc).
869 %
870 %    o destroy_memory_handler: method to destroy memory (e.g. free).
871 %
872 */
873 MagickExport void GetMagickMemoryMethods(
874   AcquireMemoryHandler *acquire_memory_handler,
875   ResizeMemoryHandler *resize_memory_handler,
876   DestroyMemoryHandler *destroy_memory_handler)
877 {
878   assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
879   assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
880   assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
881   *acquire_memory_handler=memory_methods.acquire_memory_handler;
882   *resize_memory_handler=memory_methods.resize_memory_handler;
883   *destroy_memory_handler=memory_methods.destroy_memory_handler;
884 }
885 \f
886 /*
887 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
888 %                                                                             %
889 %                                                                             %
890 %                                                                             %
891 +   G e t M a x M e m o r y R e q u e s t                                     %
892 %                                                                             %
893 %                                                                             %
894 %                                                                             %
895 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
896 %
897 %  GetMaxMemoryRequest() returns the max_memory_request value.
898 %
899 %  The format of the GetMaxMemoryRequest method is:
900 %
901 %      size_t GetMaxMemoryRequest(void)
902 %
903 */
904 MagickExport size_t GetMaxMemoryRequest(void)
905 {
906   if (max_memory_request == 0)
907     {
908       char
909         *value;
910
911       max_memory_request=(size_t) MagickULLConstant(~0);
912       value=GetPolicyValue("system:max-memory-request");
913       if (value != (char *) NULL)
914         {
915           /*
916             The security policy sets a max memory request limit.
917           */
918           max_memory_request=StringToSizeType(value,100.0);
919           value=DestroyString(value);
920         }
921     }
922   return(max_memory_request);
923 }
924 \f
925 /*
926 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
927 %                                                                             %
928 %                                                                             %
929 %                                                                             %
930 %   G e t V i r t u a l M e m o r y B l o b                                   %
931 %                                                                             %
932 %                                                                             %
933 %                                                                             %
934 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
935 %
936 %  GetVirtualMemoryBlob() returns the virtual memory blob associated with the
937 %  specified MemoryInfo structure.
938 %
939 %  The format of the GetVirtualMemoryBlob method is:
940 %
941 %      void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
942 %
943 %  A description of each parameter follows:
944 %
945 %    o memory_info: The MemoryInfo structure.
946 */
947 MagickExport void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
948 {
949   assert(memory_info != (const MemoryInfo *) NULL);
950   assert(memory_info->signature == MagickCoreSignature);
951   return(memory_info->blob);
952 }
953 \f
954 /*
955 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
956 %                                                                             %
957 %                                                                             %
958 %                                                                             %
959 +   H e a p O v e r f l o w S a n i t y C h e c k                             %
960 %                                                                             %
961 %                                                                             %
962 %                                                                             %
963 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
964 %
965 %  HeapOverflowSanityCheck() returns MagickTrue if the heap allocation request
966 %  does not exceed the maximum limits of a size_t otherwise MagickFalse.
967 %
968 %  The format of the HeapOverflowSanityCheck method is:
969 %
970 %      MagickBooleanType HeapOverflowSanityCheck(const size_t count,
971 %        const size_t quantum)
972 %
973 %  A description of each parameter follows:
974 %
975 %    o size: the size of the memory in bytes we require.
976 %
977 */
978 MagickExport MagickBooleanType HeapOverflowSanityCheck(const size_t count,
979   const size_t quantum)
980 {
981   size_t
982     size;
983
984   size=count*quantum;
985   if ((count == 0) || (quantum != (size/count)))
986     {
987       errno=ENOMEM;
988       return(MagickTrue);
989     }
990   return(MagickFalse);
991 }
992 \f
993 /*
994 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
995 %                                                                             %
996 %                                                                             %
997 %                                                                             %
998 %   R e l i n q u i s h A l i g n e d M e m o r y                             %
999 %                                                                             %
1000 %                                                                             %
1001 %                                                                             %
1002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1003 %
1004 %  RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
1005 %  or reuse.
1006 %
1007 %  The format of the RelinquishAlignedMemory method is:
1008 %
1009 %      void *RelinquishAlignedMemory(void *memory)
1010 %
1011 %  A description of each parameter follows:
1012 %
1013 %    o memory: A pointer to a block of memory to free for reuse.
1014 %
1015 */
1016 MagickExport void *RelinquishAlignedMemory(void *memory)
1017 {
1018   if (memory == (void *) NULL)
1019     return((void *) NULL);
1020 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
1021   free(memory);
1022 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
1023   _aligned_free(memory);
1024 #else
1025   free(*((void **) memory-1));
1026 #endif
1027   return(NULL);
1028 }
1029 \f
1030 /*
1031 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1032 %                                                                             %
1033 %                                                                             %
1034 %                                                                             %
1035 %   R e l i n q u i s h M a g i c k M e m o r y                               %
1036 %                                                                             %
1037 %                                                                             %
1038 %                                                                             %
1039 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1040 %
1041 %  RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
1042 %  or AcquireQuantumMemory() for reuse.
1043 %
1044 %  The format of the RelinquishMagickMemory method is:
1045 %
1046 %      void *RelinquishMagickMemory(void *memory)
1047 %
1048 %  A description of each parameter follows:
1049 %
1050 %    o memory: A pointer to a block of memory to free for reuse.
1051 %
1052 */
1053 MagickExport void *RelinquishMagickMemory(void *memory)
1054 {
1055   if (memory == (void *) NULL)
1056     return((void *) NULL);
1057 #if !defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1058   memory_methods.destroy_memory_handler(memory);
1059 #else
1060   LockSemaphoreInfo(memory_semaphore);
1061   assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
1062   assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
1063   if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
1064     {
1065       void
1066         *previous;
1067
1068       /*
1069         Coalesce with previous adjacent block.
1070       */
1071       previous=PreviousBlock(memory);
1072       RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
1073       *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
1074         (*BlockHeader(previous) & ~SizeMask);
1075       memory=previous;
1076     }
1077   if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
1078     {
1079       void
1080         *next;
1081
1082       /*
1083         Coalesce with next adjacent block.
1084       */
1085       next=NextBlock(memory);
1086       RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
1087       *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
1088         (*BlockHeader(memory) & ~SizeMask);
1089     }
1090   *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
1091   *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
1092   InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
1093   UnlockSemaphoreInfo(memory_semaphore);
1094 #endif
1095   return((void *) NULL);
1096 }
1097 \f
1098 /*
1099 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1100 %                                                                             %
1101 %                                                                             %
1102 %                                                                             %
1103 %   R e l i n q u i s h V i r t u a l M e m o r y                             %
1104 %                                                                             %
1105 %                                                                             %
1106 %                                                                             %
1107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1108 %
1109 %  RelinquishVirtualMemory() frees memory acquired with AcquireVirtualMemory().
1110 %
1111 %  The format of the RelinquishVirtualMemory method is:
1112 %
1113 %      MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
1114 %
1115 %  A description of each parameter follows:
1116 %
1117 %    o memory_info: A pointer to a block of memory to free for reuse.
1118 %
1119 */
1120 MagickExport MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
1121 {
1122   assert(memory_info != (MemoryInfo *) NULL);
1123   assert(memory_info->signature == MagickCoreSignature);
1124   if (memory_info->blob != (void *) NULL)
1125     switch (memory_info->type)
1126     {
1127       case AlignedVirtualMemory:
1128       {
1129         memory_info->blob=RelinquishAlignedMemory(memory_info->blob);
1130         break;
1131       }
1132       case MapVirtualMemory:
1133       {
1134         (void) UnmapBlob(memory_info->blob,memory_info->length);
1135         memory_info->blob=NULL;
1136         if (*memory_info->filename != '\0')
1137           (void) RelinquishUniqueFileResource(memory_info->filename);
1138         break;
1139       }
1140       case UnalignedVirtualMemory:
1141       default:
1142       {
1143         memory_info->blob=RelinquishMagickMemory(memory_info->blob);
1144         break;
1145       }
1146     }
1147   memory_info->signature=(~MagickCoreSignature);
1148   memory_info=(MemoryInfo *) RelinquishAlignedMemory(memory_info);
1149   return(memory_info);
1150 }
1151 \f
1152 /*
1153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1154 %                                                                             %
1155 %                                                                             %
1156 %                                                                             %
1157 %   R e s e t M a g i c k M e m o r y                                         %
1158 %                                                                             %
1159 %                                                                             %
1160 %                                                                             %
1161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1162 %
1163 %  ResetMagickMemory() fills the first size bytes of the memory area pointed to
1164 %  by memory with the constant byte c.
1165 %
1166 %  The format of the ResetMagickMemory method is:
1167 %
1168 %      void *ResetMagickMemory(void *memory,int byte,const size_t size)
1169 %
1170 %  A description of each parameter follows:
1171 %
1172 %    o memory: a pointer to a memory allocation.
1173 %
1174 %    o byte: set the memory to this value.
1175 %
1176 %    o size: size of the memory to reset.
1177 %
1178 */
1179 MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
1180 {
1181   assert(memory != (void *) NULL);
1182   return(memset(memory,byte,size));
1183 }
1184 \f
1185 /*
1186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1187 %                                                                             %
1188 %                                                                             %
1189 %                                                                             %
1190 +   R e s e t M a x M e m o r y R e q u e s t                                 %
1191 %                                                                             %
1192 %                                                                             %
1193 %                                                                             %
1194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1195 %
1196 %  ResetMaxMemoryRequest() resets the max_memory_request value.
1197 %
1198 %  The format of the ResetMaxMemoryRequest method is:
1199 %
1200 %      void ResetMaxMemoryRequest(void)
1201 %
1202 */
1203 MagickPrivate void ResetMaxMemoryRequest(void)
1204 {
1205   max_memory_request=0;
1206 }
1207 \f
1208 /*
1209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1210 %                                                                             %
1211 %                                                                             %
1212 %                                                                             %
1213 +   R e s e t V i r t u a l A n o n y m o u s M e m o r y                     %
1214 %                                                                             %
1215 %                                                                             %
1216 %                                                                             %
1217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1218 %
1219 %  ResetVirtualAnonymousMemory() resets the virtual_anonymous_memory value.
1220 %
1221 %  The format of the ResetVirtualAnonymousMemory method is:
1222 %
1223 %      void ResetVirtualAnonymousMemory(void)
1224 %
1225 */
1226 MagickPrivate void ResetVirtualAnonymousMemory(void)
1227 {
1228   virtual_anonymous_memory=0;
1229 }
1230 \f
1231 /*
1232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1233 %                                                                             %
1234 %                                                                             %
1235 %                                                                             %
1236 %   R e s i z e M a g i c k M e m o r y                                       %
1237 %                                                                             %
1238 %                                                                             %
1239 %                                                                             %
1240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1241 %
1242 %  ResizeMagickMemory() changes the size of the memory and returns a pointer to
1243 %  the (possibly moved) block.  The contents will be unchanged up to the
1244 %  lesser of the new and old sizes.
1245 %
1246 %  The format of the ResizeMagickMemory method is:
1247 %
1248 %      void *ResizeMagickMemory(void *memory,const size_t size)
1249 %
1250 %  A description of each parameter follows:
1251 %
1252 %    o memory: A pointer to a memory allocation.
1253 %
1254 %    o size: the new size of the allocated memory.
1255 %
1256 */
1257
1258 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1259 static inline void *ResizeBlock(void *block,size_t size)
1260 {
1261   register void
1262     *memory;
1263
1264   if (block == (void *) NULL)
1265     return(AcquireBlock(size));
1266   memory=AcquireBlock(size);
1267   if (memory == (void *) NULL)
1268     return((void *) NULL);
1269   if (size <= (SizeOfBlock(block)-sizeof(size_t)))
1270     (void) memcpy(memory,block,size);
1271   else
1272     (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
1273   memory_pool.allocation+=size;
1274   return(memory);
1275 }
1276 #endif
1277
1278 MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
1279 {
1280   register void
1281     *block;
1282
1283   if (memory == (void *) NULL)
1284     return(AcquireMagickMemory(size));
1285 #if !defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1286   block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
1287   if (block == (void *) NULL)
1288     memory=RelinquishMagickMemory(memory);
1289 #else
1290   LockSemaphoreInfo(memory_semaphore);
1291   block=ResizeBlock(memory,size == 0 ? 1UL : size);
1292   if (block == (void *) NULL)
1293     {
1294       if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
1295         {
1296           UnlockSemaphoreInfo(memory_semaphore);
1297           memory=RelinquishMagickMemory(memory);
1298           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1299         }
1300       block=ResizeBlock(memory,size == 0 ? 1UL : size);
1301       assert(block != (void *) NULL);
1302     }
1303   UnlockSemaphoreInfo(memory_semaphore);
1304   memory=RelinquishMagickMemory(memory);
1305 #endif
1306   return(block);
1307 }
1308 \f
1309 /*
1310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1311 %                                                                             %
1312 %                                                                             %
1313 %                                                                             %
1314 %   R e s i z e Q u a n t u m M e m o r y                                     %
1315 %                                                                             %
1316 %                                                                             %
1317 %                                                                             %
1318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1319 %
1320 %  ResizeQuantumMemory() changes the size of the memory and returns a pointer
1321 %  to the (possibly moved) block.  The contents will be unchanged up to the
1322 %  lesser of the new and old sizes.
1323 %
1324 %  The format of the ResizeQuantumMemory method is:
1325 %
1326 %      void *ResizeQuantumMemory(void *memory,const size_t count,
1327 %        const size_t quantum)
1328 %
1329 %  A description of each parameter follows:
1330 %
1331 %    o memory: A pointer to a memory allocation.
1332 %
1333 %    o count: the number of quantum elements to allocate.
1334 %
1335 %    o quantum: the number of bytes in each quantum.
1336 %
1337 */
1338 MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
1339   const size_t quantum)
1340 {
1341   size_t
1342     extent;
1343
1344   if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
1345     {
1346       memory=RelinquishMagickMemory(memory);
1347       return((void *) NULL);
1348     }
1349   extent=count*quantum;
1350   return(ResizeMagickMemory(memory,extent));
1351 }
1352 \f
1353 /*
1354 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1355 %                                                                             %
1356 %                                                                             %
1357 %                                                                             %
1358 %   S e t M a g i c k M e m o r y M e t h o d s                               %
1359 %                                                                             %
1360 %                                                                             %
1361 %                                                                             %
1362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1363 %
1364 %  SetMagickMemoryMethods() sets the methods to acquire, resize, and destroy
1365 %  memory. Your custom memory methods must be set prior to the
1366 %  MagickCoreGenesis() method.
1367 %
1368 %  The format of the SetMagickMemoryMethods() method is:
1369 %
1370 %      SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
1371 %        ResizeMemoryHandler resize_memory_handler,
1372 %        DestroyMemoryHandler destroy_memory_handler)
1373 %
1374 %  A description of each parameter follows:
1375 %
1376 %    o acquire_memory_handler: method to acquire memory (e.g. malloc).
1377 %
1378 %    o resize_memory_handler: method to resize memory (e.g. realloc).
1379 %
1380 %    o destroy_memory_handler: method to destroy memory (e.g. free).
1381 %
1382 */
1383 MagickExport void SetMagickMemoryMethods(
1384   AcquireMemoryHandler acquire_memory_handler,
1385   ResizeMemoryHandler resize_memory_handler,
1386   DestroyMemoryHandler destroy_memory_handler)
1387 {
1388   /*
1389     Set memory methods.
1390   */
1391   if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
1392     memory_methods.acquire_memory_handler=acquire_memory_handler;
1393   if (resize_memory_handler != (ResizeMemoryHandler) NULL)
1394     memory_methods.resize_memory_handler=resize_memory_handler;
1395   if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
1396     memory_methods.destroy_memory_handler=destroy_memory_handler;
1397 }