File lcms-bnc479606.patch of Package lcms

--- lcms-1.17/include/lcms.h
+++ lcms-1.18/include/lcms.h
@@ -1415,6 +1415,14 @@
     return (void*) malloc(size);
 }
 
+LCMS_INLINE void* _cmsCalloc(size_t nmemb, size_t size)
+{
+    size_t alloc = nmemb * size;
+    if (alloc < nmemb || alloc < size) {
+        return NULL;
+    }
+    return _cmsMalloc(alloc);
+}
 
 LCMS_INLINE void _cmsFree(void *Ptr)
 {
@@ -2027,6 +2035,10 @@
 // Build a tone curve for K->K' if possible (only works on CMYK)
 LPGAMMATABLE _cmsBuildKToneCurve(cmsHTRANSFORM hCMYK2CMYK, int nPoints);
 
+// Validates a LUT
+LCMSBOOL cdecl _cmsValidateLUT(LPLUT NewLUT);
+
+
 // These are two VITAL macros, from converting between 8 and 16 bit
 // representation. 
 
--- lcms-1.17/src/cmsgamma.c
+++ lcms-1.18/src/cmsgamma.c
@@ -114,7 +114,7 @@
        LPGAMMATABLE p;
        size_t size;
 
-       if (nEntries > 65530 || nEntries < 0) {
+       if (nEntries > 65530 || nEntries <= 0) {
                 cmsSignalError(LCMS_ERRC_ABORTED, "Couldn't create gammatable of more than 65530 entries");
                 return NULL;
        }
--- lcms-1.17/src/cmsio0.c
+++ lcms-1.18/src/cmsio0.c
@@ -33,7 +33,7 @@
 typedef struct {
                 LPBYTE Block;           // Points to allocated memory
                 size_t Size;            // Size of allocated memory
-                int Pointer;            // Points to current location
+                size_t Pointer;         // Points to current location
                 int FreeBlockOnClose;   // As title
 
                 } FILEMEM;
@@ -75,7 +75,17 @@
      FILEMEM* ResData = (FILEMEM*) Icc ->stream;
      LPBYTE Ptr;
      size_t len = size * count;
+     size_t extent = ResData -> Pointer + len;
      
+      if (len < size || len < count) {
+          cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Integer overflow with count / size.");
+          return 0;
+      }
+
+      if (extent < len || extent < ResData -> Pointer) {
+          cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Integer overflow with len.");
+          return 0;
+      } 
 
      if (ResData -> Pointer + len > ResData -> Size){
         
--- lcms-1.17/src/cmsio1.c
+++ lcms-1.18/src/cmsio1.c
@@ -261,11 +261,14 @@
 // Read profile header and validate it
 
 static
-LPLCMSICCPROFILE ReadHeader(LPLCMSICCPROFILE Icc, LCMSBOOL lIsFromMemory)
+LPLCMSICCPROFILE ReadHeader(LPLCMSICCPROFILE Icc,
+                            LCMSBOOL lIsFromMemory,
+                            DWORD dwSize)
 {
      icTag Tag;
      icHeader Header;
      icInt32Number TagCount, i;
+     icUInt32Number extent;
     
        if (Icc -> Read(&Header, sizeof(icHeader), 1, Icc) != 1) 
                       goto ErrorCleanup;
@@ -287,6 +290,10 @@
 
        if (Header.magic != icMagicNumber) goto ErrorCleanup;
                    
+       if (dwSize && dwSize != Header.size) {
+            goto ErrorCleanup;
+        }
+              
        if (Icc ->Read(&TagCount, sizeof(icInt32Number), 1, Icc) != 1)
                      goto ErrorCleanup;
 
@@ -321,7 +328,7 @@
 
        // Read tag directory
 
-       if (TagCount > MAX_TABLE_TAG) {
+       if (TagCount > MAX_TABLE_TAG || TagCount < 0) {
 
            cmsSignalError(LCMS_ERRC_ABORTED, "Too many tags (%d)", TagCount);
            goto ErrorCleanup;
@@ -338,8 +345,9 @@
               AdjustEndianess32((LPBYTE) &Tag.sig);            // Signature
 
               // Perform some sanity check. Offset + size should fall inside file.
-
-              if (Tag.offset + Tag.size > Header.size) goto ErrorCleanup;
+              extent = Tag.offset + Tag.size;
+              if (extent > Header.size || extent < Tag.offset)
+                  goto ErrorCleanup;
 
               Icc -> TagNames[i]   = Tag.sig;
               Icc -> TagOffsets[i] = Tag.offset;
@@ -494,9 +502,9 @@
        NewLUT -> OutputEntries = 256;
 
        // Do some checking
-       if (NewLUT -> cLutPoints > 100) NewLUT ->cLutPoints = 100;
-       if (NewLUT -> InputChan > MAXCHANNELS)  NewLUT -> InputChan = MAXCHANNELS;
-       if (NewLUT -> OutputChan > MAXCHANNELS) NewLUT -> OutputChan = MAXCHANNELS;
+       if (!_cmsValidateLUT(NewLUT)) {
+          return FALSE;
+       }
 
        AdjustEndianess32((LPBYTE) &LUT8.e00);
        AdjustEndianess32((LPBYTE) &LUT8.e01);
@@ -571,7 +579,7 @@
 
        if (nTabSize > 0) {
 
-            PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * nTabSize);
+            PtrW = (LPWORD) _cmsCalloc(sizeof(WORD), nTabSize);
             if (PtrW == NULL) return FALSE;
 
             Temp = (LPBYTE) _cmsMalloc(nTabSize);
@@ -662,6 +670,15 @@
            // some profiles does claim to do that. Poor lcms will try
            // to detect such condition and fix up "on the fly".
           
+           switch (sig) {
+
+            case icSigBToA0Tag:
+            case icSigBToA1Tag:
+            case icSigBToA2Tag:
+            case icSigGamutTag:
+            case icSigPreview0Tag:
+            case icSigPreview1Tag:
+            case icSigPreview2Tag: 
            {
                LPWORD WhiteLab, ExpectedWhite;
                WORD WhiteFixed[MAXCHANNELS], WhiteUnfixed[MAXCHANNELS];
@@ -701,7 +718,10 @@
                }
                
            }
+           break;
            
+        default:;
+        }           
        }
 
        return TRUE;
@@ -736,6 +756,9 @@
        NewLUT -> InputEntries  = LUT16.inputEnt;
        NewLUT -> OutputEntries = LUT16.outputEnt;
 
+       if (!_cmsValidateLUT(NewLUT)) {
+         return FALSE;
+       }
 
        // Matrix handling
 
@@ -798,11 +821,9 @@
                                                 NewLUT->InputChan));
        if (nTabSize > 0) {
 
-           PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * nTabSize);
-           if (PtrW == NULL) {
-               _cmsFree(PtrW);
+           PtrW = (LPWORD) _cmsCalloc(sizeof(WORD), nTabSize);
+           if (PtrW == NULL) 
                return FALSE;
-           }
 
            NewLUT -> T = PtrW;
            NewLUT -> Tsize = (unsigned int) (nTabSize * sizeof(WORD));
@@ -1108,15 +1129,24 @@
 static
 LCMSBOOL ReadCLUT(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT)
 {
-
+    unsigned int j;
     icCLutStruct CLUT;
 
     if (Icc -> Seek(Icc, Offset)) return FALSE;
     if (Icc ->Read(&CLUT, sizeof(icCLutStruct), 1, Icc) != 1) return FALSE;
 
 
-    cmsAlloc3DGrid(NewLUT, CLUT.gridPoints[0], NewLUT ->InputChan, 
-                                               NewLUT ->OutputChan);
+    for (j=1; j < NewLUT ->InputChan; j++) {
+        if (CLUT.gridPoints[0] != CLUT.gridPoints[j]) {
+            cmsSignalError(LCMS_ERRC_ABORTED, "CLUT with different granulatity is currently unsupported."); 
+            return FALSE;
+        }
+
+                
+    }
+
+    if (cmsAlloc3DGrid(NewLUT, CLUT.gridPoints[0], NewLUT ->InputChan, 
+                                               NewLUT ->OutputChan) == NULL) return FALSE;
 
     // Precission can be 1 or 2 bytes
 
@@ -1173,10 +1203,11 @@
     else 
         nCurves = NewLUT ->OutputChan;    
 
+    ZeroMemory(Curves, sizeof(Curves));
     for (i=0; i < nCurves; i++) {
 
         Curves[i] = ReadCurve(Icc);                     
-        if (Curves[i] == NULL) return FALSE;
+        if (Curves[i] == NULL) goto Error;
         SkipAlignment(Icc);
    
     }
@@ -1188,6 +1219,16 @@
 
     return TRUE;
 
+Error:
+    for (i=0; i < nCurves; i++) {
+
+        if (Curves[i]) 
+            cmsFreeGamma(Curves[i]);
+    }
+
+    return FALSE;
+
+
 }
 
 // V4 stuff. LutAtoB type 
@@ -1209,6 +1250,13 @@
        NewLUT -> InputChan     = LUT16.inputChan;
        NewLUT -> OutputChan    = LUT16.outputChan;
 
+       // Validate the NewLUT here to avoid excessive number of channels
+       // (leading to stack-based buffer overflow in ReadSetOfCurves).
+       // Needs revalidation after table size is filled in.
+       if (!_cmsValidateLUT(NewLUT)) {
+           return FALSE;
+       }
+
        AdjustEndianess32((LPBYTE) &LUT16.offsetB);
        AdjustEndianess32((LPBYTE) &LUT16.offsetMat);
        AdjustEndianess32((LPBYTE) &LUT16.offsetM);
@@ -1268,6 +1316,13 @@
        NewLUT -> InputChan     = LUT16.inputChan;
        NewLUT -> OutputChan    = LUT16.outputChan;
 
+       // Validate the NewLUT here to avoid excessive number of channels
+       // (leading to stack-based buffer overflow in ReadSetOfCurves).
+       // Needs revalidation after table size is filled in.
+       if (!_cmsValidateLUT(NewLUT)) {
+           return FALSE;
+       }
+
        AdjustEndianess32((LPBYTE) &LUT16.offsetB);
        AdjustEndianess32((LPBYTE) &LUT16.offsetMat);
        AdjustEndianess32((LPBYTE) &LUT16.offsetM);
@@ -1558,6 +1613,8 @@
             for (i=0; i < Offset; i++) {
                     
                     char Discard;
+                    // No return checking; could lead to large loop in
+                    // combination with int oflow above computing Offset.
                     Icc ->Read(&Discard, 1, 1, Icc);
             }
 
@@ -1566,7 +1623,7 @@
             if (Len < 0) Len = 0;
             if (Len > 20*1024) Len = 20 * 1024; 
 
-            wchar = (wchar_t*) _cmsMalloc(Len+2);
+            wchar = (wchar_t*) _cmsMalloc(Len*sizeof(wchar_t)+2);
             if (!wchar) return -1;
             
             if (Icc ->Read(wchar, 1, Len, Icc) != Len) return -1;
@@ -1942,6 +1999,8 @@
                     char Root[33];
 
                     ZeroMemory(Colorant, sizeof(WORD) * MAXCHANNELS);
+                    // No return value checking; could cause trouble with
+                    // large count.
                     Icc -> Read(Root, 1, 32, Icc);
                     Icc -> Read(PCS,  3, sizeof(WORD), Icc);
 
@@ -1975,7 +2034,8 @@
 
 LPcmsNAMEDCOLORLIST LCMSEXPORT cmsReadColorantTable(cmsHPROFILE hProfile, icTagSignature sig)
 {   
-    icInt32Number n, Count, i;
+    icInt32Number n;
+    icUInt32Number Count, i; 
     size_t offset;
     icTagTypeSignature  BaseType;
     LPLCMSICCPROFILE   Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
@@ -2316,6 +2376,10 @@
     Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc);
     AdjustEndianess32((LPBYTE) &Count);
     
+    if (Count > 1000) {
+         return NULL;
+    }
+ 
     size = sizeof(int) + Count * sizeof(cmsPSEQDESC);
     OutSeq = (LPcmsSEQ) _cmsMalloc(size);
     if (OutSeq == NULL) return NULL;
@@ -2496,7 +2560,7 @@
        NewIcc = _cmsCreateProfileFromFilePlaceholder(lpFileName);
         if (!NewIcc) return NULL;
       
-       if (!ReadHeader(NewIcc, FALSE)) return NULL;
+       if (!ReadHeader(NewIcc, FALSE, 0)) return NULL;
                       
        ReadCriticalTags(NewIcc);
 
@@ -2516,7 +2580,7 @@
        NewIcc = _cmsCreateProfileFromMemPlaceholder(MemPtr, dwSize); 
        if (!NewIcc) return NULL;
        
-       if (!ReadHeader(NewIcc, TRUE)) return NULL;
+       if (!ReadHeader(NewIcc, TRUE, dwSize)) return NULL;
              
        ReadCriticalTags(NewIcc);
 
--- lcms-1.17/src/cmslut.c
+++ lcms-1.18/src/cmslut.c
@@ -183,6 +183,37 @@
 }
 
 
+LCMSBOOL _cmsValidateLUT(LPLUT NewLUT)
+{
+    unsigned int calc = 1;
+    unsigned int oldCalc;
+    unsigned int power = NewLUT -> InputChan;
+
+    if (NewLUT -> cLutPoints > 100) return FALSE;
+    if (NewLUT -> InputChan > MAXCHANNELS)  return FALSE;
+    if (NewLUT -> OutputChan > MAXCHANNELS) return FALSE;
+
+    if (NewLUT -> cLutPoints == 0) return TRUE;
+    
+    for (; power > 0; power--) {
+
+      oldCalc = calc;
+      calc *= NewLUT -> cLutPoints;
+
+      if (calc < oldCalc || calc < NewLUT -> cLutPoints) {
+        return FALSE;
+      }
+    }
+
+    oldCalc = calc;
+    calc *= NewLUT -> OutputChan;
+    if (calc < oldCalc || calc < NewLUT -> OutputChan) {
+      return FALSE;
+    }
+
+    return TRUE;
+}
+
 LPLUT LCMSEXPORT cmsAlloc3DGrid(LPLUT NewLUT, int clutPoints, int inputChan, int outputChan)
 {
     DWORD nTabSize;
@@ -192,12 +223,15 @@
        NewLUT -> InputChan     = inputChan;
        NewLUT -> OutputChan    = outputChan;
 
+       if (!_cmsValidateLUT(NewLUT)) {
+         return NULL;
+       }
 
-       nTabSize = (NewLUT -> OutputChan * UIpow(NewLUT->cLutPoints,
-                                                NewLUT->InputChan)
-                                                * sizeof(WORD));
+       nTabSize = NewLUT -> OutputChan * UIpow(NewLUT->cLutPoints,
+                                               NewLUT->InputChan);
 
-       NewLUT -> T = (LPWORD) _cmsMalloc(nTabSize);
+       NewLUT -> T = (LPWORD) _cmsCalloc(sizeof(WORD), nTabSize);
+       nTabSize *= sizeof(WORD);
        if (NewLUT -> T == NULL) return NULL;
 
        ZeroMemory(NewLUT -> T, nTabSize);
openSUSE Build Service is sponsored by