File improve-pngchunk-bounds-checking.patch of Package exiv2-0_26.26888

This updates the implementation of PngChunk::readRawProfile()
to the version in 0.27.5

--- exiv2-0.26.orig/src/pngchunk.cpp
+++ exiv2-0.26/src/pngchunk.cpp
@@ -37,6 +37,7 @@ EXIV2_RCSID("@(#) $Id$")
 #include "iptc.hpp"
 #include "image.hpp"
 #include "error.hpp"
+#include "enforce.hpp"
 
 // + standard includes
 #include <sstream>
@@ -590,17 +591,12 @@ namespace Exiv2 {
     DataBuf PngChunk::readRawProfile(const DataBuf& text,bool iTXt)
     {
         DataBuf                 info;
-        register long           i;
-        register unsigned char *dp;
-        const char             *sp;
-        unsigned int            nibbles;
-        long                    length;
         unsigned char           unhex[103]={0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
-                                            0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
-                                            0,0,0,0,0,0,0,0,0,1, 2,3,4,5,6,7,8,9,0,0,
-                                            0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
-                                            0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,10,11,12,
-                                            13,14,15};
+            0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
+            0,0,0,0,0,0,0,0,0,1, 2,3,4,5,6,7,8,9,0,0,
+            0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
+            0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,10,11,12,
+            13,14,15};
         if (text.size_ == 0) {
             return DataBuf();
         }
@@ -611,39 +607,69 @@ namespace Exiv2 {
             return  info;
         }
 
+        const char *sp  = (char*) text.pData_+1;          // current byte (space pointer)
+        const char *eot = (char*) text.pData_+text.size_; // end of text
 
-        sp = (char*)text.pData_+1;
+        if (sp >= eot) {
+            return DataBuf();
+        }
 
         // Look for newline
-
         while (*sp != '\n')
+        {
             sp++;
+            if ( sp == eot )
+            {
+                return DataBuf();
+            }
+        }
+        sp++ ; // step over '\n'
+        if (sp == eot) {
+            return DataBuf();
+        }
 
         // Look for length
-
         while (*sp == '\0' || *sp == ' ' || *sp == '\n')
+        {
             sp++;
-
-        length = (long) atol(sp);
-        const char* eot = (char*)text.pData_ + text.size_;
-        if (length < 0 || length > (eot - sp)/2) {
-            throw Error(14);
+            if (sp == eot )
+            {
+                return DataBuf();
+            }
         }
 
-        while (*sp != ' ' && *sp != '\n')
+        // Parse the length.
+        long length = 0;
+        while ('0' <= *sp && *sp <= '9')
+        {
+            // Compute the new length using unsigned long, so that we can
+            // check for overflow.
+            const unsigned long newlength = (10 * static_cast<unsigned long>(length)) + (*sp - '0');
+            if (newlength > static_cast<unsigned long>(std::numeric_limits<long>::max())) {
+                return DataBuf(); // Integer overflow.
+            }
+            length = static_cast<long>(newlength);
             sp++;
+            if (sp == eot )
+            {
+                return DataBuf();
+            }
+        }
+        sp++ ; // step over '\n'
+        if (sp == eot) {
+            return DataBuf();
+        }
 
-        // Allocate space
+        enforce(length <= (eot - sp)/2, Exiv2::kerCorruptedMetadata);
 
+        // Allocate space
         if (length == 0)
         {
 #ifdef DEBUG
             std::cerr << "Exiv2::PngChunk::readRawProfile: Unable To Copy Raw Profile: invalid profile length\n";
 #endif
         }
-
         info.alloc(length);
-
         if (info.size_ != length)
         {
 #ifdef DEBUG
@@ -654,11 +680,12 @@ namespace Exiv2 {
 
         // Copy profile, skipping white space and column 1 "=" signs
 
-        dp      = (unsigned char*)info.pData_;
-        nibbles = length * 2;
+        unsigned char *dp = (unsigned char*)info.pData_; // decode pointer
+        unsigned int nibbles = length * 2;
 
-        for (i = 0; i < (long) nibbles; i++)
+        for (long i = 0; i < (long) nibbles; i++)
         {
+            enforce(sp < eot, Exiv2::kerCorruptedMetadata);
             while (*sp < '0' || (*sp > '9' && *sp < 'a') || *sp > 'f')
             {
                 if (*sp == '\0')
@@ -670,6 +697,7 @@ namespace Exiv2 {
                 }
 
                 sp++;
+                enforce(sp < eot, Exiv2::kerCorruptedMetadata);
             }
 
             if (i%2 == 0)
openSUSE Build Service is sponsored by