| diff --git a/third_party/lcms/src/cmscgats.c b/third_party/lcms/src/cmscgats.c |
| index 71692641a..0fe896122 100644 |
| --- a/third_party/lcms/src/cmscgats.c |
| +++ b/third_party/lcms/src/cmscgats.c |
| @@ -2456,6 +2456,9 @@ cmsHANDLE CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, const void *Ptr, cm |
| _cmsAssert(Ptr != NULL); |
| _cmsAssert(len != 0); |
| |
| + // Check for later overflow |
| + if (len + 1 == 0) return NULL; |
| + |
| type = IsMyBlock((const cmsUInt8Number*)Ptr, len); |
| if (type == 0) return NULL; |
| |
| @@ -2463,6 +2466,7 @@ cmsHANDLE CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, const void *Ptr, cm |
| if (!hIT8) return NULL; |
| |
| it8 = (cmsIT8*) hIT8; |
| + |
| it8 ->MemoryBlock = (char*) _cmsMalloc(ContextID, len + 1); |
| if (it8->MemoryBlock == NULL) |
| { |
| diff --git a/third_party/lcms/src/cmslut.c b/third_party/lcms/src/cmslut.c |
| index 11361de45..03bb01cb9 100644 |
| --- a/third_party/lcms/src/cmslut.c |
| +++ b/third_party/lcms/src/cmslut.c |
| @@ -547,7 +547,7 @@ cmsStage* CMSEXPORT cmsStageAllocCLut16bitGranular(cmsContext ContextID, |
| cmsUInt32Number outputChan, |
| const cmsUInt16Number* Table) |
| { |
| - cmsUInt32Number i, n; |
| + cmsUInt32Number i, n, cs; |
| _cmsStageCLutData* NewElem; |
| cmsStage* NewMPE; |
| |
| @@ -571,14 +571,17 @@ cmsStage* CMSEXPORT cmsStageAllocCLut16bitGranular(cmsContext ContextID, |
| |
| NewMPE ->Data = (void*) NewElem; |
| |
| - NewElem -> nEntries = n = outputChan * CubeSize(clutPoints, inputChan); |
| - NewElem -> HasFloatValues = FALSE; |
| + cs = CubeSize(clutPoints, inputChan); |
| + n = outputChan * cs; |
| |
| - if (n == 0) { |
| + if (n == 0 || n / outputChan != cs) // Check for overflow. |
| + { |
| cmsStageFree(NewMPE); |
| return NULL; |
| } |
| |
| + NewElem -> nEntries = n; |
| + NewElem -> HasFloatValues = FALSE; |
| |
| NewElem ->Tab.T = (cmsUInt16Number*) _cmsCalloc(ContextID, n, sizeof(cmsUInt16Number)); |
| if (NewElem ->Tab.T == NULL) { |
| @@ -638,7 +641,7 @@ cmsStage* CMSEXPORT cmsStageAllocCLutFloat(cmsContext ContextID, |
| |
| cmsStage* CMSEXPORT cmsStageAllocCLutFloatGranular(cmsContext ContextID, const cmsUInt32Number clutPoints[], cmsUInt32Number inputChan, cmsUInt32Number outputChan, const cmsFloat32Number* Table) |
| { |
| - cmsUInt32Number i, n; |
| + cmsUInt32Number i, n, cs; |
| _cmsStageCLutData* NewElem; |
| cmsStage* NewMPE; |
| |
| @@ -662,15 +665,18 @@ cmsStage* CMSEXPORT cmsStageAllocCLutFloatGranular(cmsContext ContextID, const c |
| |
| NewMPE ->Data = (void*) NewElem; |
| |
| - // There is a potential integer overflow on conputing n and nEntries. |
| - NewElem -> nEntries = n = outputChan * CubeSize(clutPoints, inputChan); |
| - NewElem -> HasFloatValues = TRUE; |
| + cs = CubeSize(clutPoints, inputChan); |
| + n = outputChan * cs; |
| |
| - if (n == 0) { |
| + if (n == 0 || n / outputChan != cs) // Check for overflow. |
| + { |
| cmsStageFree(NewMPE); |
| return NULL; |
| } |
| |
| + NewElem -> nEntries = n; |
| + NewElem -> HasFloatValues = TRUE; |
| + |
| NewElem ->Tab.TFloat = (cmsFloat32Number*) _cmsCalloc(ContextID, n, sizeof(cmsFloat32Number)); |
| if (NewElem ->Tab.TFloat == NULL) { |
| cmsStageFree(NewMPE); |
| diff --git a/third_party/lcms/src/cmsnamed.c b/third_party/lcms/src/cmsnamed.c |
| index 54d1abf91..50cc6b349 100644 |
| --- a/third_party/lcms/src/cmsnamed.c |
| +++ b/third_party/lcms/src/cmsnamed.c |
| @@ -92,7 +92,7 @@ cmsBool GrowMLUpool(cmsMLU* mlu) |
| static |
| cmsBool GrowMLUtable(cmsMLU* mlu) |
| { |
| - cmsUInt32Number AllocatedEntries; |
| + cmsUInt32Number AllocatedEntries, AllocatedBytes; |
| _cmsMLUentry *NewPtr; |
| |
| // Sanity check |
| @@ -103,8 +103,13 @@ cmsBool GrowMLUtable(cmsMLU* mlu) |
| // Check for overflow |
| if (AllocatedEntries / 2 != mlu ->AllocatedEntries) return FALSE; |
| |
| + AllocatedBytes = AllocatedEntries * sizeof(_cmsMLUentry); |
| + |
| + // Check for overflow |
| + if (AllocatedBytes / sizeof(_cmsMLUentry) != AllocatedEntries) return FALSE; |
| + |
| // Reallocate the memory |
| - NewPtr = (_cmsMLUentry*)_cmsRealloc(mlu ->ContextID, mlu ->Entries, AllocatedEntries*sizeof(_cmsMLUentry)); |
| + NewPtr = (_cmsMLUentry*)_cmsRealloc(mlu ->ContextID, mlu ->Entries, AllocatedBytes); |
| if (NewPtr == NULL) return FALSE; |
| |
| mlu ->Entries = NewPtr; |
| diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c |
| index ec1909f8d..074511296 100644 |
| --- a/third_party/lcms/src/cmstypes.c |
| +++ b/third_party/lcms/src/cmstypes.c |
| @@ -1488,10 +1488,10 @@ void *Type_MLU_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsU |
| cmsMLU* mlu; |
| cmsUInt32Number Count, RecLen, NumOfWchar; |
| cmsUInt32Number SizeOfHeader; |
| - cmsUInt32Number Len, Offset; |
| + cmsUInt32Number Len, Offset, WideLen, WideSizeOfTag; |
| cmsUInt32Number i; |
| wchar_t* Block; |
| - cmsUInt32Number BeginOfThisString, EndOfThisString, LargestPosition; |
| + cmsUInt32Number BeginOfThisString, EndOfThisString, LargestPosition, WideBeginOfThisString; |
| |
| *nItems = 0; |
| if (!_cmsReadUInt32Number(io, &Count)) return NULL; |
| @@ -1533,9 +1533,16 @@ void *Type_MLU_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsU |
| // True begin of the string |
| BeginOfThisString = Offset - SizeOfHeader - 8; |
| |
| - // Adjust to wchar_t elements |
| - mlu ->Entries[i].Len = (Len * sizeof(wchar_t)) / sizeof(cmsUInt16Number); |
| - mlu ->Entries[i].StrW = (BeginOfThisString * sizeof(wchar_t)) / sizeof(cmsUInt16Number); |
| + // Adjust to wchar_t elements and check for overflow |
| + WideBeginOfThisString = BeginOfThisString * sizeof(wchar_t); |
| + if (WideBeginOfThisString / sizeof(wchar_t) != BeginOfThisString) goto Error; |
| + |
| + // Adjust to wchar_t elements and check for overflow |
| + WideLen = Len * sizeof(wchar_t); |
| + if (WideLen / sizeof(wchar_t) != Len) goto Error; |
| + |
| + mlu ->Entries[i].Len = WideLen / sizeof(cmsUInt16Number); |
| + mlu ->Entries[i].StrW = WideBeginOfThisString / sizeof(cmsUInt16Number); |
| |
| // To guess maximum size, add offset + len |
| EndOfThisString = BeginOfThisString + Len; |
| @@ -1544,7 +1551,12 @@ void *Type_MLU_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsU |
| } |
| |
| // Now read the remaining of tag and fill all strings. Subtract the directory |
| - SizeOfTag = (LargestPosition * sizeof(wchar_t)) / sizeof(cmsUInt16Number); |
| + WideSizeOfTag = LargestPosition * sizeof(wchar_t); |
| + |
| + // Check for overflow |
| + if (WideSizeOfTag / sizeof(wchar_t) != LargestPosition) goto Error; |
| + |
| + SizeOfTag = WideSizeOfTag / sizeof(cmsUInt16Number); |
| if (SizeOfTag == 0) |
| { |
| Block = NULL; |
| @@ -5128,7 +5140,7 @@ static |
| cmsBool ReadOneWChar(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, wchar_t ** wcstr) |
| { |
| |
| - cmsUInt32Number nChars; |
| + cmsUInt32Number nChars, nBytes; |
| |
| // Special case for undefined strings (see ICC Votable |
| // Proposal Submission, Dictionary Type and Metadata TAG Definition) |
| @@ -5141,9 +5153,12 @@ cmsBool ReadOneWChar(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, wchar |
| if (!io -> Seek(io, e -> Offsets[i])) return FALSE; |
| |
| nChars = e ->Sizes[i] / sizeof(cmsUInt16Number); |
| + nBytes = (nChars + 1) * sizeof(wchar_t); |
| |
| + // Check for overflow |
| + if (nBytes / sizeof(wchar_t) != nChars + 1) return FALSE; |
| |
| - *wcstr = (wchar_t*) _cmsMallocZero(e ->ContextID, (nChars + 1) * sizeof(wchar_t)); |
| + *wcstr = (wchar_t*) _cmsMallocZero(e ->ContextID, nBytes); |
| if (*wcstr == NULL) return FALSE; |
| |
| if (!_cmsReadWCharArray(io, nChars, *wcstr)) { |