1diff --git a/third_party/lcms/src/cmslut.c b/third_party/lcms/src/cmslut.c 2index 9b0eb4b54..19d43361f 100644 3--- a/third_party/lcms/src/cmslut.c 4+++ b/third_party/lcms/src/cmslut.c 5@@ -1255,21 +1255,39 @@ cmsStage* CMSEXPORT cmsStageDup(cmsStage* mpe) 6 // *********************************************************************************************************** 7 8 // This function sets up the channel count 9- 10 static 11-void BlessLUT(cmsPipeline* lut) 12+cmsBool BlessLUT(cmsPipeline* lut) 13 { 14 // We can set the input/ouput channels only if we have elements. 15 if (lut ->Elements != NULL) { 16 17- cmsStage *First, *Last; 18+ cmsStage* prev; 19+ cmsStage* next; 20+ cmsStage* First; 21+ cmsStage* Last; 22 23 First = cmsPipelineGetPtrToFirstStage(lut); 24 Last = cmsPipelineGetPtrToLastStage(lut); 25 26- if (First != NULL)lut ->InputChannels = First ->InputChannels; 27- if (Last != NULL) lut ->OutputChannels = Last ->OutputChannels; 28+ if (First == NULL || Last == NULL) return FALSE; 29+ 30+ lut->InputChannels = First->InputChannels; 31+ lut->OutputChannels = Last->OutputChannels; 32+ 33+ // Check chain consistency 34+ prev = First; 35+ next = prev->Next; 36+ 37+ while (next != NULL) 38+ { 39+ if (next->InputChannels != prev->OutputChannels) 40+ return FALSE; 41+ 42+ next = next->Next; 43+ prev = prev->Next; 44+ } 45 } 46+ return TRUE; 47 } 48 49 50@@ -1331,6 +1349,7 @@ cmsPipeline* CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUInt32Number In 51 { 52 cmsPipeline* NewLUT; 53 54+ // A value of zero in channels is allowed as placeholder 55 if (InputChannels >= cmsMAXCHANNELS || 56 OutputChannels >= cmsMAXCHANNELS) return NULL; 57 58@@ -1348,7 +1367,11 @@ cmsPipeline* CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUInt32Number In 59 NewLUT ->Data = NewLUT; 60 NewLUT ->ContextID = ContextID; 61 62- BlessLUT(NewLUT); 63+ if (!BlessLUT(NewLUT)) 64+ { 65+ _cmsFree(ContextID, NewLUT); 66+ return NULL; 67+ } 68 69 return NewLUT; 70 } 71@@ -1454,7 +1477,12 @@ cmsPipeline* CMSEXPORT cmsPipelineDup(const cmsPipeline* lut) 72 73 NewLUT ->SaveAs8Bits = lut ->SaveAs8Bits; 74 75- BlessLUT(NewLUT); 76+ if (!BlessLUT(NewLUT)) 77+ { 78+ _cmsFree(lut->ContextID, NewLUT); 79+ return NULL; 80+ } 81+ 82 return NewLUT; 83 } 84 85@@ -1491,8 +1519,7 @@ int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage 86 return FALSE; 87 } 88 89- BlessLUT(lut); 90- return TRUE; 91+ return BlessLUT(lut); 92 } 93 94 // Unlink an element and return the pointer to it 95@@ -1547,6 +1574,7 @@ void CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStag 96 else 97 cmsStageFree(Unlinked); 98 99+ // May fail, but we ignore it 100 BlessLUT(lut); 101 } 102 103@@ -1573,8 +1601,7 @@ cmsBool CMSEXPORT cmsPipelineCat(cmsPipeline* l1, const cmsPipeline* l2) 104 return FALSE; 105 } 106 107- BlessLUT(l1); 108- return TRUE; 109+ return BlessLUT(l1); 110 } 111 112 113diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c 114index e5ed06c33..0256e247b 100644 115--- a/third_party/lcms/src/cmstypes.c 116+++ b/third_party/lcms/src/cmstypes.c 117@@ -1755,8 +1755,8 @@ void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cms 118 if (!_cmsReadUInt8Number(io, NULL)) goto Error; 119 120 // Do some checking 121- if (InputChannels > cmsMAXCHANNELS) goto Error; 122- if (OutputChannels > cmsMAXCHANNELS) goto Error; 123+ if (InputChannels == 0 || InputChannels > cmsMAXCHANNELS) goto Error; 124+ if (OutputChannels == 0 || OutputChannels > cmsMAXCHANNELS) goto Error; 125 126 // Allocates an empty Pipeline 127 NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels); 128@@ -2048,8 +2048,8 @@ void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm 129 if (!_cmsReadUInt8Number(io, NULL)) return NULL; 130 131 // Do some checking 132- if (InputChannels > cmsMAXCHANNELS) goto Error; 133- if (OutputChannels > cmsMAXCHANNELS) goto Error; 134+ if (InputChannels == 0 || InputChannels > cmsMAXCHANNELS) goto Error; 135+ if (OutputChannels == 0 || OutputChannels > cmsMAXCHANNELS) goto Error; 136 137 // Allocates an empty LUT 138 NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels); 139@@ -2486,7 +2486,10 @@ void* Type_LUTA2B_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c 140 if (!_cmsReadUInt32Number(io, &offsetC)) return NULL; 141 if (!_cmsReadUInt32Number(io, &offsetA)) return NULL; 142 143- // Allocates an empty LUT 144+ if (inputChan == 0 || inputChan >= cmsMAXCHANNELS) return NULL; 145+ if (outputChan == 0 || outputChan >= cmsMAXCHANNELS) return NULL; 146+ 147+ // Allocates an empty LUT 148 NewLUT = cmsPipelineAlloc(self ->ContextID, inputChan, outputChan); 149 if (NewLUT == NULL) return NULL; 150 151@@ -2794,6 +2797,9 @@ void* Type_LUTB2A_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c 152 if (!_cmsReadUInt8Number(io, &inputChan)) return NULL; 153 if (!_cmsReadUInt8Number(io, &outputChan)) return NULL; 154 155+ if (inputChan == 0 || inputChan >= cmsMAXCHANNELS) return NULL; 156+ if (outputChan == 0 || outputChan >= cmsMAXCHANNELS) return NULL; 157+ 158 // Padding 159 if (!_cmsReadUInt16Number(io, NULL)) return NULL; 160 161@@ -4443,6 +4449,9 @@ void *Type_MPE_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsU 162 if (!_cmsReadUInt16Number(io, &InputChans)) return NULL; 163 if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL; 164 165+ if (InputChans == 0 || InputChans >= cmsMAXCHANNELS) return NULL; 166+ if (OutputChans == 0 || OutputChans >= cmsMAXCHANNELS) return NULL; 167+ 168 // Allocates an empty LUT 169 NewLUT = cmsPipelineAlloc(self ->ContextID, InputChans, OutputChans); 170 if (NewLUT == NULL) return NULL; 171