In exiv2 0.28.x, DataBuf is only a wrapper for std::vector.
Exiv2::DataBuf::data() returns a shallow copy of its underlying
data. On Exiv2::DataBuf::reset(), all of its data is invalidated,
includes the data returned by Exiv2::DataBuf::data(). Thus, all usages
of said data is use-after-free, attempt to use its later is double-free.
Make a copy ourselves instead. This method works for the old exiv2, too.
Since Exiv2::PreviewImage::size() is available from forever, and both
Exiv2::PreviewImage::copy() and Exiv2::PreviewImage::pData() are
introduced in a same change (commit
9578e8123 in 2008).
Fixes: #1201
Fixes: https://github.com/void-linux/void-packages/issues/47547
Exiv2::PreviewImage image = pm.getPreviewImage(*pos);
Exiv2::PreviewImage image = pm.getPreviewImage(*pos);
- Exiv2::DataBuf buf = image.copy();
-
-#if EXIV2_TEST_VERSION(0,28,0)
- *data_len = buf.size();
- auto b = buf.data();
- buf.reset();
- return b;
-#else
- std::pair<Exiv2::byte*, long> p = buf.release();
-
- *data_len = p.second;
- return p.first;
-#endif
+ // Let's not touch data_len until we finish copy.
+ // Just in case we run into OOM.
+ size_t img_sz = image.size();
+ Exiv2::byte* b = new Exiv2::byte[img_sz];
+ std::copy_n(image.pData(), img_sz, b);
+ *data_len = img_sz;
+ return b;