1 diff --git a/third_party/lcms/src/cmslut.c b/third_party/lcms/src/cmslut.c 2 index 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 113 diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c 114 index 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