From b5d2e4feea9c942bf4951f573410845dc5d81747 Mon Sep 17 00:00:00 2001
From: Kevin Backhouse <kev@semmle.com>
Date: Wed, 19 Feb 2020 15:55:54 +0800
Subject: [PATCH] Add better bounds checking in PngImage::printStructure().

---
 src/pngimage.cpp | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/src/pngimage.cpp b/src/pngimage.cpp
index 991da6c..516dcc2 100644
--- a/src/pngimage.cpp
+++ b/src/pngimage.cpp
@@ -241,7 +241,7 @@ namespace Exiv2 {
                 if (bufRead != cheaderBuf.size_) throw Error(20);
 
                 // Decode chunk data length.
-                uint32_t dataOffset = Exiv2::getULong(cheaderBuf.pData_, Exiv2::bigEndian);
+                const uint32_t dataOffset = Exiv2::getULong(cheaderBuf.pData_, Exiv2::bigEndian);
                 for (int i = 4; i < 8; i++) {
                     chType[i-4]=cheaderBuf.pData_[i];
                 }
@@ -256,7 +256,8 @@ namespace Exiv2 {
                 }
 
                 DataBuf   buff(dataOffset);
-                io_->read(buff.pData_,dataOffset);
+                bufRead = io_->read(buff.pData_,dataOffset);
+                if (bufRead != static_cast<long>(dataOffset)) throw Exiv2::Error(14);
                 io_->seek(restore, BasicIo::beg);
 
                 // format output
@@ -269,7 +270,8 @@ namespace Exiv2 {
                 if ( bPrint ) {
                     io_->seek(dataOffset, BasicIo::cur);// jump to checksum
                     byte checksum[4];
-                    io_->read(checksum,4);
+                    bufRead = io_->read(checksum,4);
+                    if (bufRead != 4) throw Exiv2::Error(14);
                     io_->seek(restore, BasicIo::beg)   ;// restore file pointer
 
                     out << Internal::stringFormat("%8d | %-5s |%8d | "
@@ -300,9 +302,12 @@ namespace Exiv2 {
                     DataBuf   dataBuf;
                     byte*     data   = new byte[dataOffset+1];
                     data[dataOffset] = 0;
-                    io_->read(data,dataOffset);
+                    bufRead = io_->read(data,dataOffset);
+                    if (bufRead != static_cast<long>(dataOffset)) throw Exiv2::Error(14);
                     io_->seek(restore, BasicIo::beg);
                     uint32_t  name_l = (uint32_t) std::strlen((const char*)data)+1; // leading string length
+                    if (name_l > dataOffset) throw Exiv2::Error(58);
+
                     uint32_t  start  = name_l;
                     bool      bLF    = false;
 
-- 
2.19.1

