From b0410707780daff1126a460cb294c144e36e408e Mon Sep 17 00:00:00 2001
From: Kevin Backhouse <kev@semmle.com>
Date: Mon, 13 May 2019 14:57:09 +0100
Subject: [PATCH] Add bounds check on allocation size.

---
 src/pngchunk.cpp                    |  20 +++++++++++++++++---
 1 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/src/pngchunk.cpp b/src/pngchunk.cpp
index bf389ee13..64a370e5f 100644
--- a/src/pngchunk.cpp
+++ b/src/pngchunk.cpp
@@ -625,8 +625,12 @@ namespace Exiv2 {
         const char *sp  = (char*) text.pData_+1;          // current byte (space pointer)
         const char *eot = (char*) text.pData_+text.size_; // end of text
 
+        if (sp >= eot) {
+            return DataBuf();
+        }
+
         // Look for newline
-        while (*sp != '\n' && sp < eot )
+        while (*sp != '\n')
         {
             sp++;
             if ( sp == eot )
@@ -635,9 +639,12 @@ namespace Exiv2 {
             }
         }
         sp++ ; // step over '\n'
+        if (sp == eot) {
+            return DataBuf();
+        }
 
         // Look for length
-        while ( (*sp == '\0' || *sp == ' ' || *sp == '\n') && sp < eot )
+        while (*sp == '\0' || *sp == ' ' || *sp == '\n')
         {
             sp++;
             if (sp == eot )
@@ -647,7 +654,7 @@ namespace Exiv2 {
         }
 
         const char* startOfLength = sp;
-        while ( ('0' <= *sp && *sp <= '9') && sp < eot)
+        while ('0' <= *sp && *sp <= '9')
         {
             sp++;
             if (sp == eot )
@@ -656,8 +663,13 @@ namespace Exiv2 {
             }
         }
         sp++ ; // step over '\n'
+        if (sp == eot) {
+            return DataBuf();
+        }
 
         long length = (long) atol(startOfLength);
+        enforce(length >= 0, Exiv2::kerCorruptedMetadata);
+        enforce(length <= (eot - sp)/2, Exiv2::kerCorruptedMetadata);
 
         // Allocate space
         if (length == 0)
@@ -682,6 +694,7 @@ namespace Exiv2 {
 
         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')
@@ -693,6 +706,7 @@ namespace Exiv2 {
                 }
 
                 sp++;
+                enforce(sp < eot, Exiv2::kerCorruptedMetadata);
             }
 
             if (i%2 == 0)
