Blob Blame History Raw
diff --git a/src/jpgimage.cpp b/src/jpgimage.cpp
index 9afcb58..ca83f14 100644
--- a/src/jpgimage.cpp
+++ b/src/jpgimage.cpp
@@ -34,6 +34,7 @@ EXIV2_RCSID("@(#) $Id$")
 #include "image_int.hpp"
 #include "error.hpp"
 #include "futils.hpp"
+#include "enforce.hpp"
 
 #ifdef WIN32
 #include <windows.h>
@@ -328,12 +329,14 @@ namespace Exiv2 {
         int c = -1;
         // Skips potential padding between markers
         while ((c=io_->getb()) != 0xff) {
-            if (c == EOF) return -1;
+            if (c == EOF)
+                return -1;
         }
 
         // Markers can start with any number of 0xff
         while ((c=io_->getb()) == 0xff) {
-            if (c == EOF) return -2;
+            if (c == EOF)
+                return -2;
         }
         return c;
     }
@@ -564,85 +567,88 @@ namespace Exiv2 {
      out << Internal::stringFormat("%8ld | 0xff%02x %-5s", \
                              io_->tell()-2,marker,nm[marker].c_str())
 
-    void JpegBase::printStructure(std::ostream& out, PrintStructureOption option,int depth)
+    void JpegBase::printStructure(std::ostream& out, PrintStructureOption option, int depth)
     {
-        if (io_->open() != 0) throw Error(9, io_->path(), strError());
+        if (io_->open() != 0)
+            throw Error(9, io_->path(), strError());
         // Ensure that this is the correct image type
         if (!isThisType(*io_, false)) {
-            if (io_->error() || io_->eof()) throw Error(14);
+            if (io_->error() || io_->eof())
+                throw Error(14);
             throw Error(15);
         }
 
-        bool bPrint = option==kpsBasic || option==kpsRecursive;
+        bool bPrint = option == kpsBasic || option == kpsRecursive;
         Exiv2::Uint32Vector iptcDataSegs;
 
-        if ( bPrint || option == kpsXMP || option == kpsIccProfile || option == kpsIptcErase ) {
+        if (bPrint || option == kpsXMP || option == kpsIccProfile || option == kpsIptcErase) {
 
             // nmonic for markers
-            std::string nm[256] ;
-            nm[0xd8]="SOI"  ;
-            nm[0xd9]="EOI"  ;
-            nm[0xda]="SOS"  ;
-            nm[0xdb]="DQT"  ;
-            nm[0xdd]="DRI"  ;
-            nm[0xfe]="COM"  ;
+            std::string nm[256];
+            nm[0xd8] = "SOI";
+            nm[0xd9] = "EOI";
+            nm[0xda] = "SOS";
+            nm[0xdb] = "DQT";
+            nm[0xdd] = "DRI";
+            nm[0xfe] = "COM";
 
             // 0xe0 .. 0xef are APPn
             // 0xc0 .. 0xcf are SOFn (except 4)
-            nm[0xc4]="DHT"  ;
-            for ( int i = 0 ; i <= 15 ; i++ ) {
+            nm[0xc4] = "DHT";
+            for (int i = 0; i <= 15; i++) {
                 char MN[10];
-                sprintf(MN,"APP%d",i);
-                nm[0xe0+i] = MN;
-                if ( i != 4 ) {
-                    sprintf(MN,"SOF%d",i);
-                    nm[0xc0+i] = MN;
+                sprintf(MN, "APP%d", i);
+                nm[0xe0 + i] = MN;
+                if (i != 4) {
+                    sprintf(MN, "SOF%d", i);
+                    nm[0xc0 + i] = MN;
                 }
             }
 
             // which markers have a length field?
             bool mHasLength[256];
-            for ( int i = 0 ; i < 256 ; i ++ )
-                mHasLength[i]
-                  =   ( i >= sof0_ && i <= sof15_)
-                  ||  ( i >= app0_ && i <= (app0_ | 0x0F))
-                  ||  ( i == dht_  || i == dqt_ || i == dri_ || i == com_ || i == sos_ )
-                  ;
+            for (int i = 0; i < 256; i++)
+                mHasLength[i] = (i >= sof0_ && i <= sof15_) || (i >= app0_ && i <= (app0_ | 0x0F)) ||
+                                (i == dht_ || i == dqt_ || i == dri_ || i == com_ || i == sos_);
 
             // Container for the signature
-            bool        bExtXMP    = false;
-            long        bufRead    =  0;
-            const long  bufMinSize = 36;
-            DataBuf     buf(bufMinSize);
+            bool bExtXMP = false;
+            long bufRead = 0;
+            const long bufMinSize = 36;
+            DataBuf buf(bufMinSize);
 
             // Read section marker
             int marker = advanceToMarker();
-            if (marker < 0) throw Error(15);
+            if (marker < 0)
+                throw Error(15);
 
-            bool    done = false;
-            bool    first= true;
+            bool done = false;
+            bool first = true;
             while (!done) {
                 // print marker bytes
-                if ( first && bPrint ) {
+                if (first && bPrint) {
                     out << "STRUCTURE OF JPEG FILE: " << io_->path() << std::endl;
-                    out << " address | marker       |  length | data" << std::endl ;
+                    out << " address | marker       |  length | data" << std::endl;
                     REPORT_MARKER;
                 }
-                first    = false;
+                first = false;
                 bool bLF = bPrint;
 
                 // Read size and signature
                 std::memset(buf.pData_, 0x0, buf.size_);
                 bufRead = io_->read(buf.pData_, bufMinSize);
-                if (io_->error()) throw Error(14);
-                if (bufRead < 2) throw Error(15);
-                uint16_t size = mHasLength[marker] ? getUShort(buf.pData_, bigEndian) : 0 ;
-                if ( bPrint &&  mHasLength[marker] ) out << Internal::stringFormat(" | %7d ", size);
+                if (io_->error())
+                    throw Error(14);
+                if (bufRead < 2)
+                    throw Error(15);
+                uint16_t size = mHasLength[marker] ? getUShort(buf.pData_, bigEndian) : 0;
+                if (bPrint && mHasLength[marker])
+                    out << Internal::stringFormat(" | %7d ", size);
 
                 // print signature for APPn
                 if (marker >= app0_ && marker <= (app0_ | 0x0F)) {
                     // http://www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf p75
-                    const char* signature = (const char*) buf.pData_+2;
+                    const char* signature = (const char*)buf.pData_ + 2;
 
                     // 728 rmills@rmillsmbp:~/gnu/exiv2/ttt $ exiv2 -pS test/data/exiv2-bug922.jpg
                     // STRUCTURE OF JPEG FILE: test/data/exiv2-bug922.jpg
@@ -651,13 +657,13 @@ namespace Exiv2 {
                     //       2 | 0xe1 APP1  |     911 | Exif..MM.*.......%.........#....
                     //     915 | 0xe1 APP1  |     870 | http://ns.adobe.com/xap/1.0/.<x:
                     //    1787 | 0xe1 APP1  |   65460 | http://ns.adobe.com/xmp/extensio
-                    if ( option == kpsXMP && std::string(signature).find("http://ns.adobe.com/x")== 0 ) {
+                    if (option == kpsXMP && std::string(signature).find("http://ns.adobe.com/x") == 0) {
                         // extract XMP
-                        if ( size > 0 ) {
-                            io_->seek(-bufRead , BasicIo::cur);
-                            byte* xmp  = new byte[size+1];
-                            io_->read(xmp,size);
-                            int start = 0 ;
+                        if (size > 0) {
+                            io_->seek(-bufRead, BasicIo::cur);
+                            byte* xmp = new byte[size + 1];
+                            io_->read(xmp, size);
+                            int start = 0;
 
                             // http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf
                             // if we find HasExtendedXMP, set the flag and ignore this block
@@ -666,79 +672,80 @@ namespace Exiv2 {
                             // we could implement out of sequence with a dictionary of sequence/offset
                             // and dumping the XMP in a post read operation similar to kpsIptcErase
                             // for the moment, dumping 'on the fly' is working fine
-                            if ( ! bExtXMP ) {
-                                while (xmp[start]) start++;
+                            if (!bExtXMP) {
+                                while (xmp[start])
+                                    start++;
                                 start++;
-                                if ( ::strstr((char*)xmp+start,"HasExtendedXMP") ) {
-                                    start  = size ; // ignore this packet, we'll get on the next time around
+                                if (::strstr((char*)xmp + start, "HasExtendedXMP")) {
+                                    start = size;  // ignore this packet, we'll get on the next time around
                                     bExtXMP = true;
                                 }
                             } else {
-                                start = 2+35+32+4+4; // Adobe Spec, p19
+                                start = 2 + 35 + 32 + 4 + 4;  // Adobe Spec, p19
                             }
 
-                            out.write((const char*)(xmp+start),size-start);
-                            delete [] xmp;
+                            out.write((const char*)(xmp + start), size - start);
+                            delete[] xmp;
                             bufRead = size;
                             done = !bExtXMP;
                         }
-                    } else if ( option == kpsIccProfile && std::strcmp(signature,iccId_) == 0 ) {
+                    } else if (option == kpsIccProfile && std::strcmp(signature, iccId_) == 0) {
                         // extract ICCProfile
-                        if ( size > 0 ) {
-                            io_->seek(-bufRead, BasicIo::cur); // back to buffer (after marker)
-                            io_->seek(    14+2, BasicIo::cur); // step over header
-                            DataBuf   icc(size-(14+2));
-                            io_->read(             icc.pData_,icc.size_);
-                            out.write((const char*)icc.pData_,icc.size_);
+                        if (size > 0) {
+                            io_->seek(-bufRead, BasicIo::cur);  // back to buffer (after marker)
+                            io_->seek(14 + 2, BasicIo::cur);    // step over header
+                            DataBuf icc(size - (14 + 2));
+                            io_->read(icc.pData_, icc.size_);
+                            out.write((const char*)icc.pData_, icc.size_);
 #ifdef DEBUG
                             std::cout << "iccProfile size = " << icc.size_ << std::endl;
 #endif
                             bufRead = size;
                         }
-                    } else if ( option == kpsIptcErase && std::strcmp(signature,"Photoshop 3.0") == 0 ) {
+                    } else if (option == kpsIptcErase && std::strcmp(signature, "Photoshop 3.0") == 0) {
                         // delete IPTC data segment from JPEG
-                        if ( size > 0 ) {
-                            io_->seek(-bufRead , BasicIo::cur);
+                        if (size > 0) {
+                            io_->seek(-bufRead, BasicIo::cur);
                             iptcDataSegs.push_back(io_->tell());
                             iptcDataSegs.push_back(size);
                         }
-                    } else if ( bPrint ) {
-                        out << "| " << Internal::binaryToString(buf,size>32?32:size,size>0?2:0);
-                        if ( std::strcmp(signature,iccId_) == 0 ) {
-                            int chunk  = (int) signature[12];
-                            int chunks = (int) signature[13];
-                            out << Internal::stringFormat(" chunk %d/%d",chunk,chunks);
+                    } else if (bPrint) {
+                        out << "| " << Internal::binaryToString(buf, size > 32 ? 32 : size, size > 0 ? 2 : 0);
+                        if (std::strcmp(signature, iccId_) == 0) {
+                            int chunk = (int)signature[12];
+                            int chunks = (int)signature[13];
+                            out << Internal::stringFormat(" chunk %d/%d", chunk, chunks);
                         }
                     }
 
                     // for MPF: http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/MPF.html
                     // for FLIR: http://owl.phy.queensu.ca/~phil/exiftool/TagNames/FLIR.html
-                    bool bFlir = option == kpsRecursive && marker == (app0_+1) && std::strcmp(signature,"FLIR")==0;
-                    bool bExif = option == kpsRecursive && marker == (app0_+1) && std::strcmp(signature,"Exif")==0;
-                    bool bMPF  = option == kpsRecursive && marker == (app0_+2) && std::strcmp(signature,"MPF")==0;
-                    bool bPS   = option == kpsRecursive                        && std::strcmp(signature,"Photoshop 3.0")==0;
-                    if( bFlir || bExif || bMPF || bPS ) {
+                    bool bFlir = option == kpsRecursive && marker == (app0_ + 1) && std::strcmp(signature, "FLIR") == 0;
+                    bool bExif = option == kpsRecursive && marker == (app0_ + 1) && std::strcmp(signature, "Exif") == 0;
+                    bool bMPF = option == kpsRecursive && marker == (app0_ + 2) && std::strcmp(signature, "MPF") == 0;
+                    bool bPS = option == kpsRecursive && std::strcmp(signature, "Photoshop 3.0") == 0;
+                    if (bFlir || bExif || bMPF || bPS) {
                         // extract Exif data block which is tiff formatted
-                        if ( size > 0 ) {
+                        if (size > 0) {
                             out << std::endl;
 
                             // allocate storage and current file position
-                            byte*    exif      = new byte[size];
-                            uint32_t restore   = io_->tell();
+                            byte* exif = new byte[size];
+                            uint32_t restore = io_->tell();
 
                             // copy the data to memory
-                            io_->seek(-bufRead , BasicIo::cur);
-                            io_->read(exif,size);
-                            uint32_t start     = std::strcmp(signature,"Exif")==0 ? 8 : 6;
-                            uint32_t max       = (uint32_t) size -1;
+                            io_->seek(-bufRead, BasicIo::cur);
+                            io_->read(exif, size);
+                            uint32_t start = std::strcmp(signature, "Exif") == 0 ? 8 : 6;
+                            uint32_t max = (uint32_t)size - 1;
 
                             // is this an fff block?
-                            if ( bFlir ) {
-                                start = 0 ;
+                            if (bFlir) {
+                                start = 0;
                                 bFlir = false;
-                                while ( start < max ) {
-                                    if ( std::strcmp((const char*)(exif+start),"FFF")==0 ) {
-                                        bFlir = true ;
+                                while (start < max) {
+                                    if (std::strcmp((const char*)(exif + start), "FFF") == 0) {
+                                        bFlir = true;
                                         break;
                                     }
                                     start++;
@@ -747,78 +754,90 @@ namespace Exiv2 {
 
                             // there is a header in FLIR, followed by a tiff block
                             // Hunt down the tiff using brute force
-                            if ( bFlir ) {
+                            if (bFlir) {
                                 // FLIRFILEHEAD* pFFF = (FLIRFILEHEAD*) (exif+start) ;
-                                while ( start < max ) {
-                                    if ( exif[start] == 'I' && exif[start+1] == 'I' ) break;
-                                    if ( exif[start] == 'M' && exif[start+1] == 'M' ) break;
+                                while (start < max) {
+                                    if (exif[start] == 'I' && exif[start + 1] == 'I')
+                                        break;
+                                    if (exif[start] == 'M' && exif[start + 1] == 'M')
+                                        break;
                                     start++;
                                 }
-                                if ( start < max ) std::cout << "  FFF start = " << start << std::endl ;
+                                if ( start < max )
+                                    std::cout << "  FFF start = " << start << std::endl;
                                 // << " index = " << pFFF->dwIndexOff << std::endl;
                             }
 
-                            if ( bPS ) {
-                                IptcData::printStructure(out,exif,size,depth);
+                            if (bPS) {
+                                IptcData::printStructure(out, exif, size, depth);
                             } else {
                                 // create a copy on write memio object with the data, then print the structure
-                                BasicIo::AutoPtr p = BasicIo::AutoPtr(new MemIo(exif+start,size-start));
-                                if ( start < max ) printTiffStructure(*p,out,option,depth);
+                                BasicIo::AutoPtr p = BasicIo::AutoPtr(new MemIo(exif + start, size - start));
+                                if (start < max)
+                                    printTiffStructure(*p, out, option, depth);
                             }
 
                             // restore and clean up
-                            io_->seek(restore,Exiv2::BasicIo::beg);
-                            delete [] exif;
-                            bLF    = false;
+                            io_->seek(restore, Exiv2::BasicIo::beg);
+                            delete[] exif;
+                            bLF = false;
                         }
                     }
                 }
 
                 // print COM marker
-                if ( bPrint && marker == com_ ) {
-                    int n = (size-2)>32?32:size-2; // size includes 2 for the two bytes for size!
-                    out << "| " << Internal::binaryToString(buf,n,2); // start after the two bytes
+                if (bPrint && marker == com_) {
+                    int n = (size - 2) > 32 ? 32 : size - 2;             // size includes 2 for the two bytes for size!
+                    out << "| " << Internal::binaryToString(buf, n, 2);  // start after the two bytes
                 }
 
                 // Skip the segment if the size is known
-                if (io_->seek(size - bufRead, BasicIo::cur)) throw Error(14);
+                if (io_->seek(size - bufRead, BasicIo::cur))
+                    throw Error(14);
 
-                if ( bLF ) out << std::endl;
+                if (bLF)
+                    out << std::endl;
 
                 if (marker != sos_) {
                     // Read the beginning of the next segment
                     marker = advanceToMarker();
+                    enforce(marker>=0, kerNoImageInInputData);
                     REPORT_MARKER;
                 }
                 done |= marker == eoi_ || marker == sos_;
-                if ( done && bPrint ) out << std::endl;
+                if (done && bPrint)
+                    out << std::endl;
             }
         }
-        if ( option == kpsIptcErase && iptcDataSegs.size() ) {
+        if (option == kpsIptcErase && iptcDataSegs.size()) {
 #ifdef DEBUG
             std::cout << "iptc data blocks: " << iptcDataSegs.size() << std::endl;
-            uint32_t toggle = 0 ;
-            for ( Uint32Vector_i i = iptcDataSegs.begin(); i != iptcDataSegs.end() ; i++ ) {
-                std::cout << *i ;
-                if ( toggle++ % 2 ) std::cout << std::endl; else std::cout << ' ' ;
+            uint32_t toggle = 0;
+            for (Uint32Vector_i i = iptcDataSegs.begin(); i != iptcDataSegs.end(); i++) {
+                std::cout << *i;
+                if (toggle++ % 2)
+                    std::cout << std::endl;
+                else
+                    std::cout << ' ';
             }
 #endif
-            uint32_t count  = (uint32_t) iptcDataSegs.size();
+            uint32_t count = (uint32_t)iptcDataSegs.size();
 
             // figure out which blocks to copy
-            uint64_t* pos = new uint64_t[count+2];
-            pos[0]        = 0 ;
+            uint64_t* pos = new uint64_t[count + 2];
+            pos[0] = 0;
             // copy the data that is not iptc
             Uint32Vector_i it = iptcDataSegs.begin();
-            for ( uint64_t  i = 0 ; i < count ; i++ ) {
-                bool  bOdd  = (i%2)!=0;
-                bool  bEven = !bOdd;
-                pos[i+1]    = bEven ? *it : pos[i] + *it;
+            for (uint64_t i = 0; i < count; i++) {
+                bool bOdd = (i % 2) != 0;
+                bool bEven = !bOdd;
+                pos[i + 1] = bEven ? *it : pos[i] + *it;
                 it++;
             }
-            pos[count+1] = io_->size() - pos[count];
+            pos[count + 1] = io_->size() - pos[count];
 #ifdef DEBUG
-            for ( uint64_t i = 0 ; i < count+2 ; i++ ) std::cout << pos[i] << " " ;
+            for (uint64_t i = 0; i < count + 2; i++)
+                std::cout << pos[i] << " ";
             std::cout << std::endl;
 #endif
             // $ dd bs=1 skip=$((0)) count=$((13164)) if=ETH0138028.jpg of=E1.jpg
@@ -829,29 +848,30 @@ namespace Exiv2 {
             // binary copy io_ to a temporary file
             BasicIo::AutoPtr tempIo(new MemIo);
 
-            assert (tempIo.get() != 0);
-            for ( uint64_t i = 0 ; i < (count/2)+1 ; i++ ) {
-                uint64_t start  = pos[2*i]+2 ; // step JPG 2 byte marker
-                if ( start == 2 ) start = 0  ; // read the file 2 byte SOI
-                long length = (long) (pos[2*i+1] - start) ;
-                if ( length ) {
+            assert(tempIo.get() != 0);
+            for (uint64_t i = 0; i < (count / 2) + 1; i++) {
+                uint64_t start = pos[2 * i] + 2;  // step JPG 2 byte marker
+                if (start == 2)
+                    start = 0;  // read the file 2 byte SOI
+                long length = (long)(pos[2 * i + 1] - start);
+                if (length) {
 #ifdef DEBUG
-                    std::cout << start <<":"<< length << std::endl;
+                    std::cout << start << ":" << length << std::endl;
 #endif
-                    io_->seek(start,BasicIo::beg);
+                    io_->seek(start, BasicIo::beg);
                     DataBuf buf(length);
-                    io_->read(buf.pData_,buf.size_);
-                    tempIo->write(buf.pData_,buf.size_);
+                    io_->read(buf.pData_, buf.size_);
+                    tempIo->write(buf.pData_, buf.size_);
                 }
             }
-            delete [] pos;
+            delete[] pos;
 
             io_->seek(0, BasicIo::beg);
-            io_->transfer(*tempIo); // may throw
+            io_->transfer(*tempIo);  // may throw
             io_->seek(0, BasicIo::beg);
             readMetadata();
         }
-    } // JpegBase::printStructure
+    }  // JpegBase::printStructure
 
     void JpegBase::writeMetadata()
     {