Fix memory leaks in lcms

found by libfuzzer

Review-Url: https://codereview.chromium.org/2359243003
diff --git a/third_party/lcms2-2.6/0004-memory-leak-Type_Curve_Read.patch b/third_party/lcms2-2.6/0004-memory-leak-Type_Curve_Read.patch
new file mode 100644
index 0000000..341a1c6
--- /dev/null
+++ b/third_party/lcms2-2.6/0004-memory-leak-Type_Curve_Read.patch
@@ -0,0 +1,28 @@
+diff --git a/third_party/lcms2-2.6/src/cmstypes.c b/third_party/lcms2-2.6/src/cmstypes.c
+index 06742b5..9fe5e2a 100644
+--- a/third_party/lcms2-2.6/src/cmstypes.c
++++ b/third_party/lcms2-2.6/src/cmstypes.c
+@@ -1112,7 +1112,10 @@ void *Type_Curve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm
+                NewGamma = cmsBuildTabulatedToneCurve16(self ->ContextID, Count, NULL);
+                if (!NewGamma) return NULL;
+ 
+-               if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) return NULL;
++               if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) {
++                 cmsFreeToneCurve(NewGamma);
++                 return NULL;
++               }
+ 
+                *nItems = 1;
+                return NewGamma;
+@@ -2350,7 +2353,10 @@ cmsStage* ReadCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUI
+ 
+         for (i=0; i < Data ->nEntries; i++) {
+ 
+-            if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) return NULL;
++            if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) {
++              cmsStageFree(CLUT);
++              return NULL;
++            }
+             Data ->Tab.T[i] = FROM_8_TO_16(v);
+         }
+ 
diff --git a/third_party/lcms2-2.6/0005-memory-leak-AllocEmptyTransform.patch b/third_party/lcms2-2.6/0005-memory-leak-AllocEmptyTransform.patch
new file mode 100644
index 0000000..a85a968
--- /dev/null
+++ b/third_party/lcms2-2.6/0005-memory-leak-AllocEmptyTransform.patch
@@ -0,0 +1,34 @@
+diff --git a/third_party/lcms2-2.6/src/cmsxform.c b/third_party/lcms2-2.6/src/cmsxform.c
+index eddb9bd..6466d27 100644
+--- a/third_party/lcms2-2.6/src/cmsxform.c
++++ b/third_party/lcms2-2.6/src/cmsxform.c
+@@ -593,7 +593,10 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
+ 
+     // Allocate needed memory
+     _cmsTRANSFORM* p = (_cmsTRANSFORM*) _cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM));
+-    if (!p) return NULL;
++    if (!p) {
++      cmsPipelineFree(lut);
++      return NULL;
++    }
+ 
+     // Store the proposed pipeline
+     p ->Lut = lut;
+@@ -643,7 +646,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
+         if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) {
+ 
+             cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
+-            _cmsFree(ContextID, p);
++            cmsDeleteTransform(p);
+             return NULL;
+         }
+ 
+@@ -673,7 +676,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
+             if (p ->FromInput == NULL || p ->ToOutput == NULL) {
+ 
+                 cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
+-                _cmsFree(ContextID, p);
++                cmsDeleteTransform(p);
+                 return NULL;
+             }
+ 
diff --git a/third_party/lcms2-2.6/0006-memory-leak-Type_NamedColor_Read.patch b/third_party/lcms2-2.6/0006-memory-leak-Type_NamedColor_Read.patch
new file mode 100644
index 0000000..5d25d5a
--- /dev/null
+++ b/third_party/lcms2-2.6/0006-memory-leak-Type_NamedColor_Read.patch
@@ -0,0 +1,22 @@
+diff --git a/third_party/lcms2-2.6/src/cmstypes.c b/third_party/lcms2-2.6/src/cmstypes.c
+index feba387..4d24fc2 100644
+--- a/third_party/lcms2-2.6/src/cmstypes.c
++++ b/third_party/lcms2-2.6/src/cmstypes.c
+@@ -3102,7 +3102,7 @@ void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i
+ 
+     if (nDeviceCoords > cmsMAXCHANNELS) {
+         cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many device coordinates '%d'", nDeviceCoords);
+-        return 0;
++        goto Error;
+     }
+     for (i=0; i < count; i++) {
+ 
+@@ -3111,7 +3111,7 @@ void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i
+         char Root[33];
+ 
+         memset(Colorant, 0, sizeof(Colorant));
+-        if (io -> Read(io, Root, 32, 1) != 1) return NULL;
++        if (io -> Read(io, Root, 32, 1) != 1) goto Error;
+         Root[32] = 0;
+         if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error;
+         if (!_cmsReadUInt16Array(io, nDeviceCoords, Colorant)) goto Error;
diff --git a/third_party/lcms2-2.6/0007-memory-leak-OptimizeByResampling.patch b/third_party/lcms2-2.6/0007-memory-leak-OptimizeByResampling.patch
new file mode 100644
index 0000000..2c55b94
--- /dev/null
+++ b/third_party/lcms2-2.6/0007-memory-leak-OptimizeByResampling.patch
@@ -0,0 +1,13 @@
+diff --git a/third_party/lcms2-2.6/src/cmsopt.c b/third_party/lcms2-2.6/src/cmsopt.c
+index f885ef3..684910d 100644
+--- a/third_party/lcms2-2.6/src/cmsopt.c
++++ b/third_party/lcms2-2.6/src/cmsopt.c
+@@ -612,7 +612,7 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
+ 
+     // Allocate the CLUT
+     CLUT = cmsStageAllocCLut16bit(Src ->ContextID, nGridPoints, Src ->InputChannels, Src->OutputChannels, NULL);
+-    if (CLUT == NULL) return FALSE;
++    if (CLUT == NULL) goto Error;
+ 
+     // Add the CLUT to the destination LUT
+     if (!cmsPipelineInsertStage(Dest, cmsAT_END, CLUT)) {
diff --git a/third_party/lcms2-2.6/README.pdfium b/third_party/lcms2-2.6/README.pdfium
index 82bdbc6..4fcd32b 100644
--- a/third_party/lcms2-2.6/README.pdfium
+++ b/third_party/lcms2-2.6/README.pdfium
@@ -13,4 +13,8 @@
 0001-from16-to-8-overflow.patch: Prevent a UBSan warning.
 0002-infinite-loop-GrowNamedColorList.patch: Fix infinite loop when calling GrowNamedColorList.
 0003-uninit.patch: Fix use uninitialized value and stack buffer overflow read.
+0004-memory-leak-Type_Curve_Read.patch: Fix memory leak in Type_Curve_Read.
+0005-memory-leak-AllocEmptyTransform.patch: Fix memory leak in AllocEmptyTransform.
+0006-memory-leak-Type_NamedColor_Read.patch: Fix memory leak in Type_NamedColor_Read.
+0007-memory-leak-OptimizeByResampling.patch: Fix memory leak in OptimizeByResampling.
 TODO(ochang): List other patches.
diff --git a/third_party/lcms2-2.6/src/cmsopt.c b/third_party/lcms2-2.6/src/cmsopt.c
index f885ef3..684910d 100644
--- a/third_party/lcms2-2.6/src/cmsopt.c
+++ b/third_party/lcms2-2.6/src/cmsopt.c
@@ -612,7 +612,7 @@
 
     // Allocate the CLUT
     CLUT = cmsStageAllocCLut16bit(Src ->ContextID, nGridPoints, Src ->InputChannels, Src->OutputChannels, NULL);
-    if (CLUT == NULL) return FALSE;
+    if (CLUT == NULL) goto Error;
 
     // Add the CLUT to the destination LUT
     if (!cmsPipelineInsertStage(Dest, cmsAT_END, CLUT)) {
diff --git a/third_party/lcms2-2.6/src/cmstypes.c b/third_party/lcms2-2.6/src/cmstypes.c
index 44c5b87..441d6bb 100644
--- a/third_party/lcms2-2.6/src/cmstypes.c
+++ b/third_party/lcms2-2.6/src/cmstypes.c
@@ -1112,7 +1112,10 @@
                NewGamma = cmsBuildTabulatedToneCurve16(self ->ContextID, Count, NULL);
                if (!NewGamma) return NULL;
 
-               if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) return NULL;
+               if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) {
+                 cmsFreeToneCurve(NewGamma);
+                 return NULL;
+               }
 
                *nItems = 1;
                return NewGamma;
@@ -2350,7 +2353,10 @@
 
         for (i=0; i < Data ->nEntries; i++) {
 
-            if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) return NULL;
+            if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) {
+              cmsStageFree(CLUT);
+              return NULL;
+            }
             Data ->Tab.T[i] = FROM_8_TO_16(v);
         }
 
@@ -3096,7 +3102,7 @@
 
     if (nDeviceCoords > cmsMAXCHANNELS) {
         cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many device coordinates '%d'", nDeviceCoords);
-        return 0;
+        goto Error;
     }
     for (i=0; i < count; i++) {
 
@@ -3105,7 +3111,7 @@
         char Root[33];
 
         memset(Colorant, 0, sizeof(Colorant));
-        if (io -> Read(io, Root, 32, 1) != 1) return NULL;
+        if (io -> Read(io, Root, 32, 1) != 1) goto Error;
         Root[32] = 0;
         if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error;
         if (!_cmsReadUInt16Array(io, nDeviceCoords, Colorant)) goto Error;
diff --git a/third_party/lcms2-2.6/src/cmsxform.c b/third_party/lcms2-2.6/src/cmsxform.c
index eddb9bd..6466d27 100644
--- a/third_party/lcms2-2.6/src/cmsxform.c
+++ b/third_party/lcms2-2.6/src/cmsxform.c
@@ -593,7 +593,10 @@
 
     // Allocate needed memory
     _cmsTRANSFORM* p = (_cmsTRANSFORM*) _cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM));
-    if (!p) return NULL;
+    if (!p) {
+      cmsPipelineFree(lut);
+      return NULL;
+    }
 
     // Store the proposed pipeline
     p ->Lut = lut;
@@ -643,7 +646,7 @@
         if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) {
 
             cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
-            _cmsFree(ContextID, p);
+            cmsDeleteTransform(p);
             return NULL;
         }
 
@@ -673,7 +676,7 @@
             if (p ->FromInput == NULL || p ->ToOutput == NULL) {
 
                 cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
-                _cmsFree(ContextID, p);
+                cmsDeleteTransform(p);
                 return NULL;
             }