Cherrypick upstream Little CMS fixes for uninit reads.

Cherrypick a fix [1] and a follow-up fix [2] from upstream.

[1] https://github.com/mm2/Little-CMS/commit/343efbac4db1e509c5027c53dd8c7d27104c796c
[2] https://github.com/mm2/Little-CMS/commit/1c3ccf4724333743dbef6d828bb22fc7776ad1e8

Bug: chromium:1287081
Change-Id: Ie268354178f4ed43794aba5a9061475c7ff46cc6
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/89330
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/third_party/lcms/0034-uninitialized-reads.patch b/third_party/lcms/0034-uninitialized-reads.patch
new file mode 100644
index 0000000..303266e
--- /dev/null
+++ b/third_party/lcms/0034-uninitialized-reads.patch
@@ -0,0 +1,161 @@
+diff --git a/third_party/lcms/src/cmsintrp.c b/third_party/lcms/src/cmsintrp.c
+index 3d9a40530..22de3e550 100644
+--- a/third_party/lcms/src/cmsintrp.c
++++ b/third_party/lcms/src/cmsintrp.c
+@@ -200,8 +200,8 @@ void LinLerp1D(CMSREGISTER const cmsUInt16Number Value[],
+     int val3;
+     const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
+ 
+-    // if last value...
+-    if (Value[0] == 0xffff) {
++    // if last value or just one point
++    if (Value[0] == 0xffff || p->Domain[0] == 0) {
+ 
+         Output[0] = LutTable[p -> Domain[0]];      
+     }
+@@ -240,7 +240,7 @@ void LinLerp1Dfloat(const cmsFloat32Number Value[],
+        val2 = fclamp(Value[0]);
+ 
+        // if last value...
+-       if (val2 == 1.0) {
++       if (val2 == 1.0 || p->Domain[0] == 0) {
+            Output[0] = LutTable[p -> Domain[0]];          
+        }
+        else
+@@ -274,20 +274,34 @@ void Eval1Input(CMSREGISTER const cmsUInt16Number Input[],
+        cmsUInt32Number OutChan;
+        const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
+ 
+-       v = Input[0] * p16 -> Domain[0];
+-       fk = _cmsToFixedDomain(v);
+ 
+-       k0 = FIXED_TO_INT(fk);
+-       rk = (cmsUInt16Number) FIXED_REST_TO_INT(fk);
++       // if last value...
++       if (Input[0] == 0xffff || p16->Domain[0] == 0) {
++
++           cmsUInt16Number y0 = LutTable[p16->Domain[0]];
++
++           for (OutChan = 0; OutChan < p16->nOutputs; OutChan++) {
++               Output[OutChan] = y0;
++           }
++       }
++       else
++       {
++
++           v = Input[0] * p16->Domain[0];
++           fk = _cmsToFixedDomain(v);
++
++           k0 = FIXED_TO_INT(fk);
++           rk = (cmsUInt16Number)FIXED_REST_TO_INT(fk);
+ 
+-       k1 = k0 + (Input[0] != 0xFFFFU ? 1 : 0);
++           k1 = k0 + (Input[0] != 0xFFFFU ? 1 : 0);
+ 
+-       K0 = p16 -> opta[0] * k0;
+-       K1 = p16 -> opta[0] * k1;
++           K0 = p16->opta[0] * k0;
++           K1 = p16->opta[0] * k1;
+ 
+-       for (OutChan=0; OutChan < p16->nOutputs; OutChan++) {
++           for (OutChan = 0; OutChan < p16->nOutputs; OutChan++) {
+ 
+-           Output[OutChan] = LinearInterp(rk, LutTable[K0+OutChan], LutTable[K1+OutChan]);
++               Output[OutChan] = LinearInterp(rk, LutTable[K0 + OutChan], LutTable[K1 + OutChan]);
++           }
+        }
+ }
+ 
+@@ -308,7 +322,7 @@ void Eval1InputFloat(const cmsFloat32Number Value[],
+     val2 = fclamp(Value[0]);
+ 
+     // if last value...
+-    if (val2 == 1.0) {
++    if (val2 == 1.0 || p->Domain[0] == 0) {
+ 
+         y0 = LutTable[p->Domain[0]];
+ 
+diff --git a/third_party/lcms/src/cmsio0.c b/third_party/lcms/src/cmsio0.c
+index 743b958df..ff8c464fc 100644
+--- a/third_party/lcms/src/cmsio0.c
++++ b/third_party/lcms/src/cmsio0.c
+@@ -1538,8 +1538,12 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig)
+     if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return NULL;
+ 
+     n = _cmsSearchTag(Icc, sig, TRUE);
+-    if (n < 0) goto Error;               // Not found, return NULL
+-
++    if (n < 0)
++    {
++        // Not found, return NULL
++        _cmsUnlockMutex(Icc->ContextID, Icc->UsrMutex);
++        return NULL;
++    }
+ 
+     // If the element is already in memory, return the pointer
+     if (Icc -> TagPtrs[n]) {
+diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c
+index 825b11eb1..49207735b 100644
+--- a/third_party/lcms/src/cmstypes.c
++++ b/third_party/lcms/src/cmstypes.c
+@@ -3515,42 +3515,48 @@ void *Type_UcrBg_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm
+ {
+     cmsUcrBg* n = (cmsUcrBg*) _cmsMallocZero(self ->ContextID, sizeof(cmsUcrBg));
+     cmsUInt32Number CountUcr, CountBg;
++    cmsInt32Number SignedSizeOfTag = (cmsInt32Number)SizeOfTag;
+     char* ASCIIString;
+ 
+     *nItems = 0;
+     if (n == NULL) return NULL;
+ 
+     // First curve is Under color removal
++
++    if (SignedSizeOfTag < sizeof(cmsUInt32Number)) return NULL;    
+     if (!_cmsReadUInt32Number(io, &CountUcr)) return NULL;
+-    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
+-    SizeOfTag -= sizeof(cmsUInt32Number);
++    SignedSizeOfTag -= sizeof(cmsUInt32Number);
+ 
+     n ->Ucr = cmsBuildTabulatedToneCurve16(self ->ContextID, CountUcr, NULL);
+     if (n ->Ucr == NULL) return NULL;
+ 
++    if (SignedSizeOfTag < (cmsInt32Number)CountUcr * sizeof(cmsUInt16Number)) return NULL;
+     if (!_cmsReadUInt16Array(io, CountUcr, n ->Ucr->Table16)) return NULL;
+-    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
+-    SizeOfTag -= CountUcr * sizeof(cmsUInt16Number);
++  
++    SignedSizeOfTag -= CountUcr * sizeof(cmsUInt16Number);
+ 
+     // Second curve is Black generation
++
++    if (SignedSizeOfTag < sizeof(cmsUInt32Number)) return NULL;    
+     if (!_cmsReadUInt32Number(io, &CountBg)) return NULL;
+-    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
+-    SizeOfTag -= sizeof(cmsUInt32Number);
++    SignedSizeOfTag -= sizeof(cmsUInt32Number);
+ 
+     n ->Bg = cmsBuildTabulatedToneCurve16(self ->ContextID, CountBg, NULL);
+     if (n ->Bg == NULL) return NULL;
++
++    if (SignedSizeOfTag < (cmsInt32Number) CountBg * sizeof(cmsUInt16Number)) return NULL;    
+     if (!_cmsReadUInt16Array(io, CountBg, n ->Bg->Table16)) return NULL;
+-    if (SizeOfTag < CountBg * sizeof(cmsUInt16Number)) return NULL;
+-    SizeOfTag -= CountBg * sizeof(cmsUInt16Number);
+-    if (SizeOfTag == UINT_MAX) return NULL;
++    SignedSizeOfTag -= CountBg * sizeof(cmsUInt16Number);
++
++    if (SignedSizeOfTag < 0 || SignedSizeOfTag > 32000) return NULL;
+ 
+     // Now comes the text. The length is specified by the tag size
+     n ->Desc = cmsMLUalloc(self ->ContextID, 1);
+     if (n ->Desc == NULL) return NULL;
+ 
+-    ASCIIString = (char*) _cmsMalloc(self ->ContextID, SizeOfTag + 1);
+-    if (io ->Read(io, ASCIIString, sizeof(char), SizeOfTag) != SizeOfTag) return NULL;
+-    ASCIIString[SizeOfTag] = 0;
++    ASCIIString = (char*) _cmsMalloc(self ->ContextID, SignedSizeOfTag + 1);
++    if (io ->Read(io, ASCIIString, sizeof(char), SignedSizeOfTag) != (cmsUInt32Number) SignedSizeOfTag) return NULL;
++    ASCIIString[SignedSizeOfTag] = 0;
+     cmsMLUsetASCII(n ->Desc, cmsNoLanguage, cmsNoCountry, ASCIIString);
+     _cmsFree(self ->ContextID, ASCIIString);
+ 
diff --git a/third_party/lcms/README.pdfium b/third_party/lcms/README.pdfium
index 52e4ceb..8a0fafb 100644
--- a/third_party/lcms/README.pdfium
+++ b/third_party/lcms/README.pdfium
@@ -20,3 +20,4 @@
 0029-drop-register-keyword.patch: Remove deprecated 'register' keyword.
 0030-const-data.patch: Mark many data structures as const.
 0033-opt-integer-overflow.patch: Protect against integer overflow.
+0034-uninitialized-reads.patch: Protect against corrupt profiles.
diff --git a/third_party/lcms/src/cmsintrp.c b/third_party/lcms/src/cmsintrp.c
index 3d9a405..22de3e5 100644
--- a/third_party/lcms/src/cmsintrp.c
+++ b/third_party/lcms/src/cmsintrp.c
@@ -200,8 +200,8 @@
     int val3;
     const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
 
-    // if last value...
-    if (Value[0] == 0xffff) {
+    // if last value or just one point
+    if (Value[0] == 0xffff || p->Domain[0] == 0) {
 
         Output[0] = LutTable[p -> Domain[0]];      
     }
@@ -240,7 +240,7 @@
        val2 = fclamp(Value[0]);
 
        // if last value...
-       if (val2 == 1.0) {
+       if (val2 == 1.0 || p->Domain[0] == 0) {
            Output[0] = LutTable[p -> Domain[0]];          
        }
        else
@@ -274,20 +274,34 @@
        cmsUInt32Number OutChan;
        const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
 
-       v = Input[0] * p16 -> Domain[0];
-       fk = _cmsToFixedDomain(v);
 
-       k0 = FIXED_TO_INT(fk);
-       rk = (cmsUInt16Number) FIXED_REST_TO_INT(fk);
+       // if last value...
+       if (Input[0] == 0xffff || p16->Domain[0] == 0) {
 
-       k1 = k0 + (Input[0] != 0xFFFFU ? 1 : 0);
+           cmsUInt16Number y0 = LutTable[p16->Domain[0]];
 
-       K0 = p16 -> opta[0] * k0;
-       K1 = p16 -> opta[0] * k1;
+           for (OutChan = 0; OutChan < p16->nOutputs; OutChan++) {
+               Output[OutChan] = y0;
+           }
+       }
+       else
+       {
 
-       for (OutChan=0; OutChan < p16->nOutputs; OutChan++) {
+           v = Input[0] * p16->Domain[0];
+           fk = _cmsToFixedDomain(v);
 
-           Output[OutChan] = LinearInterp(rk, LutTable[K0+OutChan], LutTable[K1+OutChan]);
+           k0 = FIXED_TO_INT(fk);
+           rk = (cmsUInt16Number)FIXED_REST_TO_INT(fk);
+
+           k1 = k0 + (Input[0] != 0xFFFFU ? 1 : 0);
+
+           K0 = p16->opta[0] * k0;
+           K1 = p16->opta[0] * k1;
+
+           for (OutChan = 0; OutChan < p16->nOutputs; OutChan++) {
+
+               Output[OutChan] = LinearInterp(rk, LutTable[K0 + OutChan], LutTable[K1 + OutChan]);
+           }
        }
 }
 
@@ -308,7 +322,7 @@
     val2 = fclamp(Value[0]);
 
     // if last value...
-    if (val2 == 1.0) {
+    if (val2 == 1.0 || p->Domain[0] == 0) {
 
         y0 = LutTable[p->Domain[0]];
 
diff --git a/third_party/lcms/src/cmsio0.c b/third_party/lcms/src/cmsio0.c
index 743b958..ff8c464 100644
--- a/third_party/lcms/src/cmsio0.c
+++ b/third_party/lcms/src/cmsio0.c
@@ -1538,8 +1538,12 @@
     if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return NULL;
 
     n = _cmsSearchTag(Icc, sig, TRUE);
-    if (n < 0) goto Error;               // Not found, return NULL
-
+    if (n < 0)
+    {
+        // Not found, return NULL
+        _cmsUnlockMutex(Icc->ContextID, Icc->UsrMutex);
+        return NULL;
+    }
 
     // If the element is already in memory, return the pointer
     if (Icc -> TagPtrs[n]) {
diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c
index 825b11e..4920773 100644
--- a/third_party/lcms/src/cmstypes.c
+++ b/third_party/lcms/src/cmstypes.c
@@ -3515,42 +3515,48 @@
 {
     cmsUcrBg* n = (cmsUcrBg*) _cmsMallocZero(self ->ContextID, sizeof(cmsUcrBg));
     cmsUInt32Number CountUcr, CountBg;
+    cmsInt32Number SignedSizeOfTag = (cmsInt32Number)SizeOfTag;
     char* ASCIIString;
 
     *nItems = 0;
     if (n == NULL) return NULL;
 
     // First curve is Under color removal
+
+    if (SignedSizeOfTag < sizeof(cmsUInt32Number)) return NULL;    
     if (!_cmsReadUInt32Number(io, &CountUcr)) return NULL;
-    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
-    SizeOfTag -= sizeof(cmsUInt32Number);
+    SignedSizeOfTag -= sizeof(cmsUInt32Number);
 
     n ->Ucr = cmsBuildTabulatedToneCurve16(self ->ContextID, CountUcr, NULL);
     if (n ->Ucr == NULL) return NULL;
 
+    if (SignedSizeOfTag < (cmsInt32Number)CountUcr * sizeof(cmsUInt16Number)) return NULL;
     if (!_cmsReadUInt16Array(io, CountUcr, n ->Ucr->Table16)) return NULL;
-    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
-    SizeOfTag -= CountUcr * sizeof(cmsUInt16Number);
+  
+    SignedSizeOfTag -= CountUcr * sizeof(cmsUInt16Number);
 
     // Second curve is Black generation
+
+    if (SignedSizeOfTag < sizeof(cmsUInt32Number)) return NULL;    
     if (!_cmsReadUInt32Number(io, &CountBg)) return NULL;
-    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
-    SizeOfTag -= sizeof(cmsUInt32Number);
+    SignedSizeOfTag -= sizeof(cmsUInt32Number);
 
     n ->Bg = cmsBuildTabulatedToneCurve16(self ->ContextID, CountBg, NULL);
     if (n ->Bg == NULL) return NULL;
+
+    if (SignedSizeOfTag < (cmsInt32Number) CountBg * sizeof(cmsUInt16Number)) return NULL;    
     if (!_cmsReadUInt16Array(io, CountBg, n ->Bg->Table16)) return NULL;
-    if (SizeOfTag < CountBg * sizeof(cmsUInt16Number)) return NULL;
-    SizeOfTag -= CountBg * sizeof(cmsUInt16Number);
-    if (SizeOfTag == UINT_MAX) return NULL;
+    SignedSizeOfTag -= CountBg * sizeof(cmsUInt16Number);
+
+    if (SignedSizeOfTag < 0 || SignedSizeOfTag > 32000) return NULL;
 
     // Now comes the text. The length is specified by the tag size
     n ->Desc = cmsMLUalloc(self ->ContextID, 1);
     if (n ->Desc == NULL) return NULL;
 
-    ASCIIString = (char*) _cmsMalloc(self ->ContextID, SizeOfTag + 1);
-    if (io ->Read(io, ASCIIString, sizeof(char), SizeOfTag) != SizeOfTag) return NULL;
-    ASCIIString[SizeOfTag] = 0;
+    ASCIIString = (char*) _cmsMalloc(self ->ContextID, SignedSizeOfTag + 1);
+    if (io ->Read(io, ASCIIString, sizeof(char), SignedSizeOfTag) != (cmsUInt32Number) SignedSizeOfTag) return NULL;
+    ASCIIString[SignedSizeOfTag] = 0;
     cmsMLUsetASCII(n ->Desc, cmsNoLanguage, cmsNoCountry, ASCIIString);
     _cmsFree(self ->ContextID, ASCIIString);