libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

commit 65025629c248fe1adbef4956bba7a420ca4fa30b
parent 75ab892435b3b559596b0b900aac46230dc884df
Author: Christian Grothoff <christian@grothoff.org>
Date:   Wed, 14 Sep 2005 21:54:18 +0000

N. Durner wrote:

Hi Christian,

zumindest unter Windows bringt der exiv2 Extractor den Aufrufer bei größeren 
Dateien (hier 800 MB) zum Absturz.
Verursacht wird das Problem durch vector::reserve() in MemIo::MemIo() (basicio.
cpp).
Ich habe die Speicherverwendung so geändert, dass der Speicherblock für die zu 
extrahierende Datei nicht mehr für den exiv2 Extractor dupliziert werden muss.

Was meinst Du dazu (s. Anhang)?

Stefan: als Workaround kann libextractor_exiv2.dll einfach umbenannt werden, so dass das Modul nicht mehr geladen wird.

Grüße,

Nils


Diffstat:
MChangeLog | 4++++
Msrc/plugins/exiv2/basicio.cpp | 56+++++++++++++++++++++++++++++++++++++++++---------------
Msrc/plugins/exiv2/basicio.hpp | 14++++++++++----
Msrc/plugins/exiv2/image.cpp | 5++++-
4 files changed, 59 insertions(+), 20 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,7 @@ +Wed Sep 14 15:02:49 PDT 2005 + Avoid malloc/memcpy of file in exiv2 extractor (optimization, avoids + problems with very large files where malloc may run into problems). + Wed Sep 14 13:50:15 PDT 2005 Changed code for backwards-compatibility with zlib 1.1 (thanks to Ronan Melennec). diff --git a/src/plugins/exiv2/basicio.cpp b/src/plugins/exiv2/basicio.cpp @@ -339,10 +339,27 @@ namespace Exiv2 { { // If copying data is too slow it might be worth // creating a readonly MemIo variant - data_.reserve(size); - data_.assign(data, data+size); - idx_ = 0; + idx_ = 0; + data_ = (byte *) malloc(size); + if (data_) + { + memcpy(data_, data, size); + size_ = size; + isMalloced = true; + } + else + { + size = 0; + isMalloced = false; + } } + + void MemIo::wrap(const byte *data, long size) + { + data_ = (byte *) data; + size_ = size; + isMalloced = false; + } BasicIo::AutoPtr MemIo::temporary() const { @@ -352,15 +369,17 @@ namespace Exiv2 { void MemIo::checkSize(long wcount) { ByteVector::size_type need = wcount + idx_; - if (need > data_.size()) { - data_.resize(need); + if (need > size_) { + if (size_ > 0) + data_ = (byte *) realloc(data_, need); + else + data_ = (byte *) malloc(need); } } long MemIo::write(const byte* data, long wcount) { checkSize(wcount); - // According to Josuttis 6.2.3 this is safe memcpy(&data_[idx_], data, wcount); idx_ += wcount; return wcount; @@ -371,12 +390,20 @@ namespace Exiv2 { MemIo *memIo = dynamic_cast<MemIo*>(&src); if (memIo) { // Optimization if this is another instance of MemIo - data_.swap(memIo->data_); + if (memIo->isMalloced) + { + isMalloced = true; + memIo->isMalloced = false; + } + else + isMalloced = false; + + data_ = memIo->data_; idx_ = 0; } else{ // Generic reopen to reset position to start - data_.clear(); + free(data_); idx_ = 0; if (src.open() != 0) { throw Error(9, src.path(), strError()); @@ -422,10 +449,10 @@ namespace Exiv2 { } else { assert(pos == BasicIo::end); - newIdx = data_.size() + offset; + newIdx = size_ + offset; } - if (newIdx < 0 || newIdx > data_.size()) return 1; + if (newIdx < 0 || newIdx > size_) return 1; idx_ = newIdx; return 0; } @@ -437,7 +464,7 @@ namespace Exiv2 { long MemIo::size() const { - return (long)data_.size(); + return (long) size_; } int MemIo::open() @@ -466,10 +493,9 @@ namespace Exiv2 { long MemIo::read(byte* buf, long rcount) { - long avail = (long)(data_.size() - idx_); + long avail = (long)(size_ - idx_); long allow = std::min(rcount, avail); - // According to Josuttis 6.2.3 this is safe memcpy(buf, &data_[idx_], allow); idx_ += allow; return allow; @@ -477,7 +503,7 @@ namespace Exiv2 { int MemIo::getb() { - if (idx_ == data_.size()) + if (idx_ == size_) return EOF; return data_[idx_++]; } @@ -489,7 +515,7 @@ namespace Exiv2 { bool MemIo::eof() const { - return idx_ == data_.size(); + return idx_ == size_; } std::string MemIo::path() const diff --git a/src/plugins/exiv2/basicio.hpp b/src/plugins/exiv2/basicio.hpp @@ -476,7 +476,7 @@ namespace Exiv2 { //! @name Creators //@{ //! Default constructor that results in an empty object - MemIo() { idx_ = 0; } + MemIo() { idx_ = 0; isMalloced = false; data_ = NULL;} /*! @brief Constructor that accepts a block of memory to be copied. IO operations are performed on the copied memory. @@ -486,7 +486,10 @@ namespace Exiv2 { */ MemIo(const byte* data, long size); //! Destructor. Releases all managed memory - virtual ~MemIo() {} + ~MemIo() {if (isMalloced) free(data_);} + + void MemIo::wrap(const byte *data, long size); + //@} //! @name Manipulators @@ -631,8 +634,11 @@ namespace Exiv2 { typedef std::vector<byte> ByteVector; // DATA - ByteVector data_; - ByteVector::size_type idx_; + byte *data_; + ByteVector::size_type idx_, size_; + + // Was the buffer allocated? + bool isMalloced; // METHODS void checkSize(long wcount); diff --git a/src/plugins/exiv2/image.cpp b/src/plugins/exiv2/image.cpp @@ -142,7 +142,10 @@ namespace Exiv2 { Image::AutoPtr ImageFactory::open(const byte* data, long size) { - BasicIo::AutoPtr io(new MemIo(data, size)); + MemIo *mem = new MemIo(); + mem->wrap(data, size); + + BasicIo::AutoPtr io(mem); Image::AutoPtr image = open(io); // may throw if (image.get() == 0) throw Error(12); return image;