| diff --git a/third_party/lcms/src/cmserr.c b/third_party/lcms/src/cmserr.c | 
 | index 700152ee3..3c3848b2a 100644 | 
 | --- a/third_party/lcms/src/cmserr.c | 
 | +++ b/third_party/lcms/src/cmserr.c | 
 | @@ -25,6 +25,8 @@ | 
 |   | 
 |  #include "lcms2_internal.h" | 
 |   | 
 | +#include "core/fxcrt/fx_memory.h" | 
 | +#include "core/fxcrt/fx_system.h" | 
 |   | 
 |  // This function is here to help applications to prevent mixing lcms versions on header and shared objects. | 
 |  int CMSEXPORT cmsGetEncodedCMMversion(void) | 
 | @@ -67,140 +67,75 @@ long int CMSEXPORT cmsfilelength(FILE* f) | 
 |      return n; | 
 |  } | 
 |   | 
 | - | 
 | -// Memory handling ------------------------------------------------------------------ | 
 | -// | 
 | -// This is the interface to low-level memory management routines. By default a simple | 
 | -// wrapping to malloc/free/realloc is provided, although there is a limit on the max | 
 | -// amount of memoy that can be reclaimed. This is mostly as a safety feature to prevent  | 
 | -// bogus or evil code to allocate huge blocks that otherwise lcms would never need. | 
 | - | 
 | -#define MAX_MEMORY_FOR_ALLOC  ((cmsUInt32Number)(1024U*1024U*512U)) | 
 | - | 
 | -// User may override this behaviour by using a memory plug-in, which basically replaces | 
 | -// the default memory management functions. In this case, no check is performed and it | 
 | -// is up to the plug-in writter to keep in the safe side. There are only three functions | 
 | -// required to be implemented: malloc, realloc and free, although the user may want to | 
 | -// replace the optional mallocZero, calloc and dup as well. | 
 | - | 
 | -cmsBool   _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin); | 
 | - | 
 | -// ********************************************************************************* | 
 | - | 
 | -// This is the default memory allocation function. It does a very coarse | 
 | -// check of amount of memory, just to prevent exploits | 
 | -static | 
 | -void* _cmsMallocDefaultFn(cmsContext ContextID, cmsUInt32Number size) | 
 | +cmsBool  _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin) | 
 |  { | 
 | -    if (size > MAX_MEMORY_FOR_ALLOC) return NULL;  // Never allow over maximum | 
 | - | 
 | -    return (void*) malloc(size); | 
 | +    return TRUE; | 
 | +} | 
 |   | 
 | -    cmsUNUSED_PARAMETER(ContextID); | 
 | +// Generic allocate | 
 | +void* CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size) | 
 | +{ | 
 | +    return FXMEM_DefaultAlloc(size); | 
 |  } | 
 |   | 
 |  // Generic allocate & zero | 
 | -static | 
 | -void* _cmsMallocZeroDefaultFn(cmsContext ContextID, cmsUInt32Number size) | 
 | +void* CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size) | 
 |  { | 
 | -    void *pt = _cmsMalloc(ContextID, size); | 
 | -    if (pt == NULL) return NULL; | 
 | - | 
 | -    memset(pt, 0, size); | 
 | -    return pt; | 
 | +    void* p = FXMEM_DefaultAlloc(size); | 
 | +    if (p) memset(p, 0, size); | 
 | +    return p; | 
 |  } | 
 |   | 
 | - | 
 | -// The default free function. The only check proformed is against NULL pointers | 
 | -static | 
 | -void _cmsFreeDefaultFn(cmsContext ContextID, void *Ptr) | 
 | +// Generic calloc | 
 | +void* CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size) | 
 |  { | 
 | -    // free(NULL) is defined a no-op by C99, therefore it is safe to | 
 | -    // avoid the check, but it is here just in case... | 
 | - | 
 | -    if (Ptr) free(Ptr); | 
 | +    cmsUInt32Number total = num * size; | 
 | +    if (total == 0 || total / size != num || total >= 512 * 1024 * 1024) | 
 | +        return NULL; | 
 |   | 
 | -    cmsUNUSED_PARAMETER(ContextID); | 
 | +    return _cmsMallocZero(ContextID, num * size); | 
 |  } | 
 |   | 
 | -// The default realloc function. Again it checks for exploits. If Ptr is NULL, | 
 | -// realloc behaves the same way as malloc and allocates a new block of size bytes. | 
 | -static | 
 | -void* _cmsReallocDefaultFn(cmsContext ContextID, void* Ptr, cmsUInt32Number size) | 
 | +// Generic reallocate | 
 | +void* CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number size) | 
 |  { | 
 | - | 
 | -    if (size > MAX_MEMORY_FOR_ALLOC) return NULL;  // Never realloc over 512Mb | 
 | - | 
 | -    return realloc(Ptr, size); | 
 | - | 
 | -    cmsUNUSED_PARAMETER(ContextID); | 
 | +    return FXMEM_DefaultRealloc(Ptr, size); | 
 |  } | 
 |   | 
 | - | 
 | -// The default calloc function. Allocates an array of num elements, each one of size bytes | 
 | -// all memory is initialized to zero. | 
 | -static | 
 | -void* _cmsCallocDefaultFn(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size) | 
 | +// Generic free memory | 
 | +void CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr) | 
 |  { | 
 | -    cmsUInt32Number Total = num * size; | 
 | - | 
 | -    // Preserve calloc behaviour | 
 | -    if (Total == 0) return NULL; | 
 | - | 
 | -    // Safe check for overflow. | 
 | -    if (num >= UINT_MAX / size) return NULL; | 
 | - | 
 | -    // Check for overflow | 
 | -    if (Total < num || Total < size) { | 
 | -        return NULL; | 
 | -    } | 
 | - | 
 | -    if (Total > MAX_MEMORY_FOR_ALLOC) return NULL;  // Never alloc over 512Mb | 
 | - | 
 | -    return _cmsMallocZero(ContextID, Total); | 
 | +    if (Ptr != NULL) FXMEM_DefaultFree(Ptr); | 
 |  } | 
 |   | 
 |  // Generic block duplication | 
 | -static | 
 | -void* _cmsDupDefaultFn(cmsContext ContextID, const void* Org, cmsUInt32Number size) | 
 | +void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size) | 
 |  { | 
 | -    void* mem; | 
 | - | 
 | -    if (size > MAX_MEMORY_FOR_ALLOC) return NULL;  // Never dup over 512Mb | 
 | - | 
 | -    mem = _cmsMalloc(ContextID, size); | 
 | - | 
 | -    if (mem != NULL && Org != NULL) | 
 | -        memmove(mem, Org, size); | 
 | - | 
 | -    return mem; | 
 | +    void* p = FXMEM_DefaultAlloc(size); | 
 | +    memmove(p, Org, size); | 
 | +    return p; | 
 |  } | 
 |   | 
 | - | 
 | -// Pointers to memory manager functions in Context0 | 
 | -_cmsMemPluginChunkType _cmsMemPluginChunk = { _cmsMallocDefaultFn, _cmsMallocZeroDefaultFn, _cmsFreeDefaultFn,  | 
 | -                                              _cmsReallocDefaultFn, _cmsCallocDefaultFn,    _cmsDupDefaultFn | 
 | +_cmsMemPluginChunkType _cmsMemPluginChunk = {_cmsMalloc, _cmsMallocZero, _cmsFree, | 
 | +                                             _cmsRealloc, _cmsCalloc,    _cmsDupMem | 
 |                                              }; | 
 |   | 
 | - | 
 | -// Reset and duplicate memory manager | 
 |  void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src) | 
 |  { | 
 |      _cmsAssert(ctx != NULL); | 
 |   | 
 | -    if (src != NULL) {     | 
 | +    if (src != NULL) { | 
 |   | 
 |          // Duplicate | 
 | -        ctx ->chunks[MemPlugin] = _cmsSubAllocDup(ctx ->MemPool, src ->chunks[MemPlugin], sizeof(_cmsMemPluginChunkType));   | 
 | +        ctx ->chunks[MemPlugin] = _cmsSubAllocDup(ctx ->MemPool, src ->chunks[MemPlugin], sizeof(_cmsMemPluginChunkType)); | 
 |      } | 
 |      else { | 
 |   | 
 |          // To reset it, we use the default allocators, which cannot be overridden | 
 |          ctx ->chunks[MemPlugin] = &ctx ->DefaultMemoryManager; | 
 | -    }  | 
 | +    } | 
 |  } | 
 |   | 
 | -// Auxiliary to fill memory management functions from plugin (or context 0 defaults) | 
 |  void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr) | 
 |  { | 
 |      if (Plugin == NULL) { | 
 | @@ -214,94 +149,15 @@ void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkTy | 
 |          ptr ->ReallocPtr = Plugin -> ReallocPtr; | 
 |   | 
 |          // Make sure we revert to defaults | 
 | -        ptr ->MallocZeroPtr= _cmsMallocZeroDefaultFn; | 
 | -        ptr ->CallocPtr    = _cmsCallocDefaultFn; | 
 | -        ptr ->DupPtr       = _cmsDupDefaultFn; | 
 | -       | 
 | +        ptr ->MallocZeroPtr= _cmsMallocZero; | 
 | +        ptr ->CallocPtr    = _cmsCalloc; | 
 | +        ptr ->DupPtr       = _cmsDupMem; | 
 | + | 
 |          if (Plugin ->MallocZeroPtr != NULL) ptr ->MallocZeroPtr = Plugin -> MallocZeroPtr; | 
 |          if (Plugin ->CallocPtr != NULL)     ptr ->CallocPtr     = Plugin -> CallocPtr; | 
 |          if (Plugin ->DupPtr != NULL)        ptr ->DupPtr        = Plugin -> DupPtr; | 
 | -         | 
 | -    } | 
 | -} | 
 | - | 
 |   | 
 | -// Plug-in replacement entry | 
 | -cmsBool  _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase *Data) | 
 | -{ | 
 | -    cmsPluginMemHandler* Plugin = (cmsPluginMemHandler*) Data;      | 
 | -    _cmsMemPluginChunkType* ptr; | 
 | - | 
 | -    // NULL forces to reset to defaults. In this special case, the defaults are stored in the context structure.  | 
 | -    // Remaining plug-ins does NOT have any copy in the context structure, but this is somehow special as the | 
 | -    // context internal data should be malloce'd by using those functions.  | 
 | -    if (Data == NULL) { | 
 | - | 
 | -       struct _cmsContext_struct* ctx = ( struct _cmsContext_struct*) ContextID; | 
 | - | 
 | -       // Return to the default allocators | 
 | -        if (ContextID != NULL) { | 
 | -            ctx->chunks[MemPlugin] = (void*) &ctx->DefaultMemoryManager; | 
 | -        } | 
 | -        return TRUE; | 
 |      } | 
 | - | 
 | -    // Check for required callbacks | 
 | -    if (Plugin -> MallocPtr == NULL || | 
 | -        Plugin -> FreePtr == NULL || | 
 | -        Plugin -> ReallocPtr == NULL) return FALSE; | 
 | - | 
 | -    // Set replacement functions | 
 | -    ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); | 
 | -    if (ptr == NULL)  | 
 | -        return FALSE; | 
 | - | 
 | -    _cmsInstallAllocFunctions(Plugin, ptr); | 
 | -    return TRUE; | 
 | -} | 
 | - | 
 | -// Generic allocate | 
 | -void* CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size) | 
 | -{ | 
 | -    _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); | 
 | -    return ptr ->MallocPtr(ContextID, size); | 
 | -} | 
 | - | 
 | -// Generic allocate & zero | 
 | -void* CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size) | 
 | -{ | 
 | -    _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); | 
 | -    return ptr->MallocZeroPtr(ContextID, size); | 
 | -} | 
 | - | 
 | -// Generic calloc | 
 | -void* CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size) | 
 | -{ | 
 | -    _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); | 
 | -    return ptr->CallocPtr(ContextID, num, size); | 
 | -} | 
 | - | 
 | -// Generic reallocate | 
 | -void* CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number size) | 
 | -{ | 
 | -    _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); | 
 | -    return ptr->ReallocPtr(ContextID, Ptr, size); | 
 | -} | 
 | - | 
 | -// Generic free memory | 
 | -void CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr) | 
 | -{ | 
 | -    if (Ptr != NULL) { | 
 | -        _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); | 
 | -        ptr ->FreePtr(ContextID, Ptr); | 
 | -    } | 
 | -} | 
 | - | 
 | -// Generic block duplication | 
 | -void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size) | 
 | -{ | 
 | -    _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); | 
 | -    return ptr ->DupPtr(ContextID, Org, size); | 
 |  } | 
 |   | 
 |  // ******************************************************************************************** |