#include "MagickCore/resource_.h"
#include "MagickCore/semaphore.h"
#include "MagickCore/string_.h"
+#include "MagickCore/string-private.h"
#include "MagickCore/utility-private.h"
\f
/*
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% AcquireVirtualMemory() allocates a pointer to a block of memory at least size
-% bytes suitably aligned for any use.
+% AcquireVirtualMemory() allocates a pointer to a block of memory at least
+% size bytes suitably aligned for any use. In addition to heap, it also
+% supports memory-mapped and file-based memory-mapped memory requests.
%
% The format of the AcquireVirtualMemory method is:
%
% o quantum: the number of bytes in each quantum.
%
*/
+
+static inline size_t StringToSizeType(const char *string,const double interval)
+{
+ double
+ value;
+
+ value=SiPrefixToDoubleInterval(string,interval);
+ if (value >= (double) MagickULLConstant(~0))
+ return((size_t) MagickULLConstant(~0));
+ return((size_t) value);
+}
+
MagickExport MemoryInfo *AcquireVirtualMemory(const size_t count,
const size_t quantum)
{
+ char
+ *value;
+
MemoryInfo
*memory_info;
size_t
extent;
- static ssize_t
- virtual_anonymous_memory = (-1);
+ static size_t
+ max_memory_request = 0,
+ virtual_anonymous_memory = 0;
if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
return((MemoryInfo *) NULL);
- memory_info=(MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1,
- sizeof(*memory_info)));
- if (memory_info == (MemoryInfo *) NULL)
- ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
- (void) ResetMagickMemory(memory_info,0,sizeof(*memory_info));
- extent=count*quantum;
- memory_info->length=extent;
- memory_info->signature=MagickCoreSignature;
- if (virtual_anonymous_memory < 0)
+ if (max_memory_request == 0)
{
- char
- *value;
-
- /*
- Does the security policy require anonymous mapping for pixel cache?
- */
- virtual_anonymous_memory=0;
+ max_memory_request=(size_t) MagickULLConstant(~0);
+ value=GetPolicyValue("system:max-memory-request");
+ if (value != (char *) NULL)
+ {
+ /*
+ The security policy sets a max memory request limit.
+ */
+ max_memory_request=StringToSizeType(value,100.0);
+ value=DestroyString(value);
+ }
+ }
+ if ((count*quantum) > (size_t) max_memory_request)
+ return((MemoryInfo *) NULL);
+ if (virtual_anonymous_memory == 0)
+ {
+ virtual_anonymous_memory=1;
value=GetPolicyValue("system:memory-map");
if (LocaleCompare(value,"anonymous") == 0)
{
+ /*
+ The security policy sets anonymous mapping for the memory request.
+ */
#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
- virtual_anonymous_memory=1;
+ virtual_anonymous_memory=2;
#endif
}
value=DestroyString(value);
}
- if (virtual_anonymous_memory <= 0)
+ memory_info=(MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1,
+ sizeof(*memory_info)));
+ if (memory_info == (MemoryInfo *) NULL)
+ ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
+ (void) ResetMagickMemory(memory_info,0,sizeof(*memory_info));
+ extent=count*quantum;
+ memory_info->length=extent;
+ memory_info->signature=MagickCoreSignature;
+ if (virtual_anonymous_memory == 1)
{
- if (AcquireMagickResource(MemoryResource,extent) != MagickFalse)
- {
- memory_info->blob=AcquireAlignedMemory(1,extent);
- if (memory_info->blob != NULL)
- {
- memory_info->type=AlignedVirtualMemory;
- return(memory_info);
- }
- }
- RelinquishMagickResource(MemoryResource,extent);
+ memory_info->blob=AcquireAlignedMemory(1,extent);
+ if (memory_info->blob != NULL)
+ memory_info->type=AlignedVirtualMemory;
}
else
{
- if (AcquireMagickResource(MapResource,extent) != MagickFalse)
+ /*
+ Acquire anonymous memory map.
+ */
+ memory_info->blob=MapBlob(-1,IOMode,0,extent);
+ if (memory_info->blob != NULL)
+ memory_info->type=MapVirtualMemory;
+ else
{
+ int
+ file;
+
/*
- Acquire anonymous memory map.
+ Anonymous memory mapping failed, try file-backed memory mapping.
*/
- memory_info->blob=MapBlob(-1,IOMode,0,extent);
- if (memory_info->blob != NULL)
- {
- memory_info->type=MapVirtualMemory;
- return(memory_info);
- }
- if (AcquireMagickResource(DiskResource,extent) != MagickFalse)
+ file=AcquireUniqueFileResource(memory_info->filename);
+ if (file != -1)
{
- int
- file;
-
- /*
- Anonymous memory mapping failed, try file-backed memory mapping.
- If the MapResource request failed, there is no point in trying
- file-backed memory mapping.
- */
- file=AcquireUniqueFileResource(memory_info->filename);
- if (file != -1)
- {
- MagickOffsetType
- offset;
+ MagickOffsetType
+ offset;
- offset=(MagickOffsetType) lseek(file,extent-1,SEEK_SET);
- if ((offset == (MagickOffsetType) (extent-1)) &&
- (write(file,"",1) == 1))
+ offset=(MagickOffsetType) lseek(file,extent-1,SEEK_SET);
+ (void) close(file);
+ if ((offset == (MagickOffsetType) (extent-1)) &&
+ (write(file,"",1) == 1))
+ {
+ memory_info->blob=MapBlob(file,IOMode,0,extent);
+ if (memory_info->blob != NULL)
+ memory_info->type=MapVirtualMemory;
+ else
{
- memory_info->blob=MapBlob(file,IOMode,0,extent);
- if (memory_info->blob != NULL)
- {
- (void) close(file);
- memory_info->type=MapVirtualMemory;
- return(memory_info);
- }
+ (void) RelinquishUniqueFileResource(
+ memory_info->filename);
+ *memory_info->filename='\0';
}
- /*
- File-backed memory mapping fail, delete the temporary file.
- */
- (void) close(file);
- (void) RelinquishUniqueFileResource(memory_info->filename);
- *memory_info->filename = '\0';
}
}
- RelinquishMagickResource(DiskResource,extent);
}
- RelinquishMagickResource(MapResource,extent);
- }
- if (memory_info->blob == NULL)
- {
- memory_info->blob=AcquireMagickMemory(extent);
- if (memory_info->blob != NULL)
- memory_info->type=UnalignedVirtualMemory;
}
if (memory_info->blob == NULL)
memory_info=RelinquishVirtualMemory(memory_info);