13e5a3e02339b746abcaee6408893ca2fd8e289d

Also needed as pre-requisites:

1b917c3f7dd86336a9f6fda4456422c419dfe88c (CVE-2019-20421)
22ea582c6b74ada30bec3a6b15de3c3e52f2b4da (CVE-2021-3482)
13e5a3e02339b746abcaee6408893ca2fd8e289d (CVE-2021-29457)
e6a0982f7cd9282052b6e3485a458d60629ffa0b (CVE-2021-29473)

--- exiv2-0.25.orig/src/jp2image.cpp
+++ exiv2-0.25/src/jp2image.cpp
@@ -36,6 +36,7 @@ EXIV2_RCSID("@(#) $Id: jp2image.cpp 3777
 #include "tiffimage.hpp"
 #include "image.hpp"
 #include "basicio.hpp"
+#include "enforce.hpp"
 #include "error.hpp"
 #include "futils.hpp"
 
@@ -141,6 +142,16 @@ namespace Exiv2
         throw(Error(32, "Image comment", "JP2"));
     } // Jp2Image::setComment
 
+static void boxes_check(size_t b,size_t m)
+{
+    if ( b > m ) {
+#ifdef EXIV2_DEBUG_MESSAGES
+        std::cout << "Exiv2::Jp2Image::readMetadata box maximum exceeded" << std::endl;
+#endif
+        throw Error(kerCorruptedMetadata);
+    }
+}
+
     void Jp2Image::readMetadata()
     {
 #ifdef DEBUG
@@ -163,9 +174,12 @@ namespace Exiv2
         Jp2BoxHeader      subBox    = {0,0};
         Jp2ImageHeaderBox ihdr      = {0,0,0,0,0,0,0,0};
         Jp2UuidBox        uuid      = {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
+        size_t            boxes     = 0 ;
+        size_t            boxem     = 1000 ; // boxes max
 
         while (io_->read((byte*)&box, sizeof(box)) == sizeof(box))
         {
+            boxes_check(boxes++,boxem );
             position      = io_->tell();
             box.boxLength = getLong((byte*)&box.boxLength, bigEndian);
 #ifdef DEBUG
@@ -183,10 +197,11 @@ namespace Exiv2
 #endif
                 return;
             }
-            if (box.boxLength == 1)
+            if (box.boxLength < 8)
             {
-                // FIXME. Special case. the real box size is given in another place.
-            }
+                // box is broken, so there is nothing we can do here
+                throw Error(kerCorruptedMetadata);
+	    }
 
             switch(box.boxType)
             {
@@ -198,8 +213,12 @@ namespace Exiv2
 
                     if (io_->read((byte*)&subBox, sizeof(subBox)) == sizeof(subBox))
                     {
+                        boxes_check(boxes++, boxem) ;
                         subBox.boxLength = getLong((byte*)&subBox.boxLength, bigEndian);
                         subBox.boxType   = getLong((byte*)&subBox.boxType, bigEndian);
+                        if (subBox.boxLength > io_->size() ) {
+                            throw Error(kerCorruptedMetadata);
+                        }
 
                         if((subBox.boxType == kJp2BoxTypeImageHeader) &&
                            (io_->read((byte*)&ihdr, sizeof(ihdr)) == sizeof(ihdr)))
@@ -243,7 +262,7 @@ namespace Exiv2
                             if (io_->error()) throw Error(14);
                             if (bufRead != rawData.size_) throw Error(20);
 
-                            if (rawData.size_ > 0)
+                            if (rawData.size_ > 8) // "II*\0long"
                             {
                                 // Find the position of Exif header in bytes array.
 
@@ -426,9 +445,10 @@ namespace Exiv2
 #endif
                 box.boxLength = io_->size() - io_->tell() + 8;
             }
-            if (box.boxLength == 1)
+            if (box.boxLength < 8)
             {
-                // FIXME. Special case. the real box size is given in another place.
+                // box is broken, so there is nothing we can do here
+                throw Error(kerCorruptedMetadata);
             }
 
             // Read whole box : Box header + Box data (not fixed size - can be null).
@@ -552,6 +572,7 @@ namespace Exiv2
 
                 case kJp2BoxTypeUuid:
                 {
+                    enforce(boxBuf.size_ >= 24, Exiv2::kerCorruptedMetadata);
                     if(memcmp(boxBuf.pData_ + 8, kJp2UuidExif, 16) == 0)
                     {
 #ifdef DEBUG
