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