diff --git a/modules/lcms/NEWS b/modules/lcms/NEWS index 62dfa433abf..e710365a704 100644 --- a/modules/lcms/NEWS +++ b/modules/lcms/NEWS @@ -2,7 +2,31 @@ New in ver 1.17 =============== - Security fixes +Changes in API +---------------------- + +WIN64 support +_vsnprintf wrap +BOOL replaced by LCMSBOOL +cmsSetLanguage parameters changed to match ICC spec +removed support for extended gamut descriptor (was never fully implemented) +cmsFLAGS_NODEFAULTRESOURCEDEF moved to 0x01000000 +_cmsMalloc wrapper for malloc +_cmsFree wrapper for free + + +Implementation +---------------------- +All errors moved to fatal, since there is no easy recovery strategy +Vulnerability fixes on cmsio1.c +Status check, many functions now check the status when calling other functions. Improved robustness against ill-formed profiles. +_cmsSaveProfile didn't copy tags from a file based profile, fixed. + + +Utilities +---------- +icctrans: CMYKcm support wrongly implemented, fixed. +icclink: linking 3 to 7 channels didn't work in some cases, fixed. diff --git a/modules/lcms/README.1ST b/modules/lcms/README.1ST index 9abcf8a6ee2..60ceeda2225 100644 --- a/modules/lcms/README.1ST +++ b/modules/lcms/README.1ST @@ -74,7 +74,7 @@ ICM Stress demo from microsoft. www.microsoft.com sRGB from sRGB site www.srgb.com - If you found some profile of these not to be in public domain, + If you found any of these not to be in public domain, please notify me. I will remove the offending profile as soon as posible. diff --git a/modules/lcms/include/lcms.h b/modules/lcms/include/lcms.h index 5b6dae199b2..87e2174a868 100644 --- a/modules/lcms/include/lcms.h +++ b/modules/lcms/include/lcms.h @@ -409,9 +409,6 @@ extern "C" { #ifndef itoa # define itoa _itoa #endif -#ifndef filelength -# define filelength _filelength -#endif #ifndef fileno # define fileno _fileno #endif @@ -1403,6 +1400,7 @@ LCMS_INLINE WORD _cmsClampWord(int in) return (WORD) in; } +#ifndef LCMS_USER_ALLOC // Low-level alloc hook @@ -1414,6 +1412,14 @@ LCMS_INLINE void* _cmsMalloc(size_t size) return (void*) malloc(size); } + +LCMS_INLINE void _cmsFree(void *Ptr) +{ + if (Ptr) free(Ptr); +} + +#endif + // ------------------------------------------------------------------------------------------- end of inline functions // Signal error from inside lcms code diff --git a/modules/lcms/src/cmscam02.c b/modules/lcms/src/cmscam02.c index 358586ea014..bade0e08459 100644 --- a/modules/lcms/src/cmscam02.c +++ b/modules/lcms/src/cmscam02.c @@ -442,7 +442,7 @@ LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC) void LCMSEXPORT cmsCIECAM02Done(LCMSHANDLE hModel) { LPcmsCIECAM02 lpMod = (LPcmsCIECAM02) (LPSTR) hModel; - if (lpMod) free(lpMod); + if (lpMod) _cmsFree(lpMod); } diff --git a/modules/lcms/src/cmscam97.c b/modules/lcms/src/cmscam97.c index d52e362fdbf..7fb5c4ccbce 100644 --- a/modules/lcms/src/cmscam97.c +++ b/modules/lcms/src/cmscam97.c @@ -145,7 +145,7 @@ typedef struct { LCMSAPI void LCMSEXPORT cmsCIECAM97sDone(LCMSHANDLE hModel) { LPcmsCIECAM97s lpMod = (LPcmsCIECAM97s) (LPSTR) hModel; - if (lpMod) free(lpMod); + if (lpMod) _cmsFree(lpMod); } // Partial discounting for adaptation degree computation diff --git a/modules/lcms/src/cmscgats.c b/modules/lcms/src/cmscgats.c index ff015188a89..01fba223377 100644 --- a/modules/lcms/src/cmscgats.c +++ b/modules/lcms/src/cmscgats.c @@ -963,15 +963,15 @@ void LCMSEXPORT cmsIT8Free(LCMSHANDLE hIT8) for (p = it8->MemorySink; p != NULL; p = n) { n = p->Next; - if (p->Ptr) free(p->Ptr); - free(p); + if (p->Ptr) _cmsFree(p->Ptr); + _cmsFree(p); } } if (it8->MemoryBlock) - free(it8->MemoryBlock); + _cmsFree(it8->MemoryBlock); - free(it8); + _cmsFree(it8); } @@ -989,7 +989,7 @@ void* AllocBigBlock(LPIT8 it8, size_t size) if (ptr1 == NULL) { - free(ptr); + _cmsFree(ptr); return NULL; } @@ -2097,7 +2097,7 @@ LCMSHANDLE LCMSEXPORT cmsIT8LoadFromMem(void *Ptr, size_t len) CookPointers(it8); it8 ->nTable = 0; - free(it8->MemoryBlock); + _cmsFree(it8->MemoryBlock); it8 -> MemoryBlock = NULL; return hIT8; diff --git a/modules/lcms/src/cmsgamma.c b/modules/lcms/src/cmsgamma.c index 8cf9e270c31..ec3703d2638 100644 --- a/modules/lcms/src/cmsgamma.c +++ b/modules/lcms/src/cmsgamma.c @@ -134,7 +134,7 @@ LPGAMMATABLE LCMSEXPORT cmsAllocGamma(int nEntries) void LCMSEXPORT cmsFreeGamma(LPGAMMATABLE Gamma) { - if (Gamma) free(Gamma); + if (Gamma) _cmsFree(Gamma); } @@ -625,7 +625,7 @@ LPSAMPLEDCURVE cmsAllocSampledCurve(int nItems) if((pOut->Values = (double *) _cmsMalloc(nItems * sizeof(double))) == NULL) { - free(pOut); + _cmsFree(pOut); return NULL; } @@ -638,8 +638,8 @@ LPSAMPLEDCURVE cmsAllocSampledCurve(int nItems) void cmsFreeSampledCurve(LPSAMPLEDCURVE p) { - free((LPVOID) p -> Values); - free((LPVOID) p); + _cmsFree((LPVOID) p -> Values); + _cmsFree((LPVOID) p); } diff --git a/modules/lcms/src/cmsintrp.c b/modules/lcms/src/cmsintrp.c index 8e1e915d7de..91eff3aa66b 100644 --- a/modules/lcms/src/cmsintrp.c +++ b/modules/lcms/src/cmsintrp.c @@ -550,7 +550,7 @@ WORD cmsReverseLinearInterpLUT16(WORD Value, WORD LutTable[], LPL16PARAMS p) // Identify if value fall downto 0 or FFFF zone if (Value == 0) return 0; - if (Value == 0xFFFF) return 0xFFFF; + // if (Value == 0xFFFF) return 0xFFFF; // else restrict to valid zone @@ -602,7 +602,7 @@ WORD cmsReverseLinearInterpLUT16(WORD Value, WORD LutTable[], LPL16PARAMS p) a = (y1 - y0) / (x1 - x0); b = y0 - a * x0; - if (a == 0) return (WORD) x; + if (fabs(a) < 0.01) return (WORD) x; f = ((Value - b) / a); diff --git a/modules/lcms/src/cmsio0.c b/modules/lcms/src/cmsio0.c index ad9d1965db4..8d641fab0e4 100644 --- a/modules/lcms/src/cmsio0.c +++ b/modules/lcms/src/cmsio0.c @@ -50,7 +50,7 @@ LPVOID MemoryOpen(LPBYTE Block, size_t Size, char Mode) fm ->Block = (LPBYTE) _cmsMalloc(Size); if (fm ->Block == NULL) { - free(fm); + _cmsFree(fm); return NULL; } @@ -144,9 +144,9 @@ LCMSBOOL MemoryClose(struct _lcms_iccprofile_struct* Icc) if (ResData ->FreeBlockOnClose) { - if (ResData ->Block) free(ResData ->Block); + if (ResData ->Block) _cmsFree(ResData ->Block); } - free(ResData); + _cmsFree(ResData); return 0; } @@ -302,7 +302,7 @@ LPVOID _cmsInitTag(LPLCMSICCPROFILE Icc, icTagSignature sig, size_t size, const if (i >=0) { - if (Icc -> TagPtrs[i]) free(Icc -> TagPtrs[i]); + if (Icc -> TagPtrs[i]) _cmsFree(Icc -> TagPtrs[i]); } else { diff --git a/modules/lcms/src/cmsio1.c b/modules/lcms/src/cmsio1.c index 2b87bd7ebb0..9de5478cee4 100644 --- a/modules/lcms/src/cmsio1.c +++ b/modules/lcms/src/cmsio1.c @@ -358,7 +358,7 @@ ErrorCleanup: cmsSignalError(LCMS_ERRC_ABORTED, "Corrupted profile: '%s'", Icc->PhysicalFile); - free(Icc); + _cmsFree(Icc); return NULL; } @@ -539,13 +539,13 @@ LCMSBOOL ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig) PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * 256); if (PtrW == NULL) { - free(Temp); + _cmsFree(Temp); return FALSE; } NewLUT -> L1[i] = PtrW; if (Icc ->Read(Temp, 1, 256, Icc) != 256) { - free(Temp); + _cmsFree(Temp); return FALSE; } @@ -561,7 +561,7 @@ LCMSBOOL ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig) NewLUT -> wFlags &= ~LUT_HASTL1; } - free(Temp); + _cmsFree(Temp); // Copy 3D CLUT @@ -575,13 +575,13 @@ LCMSBOOL ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig) Temp = (LPBYTE) _cmsMalloc(nTabSize); if (Temp == NULL) { - free(PtrW); + _cmsFree(PtrW); return FALSE; } if (Icc ->Read(Temp, 1, nTabSize, Icc) != nTabSize) { - free(Temp); - free(PtrW); + _cmsFree(Temp); + _cmsFree(PtrW); return FALSE; } @@ -592,7 +592,7 @@ LCMSBOOL ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig) *PtrW++ = TO16_TAB(Temp[i]); } - free(Temp); + _cmsFree(Temp); } else { NewLUT ->T = NULL; @@ -613,13 +613,13 @@ LCMSBOOL ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig) PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * 256); if (PtrW == NULL) { - free(Temp); + _cmsFree(Temp); return FALSE; } NewLUT -> L2[i] = PtrW; if (Icc ->Read(Temp, 1, 256, Icc) != 256) { - free(Temp); + _cmsFree(Temp); return FALSE; } @@ -636,7 +636,7 @@ LCMSBOOL ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig) } - free(Temp); + _cmsFree(Temp); cmsCalcL16Params(NewLUT -> InputEntries, &NewLUT -> In16params); cmsCalcL16Params(NewLUT -> OutputEntries, &NewLUT -> Out16params); @@ -799,7 +799,7 @@ LCMSBOOL ReadLUT16(LPLCMSICCPROFILE Icc, LPLUT NewLUT) PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * nTabSize); if (PtrW == NULL) { - free(PtrW); + _cmsFree(PtrW); return FALSE; } @@ -1452,11 +1452,12 @@ int ReadEmbeddedTextTag(LPLCMSICCPROFILE Icc, size_t size, char* Name, size_t si if (UnicodeCount > size) return (int) size; - for (i=0; i < UnicodeCount; i++) - Icc ->Read(&Dummy, sizeof(icUInt16Number), 1, Icc); - - size -= UnicodeCount * sizeof(icUInt16Number); - + for (i=0; i < UnicodeCount; i++) { + size_t nread = Icc ->Read(&Dummy, sizeof(icUInt16Number), 1, Icc); + if (nread != 1) return (int) size; + size -= sizeof(icUInt16Number); + } + // Skip ScriptCode code if (Icc ->Read(&ScriptCodeCode, sizeof(icUInt16Number), 1, Icc) != 1) return -1; @@ -1464,12 +1465,15 @@ int ReadEmbeddedTextTag(LPLCMSICCPROFILE Icc, size_t size, char* Name, size_t si if (Icc ->Read(&ScriptCodeCount, sizeof(icUInt8Number), 1, Icc) != 1) return -1; size -= sizeof(icUInt8Number); + // Should remain 67 bytes as filler + if (size < 67) return (int) size; - for (i=0; i < 67; i++) - Icc ->Read(&Dummy, sizeof(icUInt8Number), 1, Icc); - - size -= 67; + for (i=0; i < 67; i++) { + size_t nread = Icc ->Read(&Dummy, sizeof(icUInt8Number), 1, Icc); + if (nread != 1) return (int) size; + size --; + } } break; @@ -1574,7 +1578,7 @@ int ReadEmbeddedTextTag(LPLCMSICCPROFILE Icc, size_t size, char* Name, size_t si Name[0] = 0; // Error } - free((void*) wchar); + _cmsFree((void*) wchar); } break; @@ -2349,7 +2353,7 @@ LPcmsSEQ LCMSEXPORT cmsReadProfileSequenceDescription(cmsHPROFILE hProfile) void LCMSEXPORT cmsFreeProfileSequenceDescription(LPcmsSEQ pseq) { if (pseq) - free(pseq); + _cmsFree(pseq); } @@ -3298,7 +3302,7 @@ LCMSBOOL SaveTagDirectory(LPLCMSICCPROFILE Icc) // Dump tag contents static -LCMSBOOL SaveTags(LPLCMSICCPROFILE Icc) +LCMSBOOL SaveTags(LPLCMSICCPROFILE Icc, LPLCMSICCPROFILE FileOrig) { LPBYTE Data; @@ -3326,8 +3330,31 @@ LCMSBOOL SaveTags(LPLCMSICCPROFILE Icc) Icc -> TagOffsets[i] = Begin = Icc ->UsedSpace; Data = (LPBYTE) Icc -> TagPtrs[i]; - if (!Data) + if (!Data) { + + // Reach here if we are copying a tag from a disk-based ICC profile which has not been modified by user. + // In this case a blind copy of the block data is performed + + if (Icc -> TagOffsets[i]) { + + size_t TagSize = FileOrig -> TagSizes[i]; + size_t TagOffset = FileOrig -> TagOffsets[i]; + void* Mem; + + if (FileOrig ->Seek(FileOrig, TagOffset)) return FALSE; + + Mem = _cmsMalloc(TagSize); + + if (FileOrig ->Read(Mem, TagSize, 1, FileOrig) != 1) return FALSE; + if (!Icc ->Write(Icc, TagSize, Mem)) return FALSE; + + Icc -> TagSizes[i] = (Icc ->UsedSpace - Begin); + free(Mem); + } + continue; + } + switch (Icc -> TagNames[i]) { @@ -3532,7 +3559,7 @@ LCMSBOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName) if (!SaveHeader(Icc)) return FALSE; if (!SaveTagDirectory(Icc)) return FALSE; - if (!SaveTags(Icc)) return FALSE; + if (!SaveTags(Icc, &Keep)) return FALSE; _cmsSetSaveToDisk(Icc, FileName); @@ -3542,7 +3569,7 @@ LCMSBOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName) if (!SaveHeader(Icc)) goto CleanUp; if (!SaveTagDirectory(Icc)) goto CleanUp; - if (!SaveTags(Icc)) goto CleanUp; + if (!SaveTags(Icc, &Keep)) goto CleanUp; rc = (Icc ->Close(Icc) == 0); CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE)); @@ -3574,7 +3601,7 @@ LCMSBOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr, if (!SaveHeader(Icc)) return FALSE; if (!SaveTagDirectory(Icc)) return FALSE; - if (!SaveTags(Icc)) return FALSE; + if (!SaveTags(Icc, &Keep)) return FALSE; if (!MemPtr) { @@ -3597,7 +3624,7 @@ LCMSBOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr, // Pass #2 does save to file into supplied stream if (!SaveHeader(Icc)) goto CleanUp; if (!SaveTagDirectory(Icc)) goto CleanUp; - if (!SaveTags(Icc)) goto CleanUp; + if (!SaveTags(Icc, &Keep)) goto CleanUp; // update BytesSaved so caller knows how many bytes put into stream *BytesNeeded = Icc ->UsedSpace; diff --git a/modules/lcms/src/cmsmatsh.c b/modules/lcms/src/cmsmatsh.c index bb4b23503ee..ca1e8bd4cca 100644 --- a/modules/lcms/src/cmsmatsh.c +++ b/modules/lcms/src/cmsmatsh.c @@ -208,11 +208,11 @@ void cmsFreeMatShaper(LPMATSHAPER MatShaper) for (i=0; i < 3; i++) { - if (MatShaper -> L[i]) free(MatShaper ->L[i]); - if (MatShaper -> L2[i]) free(MatShaper ->L2[i]); + if (MatShaper -> L[i]) _cmsFree(MatShaper ->L[i]); + if (MatShaper -> L2[i]) _cmsFree(MatShaper ->L2[i]); } - free(MatShaper); + _cmsFree(MatShaper); } diff --git a/modules/lcms/src/cmsnamed.c b/modules/lcms/src/cmsnamed.c index ba916818cab..e500a0f68d7 100644 --- a/modules/lcms/src/cmsnamed.c +++ b/modules/lcms/src/cmsnamed.c @@ -57,7 +57,7 @@ LPcmsNAMEDCOLORLIST GrowNamedColorList(LPcmsNAMEDCOLORLIST v, int ByElements) CopyMemory(TheNewList, v, sizeof(cmsNAMEDCOLORLIST) + (v ->nColors - 1) * sizeof(cmsNAMEDCOLOR)); TheNewList -> Allocated = NewElements; - free(v); + _cmsFree(v); return TheNewList; } } @@ -95,7 +95,7 @@ void cmsFreeNamedColorList(LPcmsNAMEDCOLORLIST v) return; } - free(v); + _cmsFree(v); } LCMSBOOL cmsAppendNamedColor(cmsHTRANSFORM xform, const char* Name, WORD PCS[3], WORD Colorant[MAXCHANNELS]) diff --git a/modules/lcms/src/cmsps2.c b/modules/lcms/src/cmsps2.c index 774c0105ff6..8bd4f054ddc 100644 --- a/modules/lcms/src/cmsps2.c +++ b/modules/lcms/src/cmsps2.c @@ -1204,7 +1204,7 @@ DWORD LCMSEXPORT cmsGetPostScriptCSA(cmsHPROFILE hProfile, if (!WriteNamedColorCSA(mem, hProfile, Intent)) { - free((void*) mem); + _cmsFree((void*) mem); return 0; } } @@ -1219,7 +1219,7 @@ DWORD LCMSEXPORT cmsGetPostScriptCSA(cmsHPROFILE hProfile, ColorSpace != icSigLabData) { cmsSignalError(LCMS_ERRC_ABORTED, "Invalid output color space"); - free((void*) mem); + _cmsFree((void*) mem); return 0; } @@ -1229,7 +1229,7 @@ DWORD LCMSEXPORT cmsGetPostScriptCSA(cmsHPROFILE hProfile, // Yes, so handle as LUT-based if (!WriteInputLUT(mem, hProfile, Intent)) { - free((void*) mem); + _cmsFree((void*) mem); return 0; } } @@ -1239,7 +1239,7 @@ DWORD LCMSEXPORT cmsGetPostScriptCSA(cmsHPROFILE hProfile, if (!WriteInputMatrixShaper(mem, hProfile)) { - free((void*) mem); // Something went wrong + _cmsFree((void*) mem); // Something went wrong return 0; } } @@ -1250,7 +1250,7 @@ DWORD LCMSEXPORT cmsGetPostScriptCSA(cmsHPROFILE hProfile, dwBytesUsed = mem ->dwUsed; // Get rid of memory stream - free((void*) mem); + _cmsFree((void*) mem); // Finally, return used byte count return dwBytesUsed; @@ -1671,7 +1671,7 @@ DWORD LCMSEXPORT cmsGetPostScriptCRDEx(cmsHPROFILE hProfile, if (!WriteNamedColorCRD(mem, hProfile, Intent, dwFlags)) { - free((void*) mem); + _cmsFree((void*) mem); return 0; } } @@ -1681,7 +1681,7 @@ DWORD LCMSEXPORT cmsGetPostScriptCRDEx(cmsHPROFILE hProfile, if (!WriteOutputLUT(mem, hProfile, Intent, dwFlags)) { - free((void*) mem); + _cmsFree((void*) mem); return 0; } } @@ -1696,7 +1696,7 @@ DWORD LCMSEXPORT cmsGetPostScriptCRDEx(cmsHPROFILE hProfile, dwBytesUsed = mem ->dwUsed; // Get rid of memory stream - free((void*) mem); + _cmsFree((void*) mem); // Finally, return used byte count return dwBytesUsed; diff --git a/modules/lcms/src/cmssamp.c b/modules/lcms/src/cmssamp.c index 40237e29d05..3ac73b5ea46 100644 --- a/modules/lcms/src/cmssamp.c +++ b/modules/lcms/src/cmssamp.c @@ -116,12 +116,16 @@ LCMSBOOL LCMSEXPORT cmsSample3DGrid(LPLUT Lut, _cmsSAMPLER Sampler, LPVOID Cargo &Lut -> In16params); } + for (t=0; t < (int) Lut -> OutputChan; t++) + Out[t] = Lut->T[index + t]; - // if (dwFlags & SAMPLER_INSPECT) { + if (dwFlags & SAMPLER_HASTL2) { for (t=0; t < (int) Lut -> OutputChan; t++) - Out[t] = Lut->T[index + t]; - // } + Out[t] = cmsLinearInterpLUT16(Out[t], + Lut -> L2[t], + &Lut -> Out16params); + } if (!Sampler(In, Out, Cargo)) @@ -448,6 +452,7 @@ int LCMSEXPORT cmsSetCMYKPreservationStrategy(int n) return OldVal; } +#pragma warning(disable: 4550) // Get a pointer to callback on depending of strategy static diff --git a/modules/lcms/src/cmsxform.c b/modules/lcms/src/cmsxform.c index 8c086226915..08d892680d8 100644 --- a/modules/lcms/src/cmsxform.c +++ b/modules/lcms/src/cmsxform.c @@ -1642,7 +1642,7 @@ void LCMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform) LCMS_FREE_LOCK(&p->rwlock); - free((void *) p); + _cmsFree((void *) p); }