~ubuntu-branches/debian/lenny/exiv2/lenny

« back to all changes in this revision

Viewing changes to src/exif.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mark Purcell
  • Date: 2008-06-21 08:23:53 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20080621082353-b1n4w08trwfwbfl4
Tags: 0.17.1-1
* New upstream release
  - Library transition cleared on debian-release/ d-d-a
* Version 0.17 also fixes:
  - CVE-2008-2696: DoS via metadata in images (Closes: #486328)
  - crashes when fed with wrong file (Closes: #485670)
* Urgency medium for CVE fix
* debian/patches/gcc4.3.diff unecessary for gcc-4.3
* Add /usr/share/bug/exiv2/presubj message for reportbug(1)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
// ***************************************************************** -*- C++ -*-
2
2
/*
3
 
 * Copyright (C) 2004-2007 Andreas Huggel <ahuggel@gmx.net>
 
3
 * Copyright (C) 2004-2008 Andreas Huggel <ahuggel@gmx.net>
4
4
 *
5
5
 * This program is part of the Exiv2 distribution.
6
6
 *
20
20
 */
21
21
/*
22
22
  File:      exif.cpp
23
 
  Version:   $Rev: 1039 $
 
23
  Version:   $Rev: 1402 $
24
24
  Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
25
25
  History:   26-Jan-04, ahu: created
26
26
             11-Feb-04, ahu: isolated as a component
27
27
 */
28
28
// *****************************************************************************
29
29
#include "rcsid.hpp"
30
 
EXIV2_RCSID("@(#) $Id: exif.cpp 1039 2007-02-02 10:09:31Z ahuggel $")
 
30
EXIV2_RCSID("@(#) $Id: exif.cpp 1402 2008-04-04 15:50:11Z ahuggel $")
31
31
 
32
32
// Define DEBUG_MAKERNOTE to output debug information to std::cerr, e.g, by
33
33
// calling make like this: make DEFS=-DDEBUG_MAKERNOTE exif.o
82
82
                      uint32_t offset,
83
83
                      Exiv2::ByteOrder byteOrder);
84
84
 
85
 
    // Read file path into a DataBuf, which is returned.
86
 
    Exiv2::DataBuf readFile(const std::string& path);
87
 
 
88
85
}
89
86
 
90
87
// *****************************************************************************
114
111
        if (rhs.value_.get() != 0) value_ = rhs.value_->clone(); // deep copy
115
112
    }
116
113
 
 
114
    std::ostream& Exifdatum::write(std::ostream& os) const
 
115
    {
 
116
        return ExifTags::printTag(os, tag(), ifdId(), value());
 
117
    }
 
118
 
117
119
    const Value& Exifdatum::value() const
118
120
    {
119
121
        if (value_.get() == 0) throw Error(8);
215
217
        ExifData::const_iterator sizes;
216
218
        ExifKey key("Exif.Thumbnail.StripByteCounts");
217
219
        sizes = exifData.findKey(key);
218
 
        if (sizes == exifData.end()) return 2;
 
220
        if (sizes == exifData.end()) return 1;
219
221
 
220
 
        long totalSize = 0;
 
222
        uint32_t totalSize = 0;
221
223
        for (long i = 0; i < sizes->count(); ++i) {
222
 
            totalSize += sizes->toLong(i);
 
224
            uint32_t size = sizes->toLong(i);
 
225
            if (size > 0xffffffff - totalSize) return 1;
 
226
            totalSize += size;
223
227
        }
224
228
        DataBuf stripsBuf(totalSize);
225
229
 
228
232
        ExifData::iterator stripOffsets;
229
233
        key = ExifKey("Exif.Thumbnail.StripOffsets");
230
234
        stripOffsets = exifData.findKey(key);
231
 
        if (stripOffsets == exifData.end()) return 2;
232
 
        if (stripOffsets->count() != sizes->count()) return 2;
 
235
        if (stripOffsets == exifData.end()) return 1;
 
236
        if (stripOffsets->count() != sizes->count()) return 1;
233
237
 
234
238
        std::ostringstream os; // for the strip offsets
235
 
        long currentOffset = 0;
236
 
        long firstOffset = stripOffsets->toLong(0);
237
 
        long lastOffset = 0;
238
 
        long lastSize = 0;
 
239
        uint32_t currentOffset = 0;
 
240
        uint32_t firstOffset = stripOffsets->toLong(0);
 
241
        uint32_t lastOffset = 0;
 
242
        uint32_t lastSize = 0;
239
243
        for (long i = 0; i < stripOffsets->count(); ++i) {
240
 
            long offset = stripOffsets->toLong(i);
 
244
            uint32_t offset = stripOffsets->toLong(i);
241
245
            lastOffset = offset;
242
 
            long size = sizes->toLong(i);
 
246
            uint32_t size = sizes->toLong(i);
243
247
            lastSize = size;
244
 
            if (len < offset + size) return 1;
245
 
 
246
 
            memcpy(stripsBuf.pData_ + currentOffset, buf + offset, size);
 
248
            if (   size > 0xffffffff - offset
 
249
                || static_cast<uint32_t>(len) < offset + size) {
 
250
                return 2;
 
251
            }
 
252
            std::memcpy(stripsBuf.pData_ + currentOffset, buf + offset, size);
247
253
            os << currentOffset << " ";
248
254
            currentOffset += size;
249
255
        }
303
309
        ExifKey key("Exif.Thumbnail.JPEGInterchangeFormat");
304
310
        ExifData::iterator format = exifData.findKey(key);
305
311
        if (format == exifData.end()) return 1;
306
 
        long offset = format->toLong();
 
312
        uint32_t offset = format->toLong();
307
313
        key = ExifKey("Exif.Thumbnail.JPEGInterchangeFormatLength");
308
314
        ExifData::const_iterator length = exifData.findKey(key);
309
315
        if (length == exifData.end()) return 1;
310
 
        long size = length->toLong();
311
 
        if (len < offset + size) return 2;
 
316
        uint32_t size = length->toLong();
 
317
        if (   size > 0xffffffff - offset
 
318
            || static_cast<uint32_t>(len) < offset + size) {
 
319
            return 2;
 
320
        }
312
321
        format->setDataArea(buf + offset, size);
313
322
        format->setValue("0");
314
323
        if (pIfd1) {
351
360
    {
352
361
        pData_ = new byte[rhs.size_];
353
362
        size_ = rhs.size_;
354
 
        memcpy(pData_, rhs.pData_, rhs.size_);
 
363
        std::memcpy(pData_, rhs.pData_, rhs.size_);
355
364
 
356
365
        if (rhs.pTiffHeader_) {
357
366
            pTiffHeader_ = new TiffHeader(*rhs.pTiffHeader_);
404
413
        delete[] pData_;
405
414
        pData_ = new byte[rhs.size_];
406
415
        size_ = rhs.size_;
407
 
        memcpy(pData_, rhs.pData_, rhs.size_);
 
416
        std::memcpy(pData_, rhs.pData_, rhs.size_);
408
417
 
409
418
        delete pTiffHeader_;
410
419
        pTiffHeader_ = 0;
469
478
 
470
479
        // Copy the data buffer
471
480
        DataBuf tmpData(len);
472
 
        memcpy(tmpData.pData_, buf, len);
 
481
        std::memcpy(tmpData.pData_, buf, len);
473
482
 
474
483
        // Read the TIFF header
475
484
        std::auto_ptr<TiffHeader> tmpTiffHeader(new TiffHeader);
595
604
        if (pIopIfd_) add(pIopIfd_->begin(), pIopIfd_->end(), byteOrder());
596
605
        if (pGpsIfd_) add(pGpsIfd_->begin(), pGpsIfd_->end(), byteOrder());
597
606
        if (pIfd1_)   add(pIfd1_->begin(),   pIfd1_->end(),   byteOrder());
598
 
        // Read the thumbnail (but don't worry whether it was successful or not)
599
 
        readThumbnail();
 
607
        // Finally, read the thumbnail
 
608
        rc = readThumbnail();
 
609
        if (0 < rc) {
 
610
#ifndef SUPPRESS_WARNINGS
 
611
            std::cerr << "Warning: Failed to read thumbnail, rc = "
 
612
                      << rc << "\n";
 
613
#endif
 
614
        }
600
615
 
601
616
        return 0;
602
617
    } // ExifData::load
612
627
            std::cerr << "->>>>>> using non-intrusive writing <<<<<<-\n";
613
628
#endif
614
629
            buf.alloc(size_);
615
 
            memcpy(buf.pData_, pData_, size_);
 
630
            std::memcpy(buf.pData_, pData_, size_);
616
631
        }
617
632
        // Else we have to do it the hard way...
618
633
        else {
647
662
            e.setIfdId(exifIfd.ifdId());
648
663
            e.setTag(0x927c);
649
664
            DataBuf tmpBuf(makerNote->size());
650
 
            memset(tmpBuf.pData_, 0x0, tmpBuf.size_);
 
665
            std::memset(tmpBuf.pData_, 0x0, tmpBuf.size_);
651
666
            e.setValue(undefined, tmpBuf.size_, tmpBuf.pData_, tmpBuf.size_);
652
667
            exifIfd.erase(0x927c);
653
668
            exifIfd.add(e);
944
959
                                                + pGpsIfd_->dataSize());
945
960
            }
946
961
            if (   maxOffset > pIfd1_->offset()
947
 
                || maxOffset > pIfd1_->dataOffset() && pIfd1_->dataOffset() > 0)
 
962
                || (maxOffset > pIfd1_->dataOffset() && pIfd1_->dataOffset() > 0))
948
963
                rc = false;
949
964
            /*
950
965
               Todo: Removed condition from the above if(). Should be re-added...
1271
1286
        makerNote->add(e);
1272
1287
    } // addToMakerNote
1273
1288
 
1274
 
    std::ostream& operator<<(std::ostream& os, const Exifdatum& md)
1275
 
    {
1276
 
        return ExifTags::printTag(os, md.tag(), md.ifdId(), md.value());
1277
 
    }
1278
1289
}                                       // namespace Exiv2
1279
1290
 
1280
1291
// *****************************************************************************
1300
1311
        pos->setValue(offset, byteOrder);
1301
1312
    }
1302
1313
 
1303
 
    Exiv2::DataBuf readFile(const std::string& path)
1304
 
    {
1305
 
        Exiv2::FileIo file(path);
1306
 
        if (file.open("rb") != 0) {
1307
 
            throw Exiv2::Error(10, path, "rb", Exiv2::strError());
1308
 
        }
1309
 
        struct stat st;
1310
 
        if (0 != stat(path.c_str(), &st)) {
1311
 
            throw Exiv2::Error(2, path, Exiv2::strError(), "::stat");
1312
 
        }
1313
 
        Exiv2::DataBuf buf(st.st_size);
1314
 
        long len = file.read(buf.pData_, buf.size_);
1315
 
        if (len != buf.size_) {
1316
 
            throw Exiv2::Error(2, path, Exiv2::strError(), "FileIo::read");
1317
 
        }
1318
 
        return buf;
1319
 
    }
1320
 
 
1321
1314
}