namespace enforce.hpp functions to Internal

Signed-off-by: Rosen Penev <rosenp@gmail.com>
main
Rosen Penev 2 years ago
parent 77834807c2
commit 376638259d

@ -1413,30 +1413,32 @@ int Adjust::adjustDateTime(Exiv2::ExifData& exifData, const std::string& key, co
} }
// bounds checking for yearAdjustment_ // bounds checking for yearAdjustment_
enforce<std::overflow_error>(yearAdjustment_ >= std::numeric_limits<decltype(tm.tm_year)>::min(), Exiv2::Internal::enforce<std::overflow_error>(yearAdjustment_ >= std::numeric_limits<decltype(tm.tm_year)>::min(),
"year adjustment too low"); "year adjustment too low");
enforce<std::overflow_error>(yearAdjustment_ <= std::numeric_limits<decltype(tm.tm_year)>::max(), Exiv2::Internal::enforce<std::overflow_error>(yearAdjustment_ <= std::numeric_limits<decltype(tm.tm_year)>::max(),
"year adjustment too high"); "year adjustment too high");
const auto yearAdjustment = static_cast<decltype(tm.tm_year)>(yearAdjustment_); const auto yearAdjustment = static_cast<decltype(tm.tm_year)>(yearAdjustment_);
// bounds checking for monthAdjustment_ // bounds checking for monthAdjustment_
enforce<std::overflow_error>(monthAdjustment_ >= std::numeric_limits<decltype(tm.tm_mon)>::min(), Exiv2::Internal::enforce<std::overflow_error>(monthAdjustment_ >= std::numeric_limits<decltype(tm.tm_mon)>::min(),
"month adjustment too low"); "month adjustment too low");
enforce<std::overflow_error>(monthAdjustment_ <= std::numeric_limits<decltype(tm.tm_mon)>::max(), Exiv2::Internal::enforce<std::overflow_error>(monthAdjustment_ <= std::numeric_limits<decltype(tm.tm_mon)>::max(),
"month adjustment too high"); "month adjustment too high");
const auto monthAdjustment = static_cast<decltype(tm.tm_mon)>(monthAdjustment_); const auto monthAdjustment = static_cast<decltype(tm.tm_mon)>(monthAdjustment_);
// bounds checking for dayAdjustment_ // bounds checking for dayAdjustment_
static constexpr time_t secondsInDay = 24 * 60 * 60; static constexpr time_t secondsInDay = 24 * 60 * 60;
enforce<std::overflow_error>(dayAdjustment_ >= std::numeric_limits<time_t>::min() / secondsInDay, Exiv2::Internal::enforce<std::overflow_error>(dayAdjustment_ >= std::numeric_limits<time_t>::min() / secondsInDay,
"day adjustment too low"); "day adjustment too low");
enforce<std::overflow_error>(dayAdjustment_ <= std::numeric_limits<time_t>::max() / secondsInDay, Exiv2::Internal::enforce<std::overflow_error>(dayAdjustment_ <= std::numeric_limits<time_t>::max() / secondsInDay,
"day adjustment too high"); "day adjustment too high");
const auto dayAdjustment = static_cast<time_t>(dayAdjustment_); const auto dayAdjustment = static_cast<time_t>(dayAdjustment_);
// bounds checking for adjustment_ // bounds checking for adjustment_
enforce<std::overflow_error>(adjustment_ >= std::numeric_limits<time_t>::min(), "seconds adjustment too low"); Exiv2::Internal::enforce<std::overflow_error>(adjustment_ >= std::numeric_limits<time_t>::min(),
enforce<std::overflow_error>(adjustment_ <= std::numeric_limits<time_t>::max(), "seconds adjustment too high"); "seconds adjustment too low");
Exiv2::Internal::enforce<std::overflow_error>(adjustment_ <= std::numeric_limits<time_t>::max(),
"seconds adjustment too high");
const auto adjustment = static_cast<time_t>(adjustment_); const auto adjustment = static_cast<time_t>(adjustment_);
const auto monOverflow = Safe::add(tm.tm_mon, monthAdjustment) / 12; const auto monOverflow = Safe::add(tm.tm_mon, monthAdjustment) / 12;

@ -46,23 +46,23 @@ void mini1(const char* path) {
// Write nothing to a new structure, without a previous binary image // Write nothing to a new structure, without a previous binary image
wm = ExifParser::encode(blob, nullptr, 0, bigEndian, exifData); wm = ExifParser::encode(blob, nullptr, 0, bigEndian, exifData);
enforce(wm == wmIntrusive, Exiv2::ErrorCode::kerErrorMessage, "encode returned an unexpected value"); Internal::enforce(wm == wmIntrusive, Exiv2::ErrorCode::kerErrorMessage, "encode returned an unexpected value");
std::cout << "Test 1: Writing empty Exif data without original binary data: ok.\n"; std::cout << "Test 1: Writing empty Exif data without original binary data: ok.\n";
// Write nothing, this time with a previous binary image // Write nothing, this time with a previous binary image
DataBuf buf = readFile(path); DataBuf buf = readFile(path);
wm = ExifParser::encode(blob, buf.c_data(), buf.size(), bigEndian, exifData); wm = ExifParser::encode(blob, buf.c_data(), buf.size(), bigEndian, exifData);
enforce(wm == wmIntrusive, Exiv2::ErrorCode::kerErrorMessage, "encode returned an unexpected value"); Internal::enforce(wm == wmIntrusive, Exiv2::ErrorCode::kerErrorMessage, "encode returned an unexpected value");
std::cout << "Test 2: Writing empty Exif data with original binary data: ok.\n"; std::cout << "Test 2: Writing empty Exif data with original binary data: ok.\n";
// Write something to a new structure, without a previous binary image // Write something to a new structure, without a previous binary image
exifData["Exif.Photo.DateTimeOriginal"] = "Yesterday at noon"; exifData["Exif.Photo.DateTimeOriginal"] = "Yesterday at noon";
wm = ExifParser::encode(blob, nullptr, 0, bigEndian, exifData); wm = ExifParser::encode(blob, nullptr, 0, bigEndian, exifData);
enforce(wm == wmIntrusive, Exiv2::ErrorCode::kerErrorMessage, "encode returned an unexpected value"); Internal::enforce(wm == wmIntrusive, Exiv2::ErrorCode::kerErrorMessage, "encode returned an unexpected value");
std::cout << "Test 3: Wrote non-empty Exif data without original binary data:\n"; std::cout << "Test 3: Wrote non-empty Exif data without original binary data:\n";
exifData.clear(); exifData.clear();
ByteOrder bo = ExifParser::decode(exifData, blob.data(), blob.size()); ByteOrder bo = ExifParser::decode(exifData, blob.data(), blob.size());
enforce(bo == bigEndian, Exiv2::ErrorCode::kerErrorMessage, "decode returned an unexpected value"); Internal::enforce(bo == bigEndian, Exiv2::ErrorCode::kerErrorMessage, "decode returned an unexpected value");
print(exifData); print(exifData);
} }

@ -66,13 +66,13 @@ void ReplaceStringInPlace(std::string& subject, std::string_view search, std::st
namespace Exiv2 { namespace Exiv2 {
void BasicIo::readOrThrow(byte* buf, size_t rcount, ErrorCode err) { void BasicIo::readOrThrow(byte* buf, size_t rcount, ErrorCode err) {
const size_t nread = read(buf, rcount); const size_t nread = read(buf, rcount);
enforce(nread == rcount, err); Internal::enforce(nread == rcount, err);
enforce(!error(), err); Internal::enforce(!error(), err);
} }
void BasicIo::seekOrThrow(int64_t offset, Position pos, ErrorCode err) { void BasicIo::seekOrThrow(int64_t offset, Position pos, ErrorCode err) {
const int r = seek(offset, pos); const int r = seek(offset, pos);
enforce(r == 0, err); Internal::enforce(r == 0, err);
} }
//! Internal Pimpl structure of class FileIo. //! Internal Pimpl structure of class FileIo.
@ -470,7 +470,7 @@ int FileIo::seek(int64_t offset, Position pos) {
size_t FileIo::tell() const { size_t FileIo::tell() const {
const long pos = std::ftell(p_->fp_); const long pos = std::ftell(p_->fp_);
enforce(pos >= 0, ErrorCode::kerInputDataReadFailed); Internal::enforce(pos >= 0, ErrorCode::kerInputDataReadFailed);
return static_cast<size_t>(pos); return static_cast<size_t>(pos);
} }

@ -249,7 +249,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
byte hdrbuf[2 * sizeof(uint32_t)]; byte hdrbuf[2 * sizeof(uint32_t)];
size_t hdrsize = sizeof(hdrbuf); size_t hdrsize = sizeof(hdrbuf);
enforce(hdrsize <= static_cast<size_t>(pbox_end - address), Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(hdrsize <= static_cast<size_t>(pbox_end - address), Exiv2::ErrorCode::kerCorruptedMetadata);
if (io_->read(reinterpret_cast<byte*>(&hdrbuf), sizeof(hdrbuf)) != sizeof(hdrbuf)) if (io_->read(reinterpret_cast<byte*>(&hdrbuf), sizeof(hdrbuf)) != sizeof(hdrbuf))
return pbox_end; return pbox_end;
@ -268,7 +268,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
if (box_length == 1) { if (box_length == 1) {
// The box size is encoded as a uint64_t, so we need to read another 8 bytes. // The box size is encoded as a uint64_t, so we need to read another 8 bytes.
hdrsize += 8; hdrsize += 8;
enforce(hdrsize <= static_cast<size_t>(pbox_end - address), Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(hdrsize <= static_cast<size_t>(pbox_end - address), Exiv2::ErrorCode::kerCorruptedMetadata);
DataBuf data(8); DataBuf data(8);
io_->read(data.data(), data.size()); io_->read(data.data(), data.size());
box_length = data.read_uint64(0, endian_); box_length = data.read_uint64(0, endian_);
@ -276,8 +276,8 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
// read data in box and restore file position // read data in box and restore file position
const size_t restore = io_->tell(); const size_t restore = io_->tell();
enforce(box_length >= hdrsize, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(box_length >= hdrsize, Exiv2::ErrorCode::kerCorruptedMetadata);
enforce(box_length - hdrsize <= pbox_end - restore, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(box_length - hdrsize <= pbox_end - restore, Exiv2::ErrorCode::kerCorruptedMetadata);
const auto buffer_size = box_length - hdrsize; const auto buffer_size = box_length - hdrsize;
if (skipBox(box_type)) { if (skipBox(box_type)) {
@ -299,7 +299,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
uint32_t flags = 0; uint32_t flags = 0;
if (fullBox(box_type)) { if (fullBox(box_type)) {
enforce(data.size() - skip >= 4, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(data.size() - skip >= 4, Exiv2::ErrorCode::kerCorruptedMetadata);
flags = data.read_uint32(skip, endian_); // version/flags flags = data.read_uint32(skip, endian_); // version/flags
version = static_cast<uint8_t>(flags >> 24); version = static_cast<uint8_t>(flags >> 24);
flags &= 0x00ffffff; flags &= 0x00ffffff;
@ -309,7 +309,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
switch (box_type) { switch (box_type) {
// See notes in skipBox() // See notes in skipBox()
case TAG_ftyp: { case TAG_ftyp: {
enforce(data.size() >= 4, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(data.size() >= 4, Exiv2::ErrorCode::kerCorruptedMetadata);
fileType_ = data.read_uint32(0, endian_); fileType_ = data.read_uint32(0, endian_);
if (bTrace) { if (bTrace) {
out << "brand: " << toAscii(fileType_); out << "brand: " << toAscii(fileType_);
@ -323,7 +323,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
bLF = false; bLF = false;
} }
enforce(data.size() - skip >= 2, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(data.size() - skip >= 2, Exiv2::ErrorCode::kerCorruptedMetadata);
uint16_t n = data.read_uint16(skip, endian_); uint16_t n = data.read_uint16(skip, endian_);
skip += 2; skip += 2;
@ -335,7 +335,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
// 8.11.6.2 // 8.11.6.2
case TAG_infe: { // .__._.__hvc1_ 2 0 0 1 0 1 0 0 104 118 99 49 0 case TAG_infe: { // .__._.__hvc1_ 2 0 0 1 0 1 0 0 104 118 99 49 0
enforce(data.size() - skip >= 8, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(data.size() - skip >= 8, Exiv2::ErrorCode::kerCorruptedMetadata);
/* getULong (data.pData_+skip,endian_) ; */ skip += 4; /* getULong (data.pData_+skip,endian_) ; */ skip += 4;
uint16_t ID = data.read_uint16(skip, endian_); uint16_t ID = data.read_uint16(skip, endian_);
skip += 2; skip += 2;
@ -344,7 +344,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
// Check that the string has a '\0' terminator. // Check that the string has a '\0' terminator.
const char* str = data.c_str(skip); const char* str = data.c_str(skip);
const size_t maxlen = data.size() - skip; const size_t maxlen = data.size() - skip;
enforce(maxlen > 0 && strnlen(str, maxlen) < maxlen, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(maxlen > 0 && strnlen(str, maxlen) < maxlen, Exiv2::ErrorCode::kerCorruptedMetadata);
std::string name(str); std::string name(str);
if (name.find("Exif") != std::string::npos) { // "Exif" or "ExifExif" if (name.find("Exif") != std::string::npos) { // "Exif" or "ExifExif"
exifID_ = ID; exifID_ = ID;
@ -393,7 +393,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
// 8.11.3.1 // 8.11.3.1
case TAG_iloc: { case TAG_iloc: {
enforce(data.size() - skip >= 2, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(data.size() - skip >= 2, Exiv2::ErrorCode::kerCorruptedMetadata);
uint8_t u = data.read_uint8(skip++); uint8_t u = data.read_uint8(skip++);
uint16_t offsetSize = u >> 4; uint16_t offsetSize = u >> 4;
uint16_t lengthSize = u & 0xF; uint16_t lengthSize = u & 0xF;
@ -406,7 +406,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
#else #else
skip++; skip++;
#endif #endif
enforce(data.size() - skip >= (version < 2u ? 2u : 4u), Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(data.size() - skip >= (version < 2u ? 2u : 4u), Exiv2::ErrorCode::kerCorruptedMetadata);
uint32_t itemCount = version < 2 ? data.read_uint16(skip, endian_) : data.read_uint32(skip, endian_); uint32_t itemCount = version < 2 ? data.read_uint16(skip, endian_) : data.read_uint32(skip, endian_);
skip += version < 2 ? 2 : 4; skip += version < 2 ? 2 : 4;
if (itemCount && itemCount < box_length / 14 && offsetSize == 4 && lengthSize == 4 && if (itemCount && itemCount < box_length / 14 && offsetSize == 4 && lengthSize == 4 &&
@ -419,8 +419,8 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
size_t base = skip; size_t base = skip;
for (uint32_t i = 0; i < itemCount; i++) { for (uint32_t i = 0; i < itemCount; i++) {
skip = base + i * step; // move in 14, 16 or 18 byte steps skip = base + i * step; // move in 14, 16 or 18 byte steps
enforce(data.size() - skip >= (version > 2u ? 4u : 2u), Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(data.size() - skip >= (version > 2u ? 4u : 2u), Exiv2::ErrorCode::kerCorruptedMetadata);
enforce(data.size() - skip >= step, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(data.size() - skip >= step, Exiv2::ErrorCode::kerCorruptedMetadata);
uint32_t ID = version > 2 ? data.read_uint32(skip, endian_) : data.read_uint16(skip, endian_); uint32_t ID = version > 2 ? data.read_uint32(skip, endian_) : data.read_uint16(skip, endian_);
auto offset = [this, &data, skip, step] { auto offset = [this, &data, skip, step] {
if (step == 14 || step == 16) if (step == 14 || step == 16)
@ -445,7 +445,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
} break; } break;
case TAG_ispe: { case TAG_ispe: {
enforce(data.size() - skip >= 12, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(data.size() - skip >= 12, Exiv2::ErrorCode::kerCorruptedMetadata);
skip += 4; skip += 4;
uint32_t width = data.read_uint32(skip, endian_); uint32_t width = data.read_uint32(skip, endian_);
skip += 4; skip += 4;
@ -524,7 +524,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
parseXmp(buffer_size, io_->tell()); parseXmp(buffer_size, io_->tell());
break; break;
case TAG_brob: { case TAG_brob: {
enforce(data.size() >= 4, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(data.size() >= 4, Exiv2::ErrorCode::kerCorruptedMetadata);
uint32_t realType = data.read_uint32(0, endian_); uint32_t realType = data.read_uint32(0, endian_);
if (bTrace) { if (bTrace) {
out << "type: " << toAscii(realType); out << "type: " << toAscii(realType);
@ -534,7 +534,7 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
brotliUncompress(data.c_data(4), data.size() - 4, arr); brotliUncompress(data.c_data(4), data.size() - 4, arr);
if (realType == TAG_exif) { if (realType == TAG_exif) {
uint32_t offset = Safe::add(arr.read_uint32(0, endian_), 4u); uint32_t offset = Safe::add(arr.read_uint32(0, endian_), 4u);
enforce(Safe::add(offset, 4u) < arr.size(), Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(Safe::add(offset, 4u) < arr.size(), Exiv2::ErrorCode::kerCorruptedMetadata);
Internal::TiffParserWorker::decode(exifData(), iptcData(), xmpData(), arr.c_data(offset), arr.size() - offset, Internal::TiffParserWorker::decode(exifData(), iptcData(), xmpData(), arr.c_data(offset), arr.size() - offset,
Internal::Tag::root, Internal::TiffMapping::findDecoder); Internal::Tag::root, Internal::TiffMapping::findDecoder);
} else if (realType == TAG_xml) { } else if (realType == TAG_xml) {
@ -580,10 +580,11 @@ uint64_t BmffImage::boxHandler(std::ostream& out /* = std::cout*/, Exiv2::PrintS
} }
void BmffImage::parseTiff(uint32_t root_tag, uint64_t length, uint64_t start) { void BmffImage::parseTiff(uint32_t root_tag, uint64_t length, uint64_t start) {
enforce(start <= io_->size(), ErrorCode::kerCorruptedMetadata); Internal::enforce(start <= io_->size(), ErrorCode::kerCorruptedMetadata);
enforce(length <= io_->size() - start, ErrorCode::kerCorruptedMetadata); Internal::enforce(length <= io_->size() - start, ErrorCode::kerCorruptedMetadata);
enforce(start <= static_cast<uint64_t>(std::numeric_limits<int64_t>::max()), ErrorCode::kerCorruptedMetadata); Internal::enforce(start <= static_cast<uint64_t>(std::numeric_limits<int64_t>::max()),
enforce(length <= std::numeric_limits<size_t>::max(), ErrorCode::kerCorruptedMetadata); ErrorCode::kerCorruptedMetadata);
Internal::enforce(length <= std::numeric_limits<size_t>::max(), ErrorCode::kerCorruptedMetadata);
// read and parse exif data // read and parse exif data
const size_t restore = io_->tell(); const size_t restore = io_->tell();
@ -608,8 +609,8 @@ void BmffImage::parseTiff(uint32_t root_tag, uint64_t length, uint64_t start) {
void BmffImage::parseTiff(uint32_t root_tag, uint64_t length) { void BmffImage::parseTiff(uint32_t root_tag, uint64_t length) {
if (length > 8) { if (length > 8) {
enforce(length - 8 <= io_->size() - io_->tell(), ErrorCode::kerCorruptedMetadata); Internal::enforce(length - 8 <= io_->size() - io_->tell(), ErrorCode::kerCorruptedMetadata);
enforce(length - 8 <= std::numeric_limits<size_t>::max(), ErrorCode::kerCorruptedMetadata); Internal::enforce(length - 8 <= std::numeric_limits<size_t>::max(), ErrorCode::kerCorruptedMetadata);
DataBuf data(static_cast<size_t>(length - 8u)); DataBuf data(static_cast<size_t>(length - 8u));
const size_t bufRead = io_->read(data.data(), data.size()); const size_t bufRead = io_->read(data.data(), data.size());
@ -624,8 +625,8 @@ void BmffImage::parseTiff(uint32_t root_tag, uint64_t length) {
} }
void BmffImage::parseXmp(uint64_t length, uint64_t start) { void BmffImage::parseXmp(uint64_t length, uint64_t start) {
enforce(start <= io_->size(), ErrorCode::kerCorruptedMetadata); Internal::enforce(start <= io_->size(), ErrorCode::kerCorruptedMetadata);
enforce(length <= io_->size() - start, ErrorCode::kerCorruptedMetadata); Internal::enforce(length <= io_->size() - start, ErrorCode::kerCorruptedMetadata);
const size_t restore = io_->tell(); const size_t restore = io_->tell();
io_->seek(static_cast<int64_t>(start), BasicIo::beg); io_->seek(static_cast<int64_t>(start), BasicIo::beg);
@ -651,7 +652,7 @@ void BmffImage::parseCr3Preview(DataBuf& data, std::ostream& out, bool bTrace, u
size_t height_offset, size_t size_offset, size_t relative_position) { size_t height_offset, size_t size_offset, size_t relative_position) {
// Derived from https://github.com/lclevy/canon_cr3 // Derived from https://github.com/lclevy/canon_cr3
const size_t here = io_->tell(); const size_t here = io_->tell();
enforce(here <= std::numeric_limits<size_t>::max() - relative_position, ErrorCode::kerCorruptedMetadata); Internal::enforce(here <= std::numeric_limits<size_t>::max() - relative_position, ErrorCode::kerCorruptedMetadata);
NativePreview nativePreview; NativePreview nativePreview;
nativePreview.position_ = here + relative_position; nativePreview.position_ = here + relative_position;
nativePreview.width_ = data.read_uint16(width_offset, endian_); nativePreview.width_ = data.read_uint16(width_offset, endian_);

@ -22,6 +22,7 @@
#include "error.hpp" #include "error.hpp"
namespace Exiv2::Internal {
/*! /*!
* @brief Ensure that condition is true, otherwise throw an exception of the * @brief Ensure that condition is true, otherwise throw an exception of the
* type exception_t * type exception_t
@ -81,3 +82,4 @@ inline void enforce(bool condition, Exiv2::ErrorCode err_code, const T& arg1, co
throw Exiv2::Error(err_code, arg1, arg2, arg3); throw Exiv2::Error(err_code, arg1, arg2, arg3);
} }
} }
} // namespace Exiv2::Internal

@ -238,7 +238,7 @@ std::string strError() {
#else #else
char buf[n] = {}; char buf[n] = {};
const int ret = strerror_r(error, buf, n); const int ret = strerror_r(error, buf, n);
enforce(ret != ERANGE, Exiv2::ErrorCode::kerCallFailed); Internal::enforce(ret != ERANGE, Exiv2::ErrorCode::kerCallFailed);
#endif #endif
os << buf; os << buf;
// Issue# 908. // Issue# 908.

@ -308,7 +308,7 @@ void Image::printIFDStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStruct
io.readOrThrow(dir.data(), 2, ErrorCode::kerCorruptedMetadata); io.readOrThrow(dir.data(), 2, ErrorCode::kerCorruptedMetadata);
uint16_t dirLength = byteSwap2(dir, 0, bSwap); uint16_t dirLength = byteSwap2(dir, 0, bSwap);
// Prevent infinite loops. (GHSA-m479-7frc-gqqg) // Prevent infinite loops. (GHSA-m479-7frc-gqqg)
enforce(dirLength > 0, ErrorCode::kerCorruptedMetadata); Internal::enforce(dirLength > 0, ErrorCode::kerCorruptedMetadata);
if (dirLength > 500) // tooBig if (dirLength > 500) // tooBig
throw Error(ErrorCode::kerTiffDirectoryTooLarge); throw Error(ErrorCode::kerTiffDirectoryTooLarge);
@ -384,7 +384,7 @@ void Image::printIFDStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStruct
throw Error(ErrorCode::kerInvalidMalloc); throw Error(ErrorCode::kerInvalidMalloc);
} }
// Overflow check // Overflow check
enforce(allocate64 <= std::numeric_limits<size_t>::max(), ErrorCode::kerCorruptedMetadata); Internal::enforce(allocate64 <= std::numeric_limits<size_t>::max(), ErrorCode::kerCorruptedMetadata);
DataBuf buf(allocate64); // allocate a buffer DataBuf buf(allocate64); // allocate a buffer
std::copy_n(dir.c_data(8), 4, buf.begin()); // copy dir[8:11] into buffer (short strings) std::copy_n(dir.c_data(8), 4, buf.begin()); // copy dir[8:11] into buffer (short strings)

@ -290,12 +290,12 @@ void IptcData::printStructure(std::ostream& out, const Slice<byte*>& bytes, size
char buff[100]; char buff[100];
uint16_t record = bytes.at(i + 1); uint16_t record = bytes.at(i + 1);
uint16_t dataset = bytes.at(i + 2); uint16_t dataset = bytes.at(i + 2);
enforce(bytes.size() - i >= 5, ErrorCode::kerCorruptedMetadata); Internal::enforce(bytes.size() - i >= 5, ErrorCode::kerCorruptedMetadata);
uint16_t len = getUShort(bytes.subSlice(i + 3, bytes.size()), bigEndian); uint16_t len = getUShort(bytes.subSlice(i + 3, bytes.size()), bigEndian);
snprintf(buff, sizeof(buff), " %6d | %7d | %-24s | %6d | ", record, dataset, snprintf(buff, sizeof(buff), " %6d | %7d | %-24s | %6d | ", record, dataset,
Exiv2::IptcDataSets::dataSetName(dataset, record).c_str(), len); Exiv2::IptcDataSets::dataSetName(dataset, record).c_str(), len);
enforce(bytes.size() - i >= 5 + static_cast<size_t>(len), ErrorCode::kerCorruptedMetadata); Internal::enforce(bytes.size() - i >= 5 + static_cast<size_t>(len), ErrorCode::kerCorruptedMetadata);
out << buff << Internal::binaryToString(makeSlice(bytes, i + 5, i + 5 + (len > 40 ? 40 : len))) out << buff << Internal::binaryToString(makeSlice(bytes, i + 5, i + 5 + (len > 40 ? 40 : len)))
<< (len > 40 ? "..." : "") << std::endl; << (len > 40 ? "..." : "") << std::endl;
i += 5 + len; i += 5 + len;

@ -157,7 +157,7 @@ void Jp2Image::readMetadata() {
<< "Position: " << position << " box type: " << toAscii(box.type) << " length: " << box.length << "Position: " << position << " box type: " << toAscii(box.type) << " length: " << box.length
<< std::endl; << std::endl;
#endif #endif
enforce(box.length <= boxHSize + io_->size() - io_->tell(), ErrorCode::kerCorruptedMetadata); Internal::enforce(box.length <= boxHSize + io_->size() - io_->tell(), ErrorCode::kerCorruptedMetadata);
if (box.length == 0) if (box.length == 0)
return; return;
@ -245,7 +245,7 @@ void Jp2Image::readMetadata() {
ihdr.imageHeight = getULong(reinterpret_cast<byte*>(&ihdr.imageHeight), bigEndian); ihdr.imageHeight = getULong(reinterpret_cast<byte*>(&ihdr.imageHeight), bigEndian);
ihdr.imageWidth = getULong(reinterpret_cast<byte*>(&ihdr.imageWidth), bigEndian); ihdr.imageWidth = getULong(reinterpret_cast<byte*>(&ihdr.imageWidth), bigEndian);
ihdr.componentCount = getShort(reinterpret_cast<byte*>(&ihdr.componentCount), bigEndian); ihdr.componentCount = getShort(reinterpret_cast<byte*>(&ihdr.componentCount), bigEndian);
enforce(ihdr.c == 7, ErrorCode::kerCorruptedMetadata); Internal::enforce(ihdr.c == 7, ErrorCode::kerCorruptedMetadata);
pixelWidth_ = ihdr.imageWidth; pixelWidth_ = ihdr.imageWidth;
pixelHeight_ = ihdr.imageHeight; pixelHeight_ = ihdr.imageHeight;
@ -276,7 +276,7 @@ void Jp2Image::readMetadata() {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::Jp2Image::readMetadata: Exif data found" << std::endl; std::cout << "Exiv2::Jp2Image::readMetadata: Exif data found" << std::endl;
#endif #endif
enforce(box.length >= boxHSize + sizeof(uuid), ErrorCode::kerCorruptedMetadata); Internal::enforce(box.length >= boxHSize + sizeof(uuid), ErrorCode::kerCorruptedMetadata);
rawData.alloc(box.length - (boxHSize + sizeof(uuid))); rawData.alloc(box.length - (boxHSize + sizeof(uuid)));
bufRead = io_->read(rawData.data(), rawData.size()); bufRead = io_->read(rawData.data(), rawData.size());
if (io_->error()) if (io_->error())
@ -324,7 +324,7 @@ void Jp2Image::readMetadata() {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::Jp2Image::readMetadata: Iptc data found" << std::endl; std::cout << "Exiv2::Jp2Image::readMetadata: Iptc data found" << std::endl;
#endif #endif
enforce(box.length >= boxHSize + sizeof(uuid), ErrorCode::kerCorruptedMetadata); Internal::enforce(box.length >= boxHSize + sizeof(uuid), ErrorCode::kerCorruptedMetadata);
rawData.alloc(box.length - (boxHSize + sizeof(uuid))); rawData.alloc(box.length - (boxHSize + sizeof(uuid)));
bufRead = io_->read(rawData.data(), rawData.size()); bufRead = io_->read(rawData.data(), rawData.size());
if (io_->error()) if (io_->error())
@ -344,7 +344,7 @@ void Jp2Image::readMetadata() {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::Jp2Image::readMetadata: Xmp data found" << std::endl; std::cout << "Exiv2::Jp2Image::readMetadata: Xmp data found" << std::endl;
#endif #endif
enforce(box.length >= boxHSize + sizeof(uuid), ErrorCode::kerCorruptedMetadata); Internal::enforce(box.length >= boxHSize + sizeof(uuid), ErrorCode::kerCorruptedMetadata);
rawData.alloc(box.length - (boxHSize + sizeof(uuid))); rawData.alloc(box.length - (boxHSize + sizeof(uuid)));
bufRead = io_->read(rawData.data(), rawData.size()); bufRead = io_->read(rawData.data(), rawData.size());
if (io_->error()) if (io_->error())
@ -420,7 +420,7 @@ void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option, si
const size_t position = io_->tell(); const size_t position = io_->tell();
box.length = getULong(reinterpret_cast<byte*>(&box.length), bigEndian); box.length = getULong(reinterpret_cast<byte*>(&box.length), bigEndian);
box.type = getULong(reinterpret_cast<byte*>(&box.type), bigEndian); box.type = getULong(reinterpret_cast<byte*>(&box.type), bigEndian);
enforce(box.length <= boxHSize + io_->size() - io_->tell(), ErrorCode::kerCorruptedMetadata); Internal::enforce(box.length <= boxHSize + io_->size() - io_->tell(), ErrorCode::kerCorruptedMetadata);
if (bPrint) { if (bPrint) {
out << Internal::stringFormat("%8ld | %8ld | ", position - boxHSize, static_cast<size_t>(box.length)) out << Internal::stringFormat("%8ld | %8ld | ", position - boxHSize, static_cast<size_t>(box.length))
@ -473,7 +473,7 @@ void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option, si
} }
if (subBox.type == kJp2BoxTypeImageHeader) { if (subBox.type == kJp2BoxTypeImageHeader) {
enforce(subBox.length == 22, ErrorCode::kerCorruptedMetadata); Internal::enforce(subBox.length == 22, ErrorCode::kerCorruptedMetadata);
// height (4), width (4), componentsCount (2), bpc (1) // height (4), width (4), componentsCount (2), bpc (1)
auto compressionType = data.read_uint8(11); auto compressionType = data.read_uint8(11);
auto unkC = data.read_uint8(12); auto unkC = data.read_uint8(12);
@ -485,7 +485,7 @@ void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option, si
const size_t pad = 3; // don't know why there are 3 padding bytes const size_t pad = 3; // don't know why there are 3 padding bytes
// Bounds-check for the `getULong()` below, which reads 4 bytes, starting at `pad`. // Bounds-check for the `getULong()` below, which reads 4 bytes, starting at `pad`.
enforce(data.size() >= pad + 4, ErrorCode::kerCorruptedMetadata); Internal::enforce(data.size() >= pad + 4, ErrorCode::kerCorruptedMetadata);
/// \todo A conforming JP2 reader shall ignore all Colour Specification boxes after the first. /// \todo A conforming JP2 reader shall ignore all Colour Specification boxes after the first.
auto METH = data.read_uint8(0); auto METH = data.read_uint8(0);
@ -502,7 +502,7 @@ void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option, si
if (bPrint) { if (bPrint) {
out << " | iccLength:" << iccLength; out << " | iccLength:" << iccLength;
} }
enforce(iccLength <= data.size() - pad, ErrorCode::kerCorruptedMetadata); Internal::enforce(iccLength <= data.size() - pad, ErrorCode::kerCorruptedMetadata);
if (bICC) { if (bICC) {
out.write(data.c_str(pad), iccLength); out.write(data.c_str(pad), iccLength);
} }
@ -532,7 +532,7 @@ void Jp2Image::printStructure(std::ostream& out, PrintStructureOption option, si
} }
DataBuf rawData; DataBuf rawData;
enforce(box.length >= sizeof(uuid) + boxHSize, ErrorCode::kerCorruptedMetadata); Internal::enforce(box.length >= sizeof(uuid) + boxHSize, ErrorCode::kerCorruptedMetadata);
rawData.alloc(box.length - sizeof(uuid) - boxHSize); rawData.alloc(box.length - sizeof(uuid) - boxHSize);
const size_t bufRead = io_->read(rawData.data(), rawData.size()); const size_t bufRead = io_->read(rawData.data(), rawData.size());
if (io_->error()) if (io_->error())
@ -602,14 +602,14 @@ void Jp2Image::encodeJp2Header(const DataBuf& boxBuf, DataBuf& outBuf) {
DataBuf output(boxBuf.size() + iccProfile_.size() + 100); // allocate sufficient space DataBuf output(boxBuf.size() + iccProfile_.size() + 100); // allocate sufficient space
size_t outlen = boxHSize; // now many bytes have we written to output? size_t outlen = boxHSize; // now many bytes have we written to output?
size_t inlen = boxHSize; // how many bytes have we read from boxBuf? size_t inlen = boxHSize; // how many bytes have we read from boxBuf?
enforce(boxHSize <= output.size(), ErrorCode::kerCorruptedMetadata); Internal::enforce(boxHSize <= output.size(), ErrorCode::kerCorruptedMetadata);
uint32_t length = getULong(boxBuf.c_data(0), bigEndian); uint32_t length = getULong(boxBuf.c_data(0), bigEndian);
enforce(length <= output.size(), ErrorCode::kerCorruptedMetadata); Internal::enforce(length <= output.size(), ErrorCode::kerCorruptedMetadata);
uint32_t count = boxHSize; uint32_t count = boxHSize;
bool bWroteColor = false; bool bWroteColor = false;
while (count < length && !bWroteColor) { while (count < length && !bWroteColor) {
enforce(boxHSize <= length - count, ErrorCode::kerCorruptedMetadata); Internal::enforce(boxHSize <= length - count, ErrorCode::kerCorruptedMetadata);
Internal::Jp2BoxHeader subBox; Internal::Jp2BoxHeader subBox;
memcpy(&subBox, boxBuf.c_data(count), boxHSize); memcpy(&subBox, boxBuf.c_data(count), boxHSize);
Internal::Jp2BoxHeader newBox = subBox; Internal::Jp2BoxHeader newBox = subBox;
@ -621,8 +621,8 @@ void Jp2Image::encodeJp2Header(const DataBuf& boxBuf, DataBuf& outBuf) {
std::cout << "Jp2Image::encodeJp2Header subbox: " << toAscii(subBox.type) << " length = " << subBox.length std::cout << "Jp2Image::encodeJp2Header subbox: " << toAscii(subBox.type) << " length = " << subBox.length
<< std::endl; << std::endl;
#endif #endif
enforce(subBox.length > 0, ErrorCode::kerCorruptedMetadata); Internal::enforce(subBox.length > 0, ErrorCode::kerCorruptedMetadata);
enforce(subBox.length <= length - count, ErrorCode::kerCorruptedMetadata); Internal::enforce(subBox.length <= length - count, ErrorCode::kerCorruptedMetadata);
count += subBox.length; count += subBox.length;
newBox.type = subBox.type; newBox.type = subBox.type;
} else { } else {
@ -637,7 +637,7 @@ void Jp2Image::encodeJp2Header(const DataBuf& boxBuf, DataBuf& outBuf) {
if (!iccProfileDefined()) { if (!iccProfileDefined()) {
const char* pad = "\x01\x00\x00\x00\x00\x00\x10\x00\x00\x05\x1cuuid"; const char* pad = "\x01\x00\x00\x00\x00\x00\x10\x00\x00\x05\x1cuuid";
uint32_t psize = 15; uint32_t psize = 15;
enforce(newlen <= output.size() - outlen, ErrorCode::kerCorruptedMetadata); Internal::enforce(newlen <= output.size() - outlen, ErrorCode::kerCorruptedMetadata);
ul2Data(reinterpret_cast<byte*>(&newBox.length), psize, bigEndian); ul2Data(reinterpret_cast<byte*>(&newBox.length), psize, bigEndian);
ul2Data(reinterpret_cast<byte*>(&newBox.type), newBox.type, bigEndian); ul2Data(reinterpret_cast<byte*>(&newBox.type), newBox.type, bigEndian);
std::copy_n(reinterpret_cast<char*>(&newBox), sizeof(newBox), output.begin() + outlen); std::copy_n(reinterpret_cast<char*>(&newBox), sizeof(newBox), output.begin() + outlen);
@ -646,7 +646,7 @@ void Jp2Image::encodeJp2Header(const DataBuf& boxBuf, DataBuf& outBuf) {
const char* pad = "\x02\x00\x00"; const char* pad = "\x02\x00\x00";
uint32_t psize = 3; uint32_t psize = 3;
newlen = sizeof(newBox) + psize + iccProfile_.size(); newlen = sizeof(newBox) + psize + iccProfile_.size();
enforce(newlen <= output.size() - outlen, ErrorCode::kerCorruptedMetadata); Internal::enforce(newlen <= output.size() - outlen, ErrorCode::kerCorruptedMetadata);
ul2Data(reinterpret_cast<byte*>(&newBox.length), static_cast<uint32_t>(newlen), bigEndian); ul2Data(reinterpret_cast<byte*>(&newBox.length), static_cast<uint32_t>(newlen), bigEndian);
ul2Data(reinterpret_cast<byte*>(&newBox.type), newBox.type, bigEndian); ul2Data(reinterpret_cast<byte*>(&newBox.type), newBox.type, bigEndian);
std::copy_n(reinterpret_cast<char*>(&newBox), sizeof(newBox), output.begin() + outlen); std::copy_n(reinterpret_cast<char*>(&newBox), sizeof(newBox), output.begin() + outlen);
@ -654,7 +654,7 @@ void Jp2Image::encodeJp2Header(const DataBuf& boxBuf, DataBuf& outBuf) {
std::copy(iccProfile_.begin(), iccProfile_.end(), output.begin() + outlen + sizeof(newBox) + psize); std::copy(iccProfile_.begin(), iccProfile_.end(), output.begin() + outlen + sizeof(newBox) + psize);
} }
} else { } else {
enforce(newlen <= output.size() - outlen, ErrorCode::kerCorruptedMetadata); Internal::enforce(newlen <= output.size() - outlen, ErrorCode::kerCorruptedMetadata);
std::copy_n(boxBuf.c_data(inlen), subBox.length, output.begin() + outlen); std::copy_n(boxBuf.c_data(inlen), subBox.length, output.begin() + outlen);
} }
@ -734,7 +734,8 @@ void Jp2Image::doWriteMetadata(BasicIo& outIo) {
} }
// Prevent a malicious file from causing a large memory allocation. // Prevent a malicious file from causing a large memory allocation.
enforce(box.length - 8 <= static_cast<size_t>(io_->size() - io_->tell()), ErrorCode::kerCorruptedMetadata); Internal::enforce(box.length - 8 <= static_cast<size_t>(io_->size() - io_->tell()),
ErrorCode::kerCorruptedMetadata);
// Read whole box : Box header + Box data (not fixed size - can be null). // Read whole box : Box header + Box data (not fixed size - can be null).
DataBuf boxBuf(box.length); // Box header (8 bytes) + box data. DataBuf boxBuf(box.length); // Box header (8 bytes) + box data.
@ -831,7 +832,7 @@ void Jp2Image::doWriteMetadata(BasicIo& outIo) {
} }
case kJp2BoxTypeUuid: { case kJp2BoxTypeUuid: {
enforce(boxBuf.size() >= 24, ErrorCode::kerCorruptedMetadata); Internal::enforce(boxBuf.size() >= 24, ErrorCode::kerCorruptedMetadata);
if (boxBuf.cmpBytes(8, kJp2UuidExif, 16) == 0) { if (boxBuf.cmpBytes(8, kJp2UuidExif, 16) == 0) {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::Jp2Image::doWriteMetadata: strip Exif Uuid box" << std::endl; std::cout << "Exiv2::Jp2Image::doWriteMetadata: strip Exif Uuid box" << std::endl;

@ -31,6 +31,7 @@
namespace Exiv2 { namespace Exiv2 {
using Exiv2::Internal::enforce;
using Exiv2::Internal::startsWith; using Exiv2::Internal::startsWith;
namespace { namespace {
// JPEG Segment markers (The first byte is always 0xFF, the value of these constants correspond to the 2nd byte) // JPEG Segment markers (The first byte is always 0xFF, the value of these constants correspond to the 2nd byte)
@ -61,11 +62,11 @@ constexpr auto exifId_ = "Exif\0\0"; //!< Exif identifier
constexpr auto xmpId_ = "http://ns.adobe.com/xap/1.0/\0"; //!< XMP packet identifier constexpr auto xmpId_ = "http://ns.adobe.com/xap/1.0/\0"; //!< XMP packet identifier
constexpr auto iccId_ = "ICC_PROFILE\0"; //!< ICC profile identifier constexpr auto iccId_ = "ICC_PROFILE\0"; //!< ICC profile identifier
inline bool inRange(int lo, int value, int hi) { constexpr bool inRange(int lo, int value, int hi) {
return lo <= value && value <= hi; return lo <= value && value <= hi;
} }
inline bool inRange2(int value, int lo1, int hi1, int lo2, int hi2) { constexpr bool inRange2(int value, int lo1, int hi1, int lo2, int hi2) {
return inRange(lo1, value, hi1) || inRange(lo2, value, hi2); return inRange(lo1, value, hi1) || inRange(lo2, value, hi2);
} }

@ -1446,19 +1446,19 @@ static long getKeyLong(const std::string& key, const ExifData* metadata, int whi
/*! http://stackoverflow.com/questions/1798112/removing-leading-and-trailing-spaces-from-a-string /*! http://stackoverflow.com/questions/1798112/removing-leading-and-trailing-spaces-from-a-string
trim from left trim from left
*/ */
inline std::string& ltrim(std::string& s, const char* t = " \t\n\r\f\v") { static std::string& ltrim(std::string& s, const char* t = " \t\n\r\f\v") {
s.erase(0, s.find_first_not_of(t)); s.erase(0, s.find_first_not_of(t));
return s; return s;
} }
//! trim from right //! trim from right
inline std::string& rtrim(std::string& s, const char* t = " \t\n\r\f\v") { static std::string& rtrim(std::string& s, const char* t = " \t\n\r\f\v") {
s.erase(s.find_last_not_of(t) + 1); s.erase(s.find_last_not_of(t) + 1);
return s; return s;
} }
//! trim from left & right //! trim from left & right
inline std::string& trim(std::string& s, const char* t = " \t\n\r\f\v") { static std::string& trim(std::string& s, const char* t = " \t\n\r\f\v") {
return ltrim(rtrim(s, t), t); return ltrim(rtrim(s, t), t);
} }

@ -77,22 +77,22 @@ void MrwImage::readMetadata() {
uint32_t const end = getULong(tmp + 4, bigEndian); uint32_t const end = getULong(tmp + 4, bigEndian);
pos += len; pos += len;
enforce(pos <= end, ErrorCode::kerFailedToReadImageData); Internal::enforce(pos <= end, ErrorCode::kerFailedToReadImageData);
io_->read(tmp, len); io_->read(tmp, len);
if (io_->error() || io_->eof()) if (io_->error() || io_->eof())
throw Error(ErrorCode::kerFailedToReadImageData); throw Error(ErrorCode::kerFailedToReadImageData);
while (memcmp(tmp + 1, "TTW", 3) != 0) { while (memcmp(tmp + 1, "TTW", 3) != 0) {
uint32_t const siz = getULong(tmp + 4, bigEndian); uint32_t const siz = getULong(tmp + 4, bigEndian);
enforce(siz <= end - pos, ErrorCode::kerFailedToReadImageData); Internal::enforce(siz <= end - pos, ErrorCode::kerFailedToReadImageData);
pos += siz; pos += siz;
io_->seek(siz, BasicIo::cur); io_->seek(siz, BasicIo::cur);
enforce(!io_->error() && !io_->eof(), ErrorCode::kerFailedToReadImageData); Internal::enforce(!io_->error() && !io_->eof(), ErrorCode::kerFailedToReadImageData);
enforce(len <= end - pos, ErrorCode::kerFailedToReadImageData); Internal::enforce(len <= end - pos, ErrorCode::kerFailedToReadImageData);
pos += len; pos += len;
io_->read(tmp, len); io_->read(tmp, len);
enforce(!io_->error() && !io_->eof(), ErrorCode::kerFailedToReadImageData); Internal::enforce(!io_->error() && !io_->eof(), ErrorCode::kerFailedToReadImageData);
} }
const uint32_t siz = getULong(tmp + 4, bigEndian); const uint32_t siz = getULong(tmp + 4, bigEndian);
@ -101,10 +101,10 @@ void MrwImage::readMetadata() {
// greater than io_->size() then it is definitely invalid. But the // greater than io_->size() then it is definitely invalid. But the
// exact bounds checking is done by the call to io_->read, which // exact bounds checking is done by the call to io_->read, which
// will fail if there are fewer than siz bytes left to read. // will fail if there are fewer than siz bytes left to read.
enforce(siz <= io_->size(), ErrorCode::kerFailedToReadImageData); Internal::enforce(siz <= io_->size(), ErrorCode::kerFailedToReadImageData);
DataBuf buf(siz); DataBuf buf(siz);
io_->read(buf.data(), buf.size()); io_->read(buf.data(), buf.size());
enforce(!io_->error() && !io_->eof(), ErrorCode::kerFailedToReadImageData); Internal::enforce(!io_->error() && !io_->eof(), ErrorCode::kerFailedToReadImageData);
ByteOrder bo = TiffParser::decode(exifData_, iptcData_, xmpData_, buf.c_data(), buf.size()); ByteOrder bo = TiffParser::decode(exifData_, iptcData_, xmpData_, buf.c_data(), buf.size());
setByteOrder(bo); setByteOrder(bo);

@ -87,7 +87,7 @@ void PgfImage::readMetadata() {
// And now, the most interesting, the user data byte array where metadata are stored as small image. // And now, the most interesting, the user data byte array where metadata are stored as small image.
enforce(headerSize <= std::numeric_limits<size_t>::max() - 8, ErrorCode::kerCorruptedMetadata); Internal::enforce(headerSize <= std::numeric_limits<size_t>::max() - 8, ErrorCode::kerCorruptedMetadata);
size_t size = headerSize + 8 - io_->tell(); size_t size = headerSize + 8 - io_->tell();
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES

@ -154,7 +154,7 @@ DataBuf Photoshop::setIptcIrb(const byte* pPsData, size_t sizePsData, const Iptc
// Write existing stuff after record, skip the current and all remaining IPTC blocks // Write existing stuff after record, skip the current and all remaining IPTC blocks
size_t pos = sizeFront; size_t pos = sizeFront;
auto nextSizeData = Safe::add<long>(static_cast<long>(sizePsData), -static_cast<long>(pos)); auto nextSizeData = Safe::add<long>(static_cast<long>(sizePsData), -static_cast<long>(pos));
enforce(nextSizeData >= 0, ErrorCode::kerCorruptedMetadata); Internal::enforce(nextSizeData >= 0, ErrorCode::kerCorruptedMetadata);
while (0 == Photoshop::locateIptcIrb(pPsData + pos, nextSizeData, &record, sizeHdr, sizeIptc)) { while (0 == Photoshop::locateIptcIrb(pPsData + pos, nextSizeData, &record, sizeHdr, sizeIptc)) {
const auto newPos = static_cast<size_t>(record - pPsData); const auto newPos = static_cast<size_t>(record - pPsData);
if (newPos > pos) { // Copy data up to the IPTC IRB if (newPos > pos) { // Copy data up to the IPTC IRB
@ -162,7 +162,7 @@ DataBuf Photoshop::setIptcIrb(const byte* pPsData, size_t sizePsData, const Iptc
} }
pos = newPos + sizeHdr + sizeIptc + (sizeIptc & 1); // Skip the IPTC IRB pos = newPos + sizeHdr + sizeIptc + (sizeIptc & 1); // Skip the IPTC IRB
nextSizeData = Safe::add<long>(static_cast<long>(sizePsData), -static_cast<long>(pos)); nextSizeData = Safe::add<long>(static_cast<long>(sizePsData), -static_cast<long>(pos));
enforce(nextSizeData >= 0, ErrorCode::kerCorruptedMetadata); Internal::enforce(nextSizeData >= 0, ErrorCode::kerCorruptedMetadata);
} }
if (pos < sizePsData) { if (pos < sizePsData) {
append(psBlob, pPsData + pos, sizePsData - pos); append(psBlob, pPsData + pos, sizePsData - pos);

@ -41,7 +41,7 @@ constexpr unsigned char pngBlank[] = {
const auto nullComp = reinterpret_cast<const Exiv2::byte*>("\0\0"); const auto nullComp = reinterpret_cast<const Exiv2::byte*>("\0\0");
const auto typeExif = reinterpret_cast<const Exiv2::byte*>("eXIf"); const auto typeExif = reinterpret_cast<const Exiv2::byte*>("eXIf");
const auto typeICCP = reinterpret_cast<const Exiv2::byte*>("iCCP"); const auto typeICCP = reinterpret_cast<const Exiv2::byte*>("iCCP");
inline bool compare(std::string_view str, const Exiv2::DataBuf& buf) { bool compare(std::string_view str, const Exiv2::DataBuf& buf) {
const auto minlen = std::min(str.size(), buf.size()); const auto minlen = std::min(str.size(), buf.size());
return buf.cmpBytes(0, str.data(), minlen) == 0; return buf.cmpBytes(0, str.data(), minlen) == 0;
} }

@ -731,7 +731,7 @@ DataBuf LoaderTiff::getData() const {
dataValue.setDataArea(base + offset, size); dataValue.setDataArea(base + offset, size);
} else { } else {
// FIXME: the buffer is probably copied twice, it should be optimized // FIXME: the buffer is probably copied twice, it should be optimized
enforce(size_ <= io.size(), ErrorCode::kerCorruptedMetadata); Internal::enforce(size_ <= io.size(), ErrorCode::kerCorruptedMetadata);
DataBuf buf(size_); DataBuf buf(size_);
uint32_t idxBuf = 0; uint32_t idxBuf = 0;
for (size_t i = 0; i < sizes.count(); i++) { for (size_t i = 0; i < sizes.count(); i++) {
@ -742,7 +742,7 @@ DataBuf LoaderTiff::getData() const {
// see the constructor of LoaderTiff // see the constructor of LoaderTiff
// But e.g in malicious files some of these values could be negative // But e.g in malicious files some of these values could be negative
// That's why we check again for each step here to really make sure we don't overstep // That's why we check again for each step here to really make sure we don't overstep
enforce(Safe::add(idxBuf, size) <= size_, ErrorCode::kerCorruptedMetadata); Internal::enforce(Safe::add(idxBuf, size) <= size_, ErrorCode::kerCorruptedMetadata);
if (size != 0 && Safe::add(offset, size) <= static_cast<uint32_t>(io.size())) { if (size != 0 && Safe::add(offset, size) <= static_cast<uint32_t>(io.size())) {
std::copy_n(base + offset, size, buf.begin() + idxBuf); std::copy_n(base + offset, size, buf.begin() + idxBuf);
} }

@ -167,10 +167,10 @@ void PsdImage::readMetadata() {
throw Error(ErrorCode::kerNotAnImage, "Photoshop"); throw Error(ErrorCode::kerNotAnImage, "Photoshop");
} }
uint32_t resourcesLength = getULong(buf, bigEndian); uint32_t resourcesLength = getULong(buf, bigEndian);
enforce(resourcesLength < io_->size(), Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(resourcesLength < io_->size(), Exiv2::ErrorCode::kerCorruptedMetadata);
while (resourcesLength > 0) { while (resourcesLength > 0) {
enforce(resourcesLength >= 8, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(resourcesLength >= 8, Exiv2::ErrorCode::kerCorruptedMetadata);
resourcesLength -= 8; resourcesLength -= 8;
if (io_->read(buf, 8) != 8) { if (io_->read(buf, 8) != 8) {
throw Error(ErrorCode::kerNotAnImage, "Photoshop"); throw Error(ErrorCode::kerNotAnImage, "Photoshop");
@ -183,12 +183,12 @@ void PsdImage::readMetadata() {
uint32_t resourceNameLength = buf[6] & ~1; uint32_t resourceNameLength = buf[6] & ~1;
// skip the resource name, plus any padding // skip the resource name, plus any padding
enforce(resourceNameLength <= resourcesLength, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(resourceNameLength <= resourcesLength, Exiv2::ErrorCode::kerCorruptedMetadata);
resourcesLength -= resourceNameLength; resourcesLength -= resourceNameLength;
io_->seek(resourceNameLength, BasicIo::cur); io_->seek(resourceNameLength, BasicIo::cur);
// read resource size // read resource size
enforce(resourcesLength >= 4, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(resourcesLength >= 4, Exiv2::ErrorCode::kerCorruptedMetadata);
resourcesLength -= 4; resourcesLength -= 4;
if (io_->read(buf, 4) != 4) { if (io_->read(buf, 4) != 4) {
throw Error(ErrorCode::kerNotAnImage, "Photoshop"); throw Error(ErrorCode::kerNotAnImage, "Photoshop");
@ -201,10 +201,10 @@ void PsdImage::readMetadata() {
<< "\n"; << "\n";
#endif #endif
enforce(resourceSize <= resourcesLength, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(resourceSize <= resourcesLength, Exiv2::ErrorCode::kerCorruptedMetadata);
readResourceBlock(resourceId, resourceSize); readResourceBlock(resourceId, resourceSize);
resourceSize = (resourceSize + 1) & ~1; // pad to even resourceSize = (resourceSize + 1) & ~1; // pad to even
enforce(resourceSize <= resourcesLength, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(resourceSize <= resourcesLength, Exiv2::ErrorCode::kerCorruptedMetadata);
resourcesLength -= resourceSize; resourcesLength -= resourceSize;
io_->seek(curOffset + resourceSize, BasicIo::beg); io_->seek(curOffset + resourceSize, BasicIo::beg);
} }

@ -243,17 +243,17 @@ void RafImage::readMetadata() {
uint32_t jpg_img_off_u32 = Exiv2::getULong(jpg_img_offset, bigEndian); uint32_t jpg_img_off_u32 = Exiv2::getULong(jpg_img_offset, bigEndian);
uint32_t jpg_img_len_u32 = Exiv2::getULong(jpg_img_length, bigEndian); uint32_t jpg_img_len_u32 = Exiv2::getULong(jpg_img_length, bigEndian);
enforce(Safe::add(jpg_img_off_u32, jpg_img_len_u32) <= io_->size(), ErrorCode::kerCorruptedMetadata); Internal::enforce(Safe::add(jpg_img_off_u32, jpg_img_len_u32) <= io_->size(), ErrorCode::kerCorruptedMetadata);
#if LONG_MAX < UINT_MAX #if LONG_MAX < UINT_MAX
enforce(jpg_img_off_u32 <= std::numeric_limits<uint32_t>::max(), ErrorCode::kerCorruptedMetadata); Internal::enforce(jpg_img_off_u32 <= std::numeric_limits<uint32_t>::max(), ErrorCode::kerCorruptedMetadata);
enforce(jpg_img_len_u32 <= std::numeric_limits<uint32_t>::max(), ErrorCode::kerCorruptedMetadata); Internal::enforce(jpg_img_len_u32 <= std::numeric_limits<uint32_t>::max(), ErrorCode::kerCorruptedMetadata);
#endif #endif
auto jpg_img_off = static_cast<long>(jpg_img_off_u32); auto jpg_img_off = static_cast<long>(jpg_img_off_u32);
auto jpg_img_len = static_cast<long>(jpg_img_len_u32); auto jpg_img_len = static_cast<long>(jpg_img_len_u32);
enforce(jpg_img_len >= 12, ErrorCode::kerCorruptedMetadata); Internal::enforce(jpg_img_len >= 12, ErrorCode::kerCorruptedMetadata);
DataBuf buf(jpg_img_len - 12); DataBuf buf(jpg_img_len - 12);
if (io_->seek(jpg_img_off + 12, BasicIo::beg) != 0) if (io_->seek(jpg_img_off + 12, BasicIo::beg) != 0)
@ -285,7 +285,7 @@ void RafImage::readMetadata() {
uint32_t tiffLength = Exiv2::getULong(readBuff, bigEndian); uint32_t tiffLength = Exiv2::getULong(readBuff, bigEndian);
// sanity check. Does tiff lie inside the file? // sanity check. Does tiff lie inside the file?
enforce(Safe::add(tiffOffset, tiffLength) <= io_->size(), ErrorCode::kerCorruptedMetadata); Internal::enforce(Safe::add(tiffOffset, tiffLength) <= io_->size(), ErrorCode::kerCorruptedMetadata);
if (io_->seek(tiffOffset, BasicIo::beg) != 0) if (io_->seek(tiffOffset, BasicIo::beg) != 0)
throw Error(ErrorCode::kerFailedToReadImageData); throw Error(ErrorCode::kerFailedToReadImageData);

@ -192,9 +192,9 @@ const char* Exiv2::DataBuf::c_str(size_t offset) const {
// free functions // free functions
static void checkDataBufBounds(const DataBuf& buf, size_t end) { static void checkDataBufBounds(const DataBuf& buf, size_t end) {
enforce<std::invalid_argument>(end <= static_cast<size_t>(std::numeric_limits<long>::max()), Internal::enforce<std::invalid_argument>(end <= static_cast<size_t>(std::numeric_limits<long>::max()),
"end of slice too large to be compared with DataBuf bounds."); "end of slice too large to be compared with DataBuf bounds.");
enforce<std::out_of_range>(end <= buf.size(), "Invalid slice bounds specified"); Internal::enforce<std::out_of_range>(end <= buf.size(), "Invalid slice bounds specified");
} }
Slice<byte*> makeSlice(DataBuf& buf, size_t begin, size_t end) { Slice<byte*> makeSlice(DataBuf& buf, size_t begin, size_t end) {

@ -954,7 +954,7 @@ size_t TimeValue::copy(byte* buf, ByteOrder /*byteOrder*/) const {
"%02d%02d%02d%1c%02d%02d", time_.hour, time_.minute, time_.second, "%02d%02d%02d%1c%02d%02d", time_.hour, time_.minute, time_.second,
plusMinus, abs(time_.tzHour), abs(time_.tzMinute))); plusMinus, abs(time_.tzHour), abs(time_.tzMinute)));
enforce(wrote == 11, Exiv2::ErrorCode::kerUnsupportedTimeFormat); Internal::enforce(wrote == 11, Exiv2::ErrorCode::kerUnsupportedTimeFormat);
std::memcpy(buf, temp, wrote); std::memcpy(buf, temp, wrote);
return wrote; return wrote;
} }

@ -173,7 +173,7 @@ void WebPImage::doWriteMetadata(BasicIo& outIo) {
has_vp8x = true; has_vp8x = true;
} }
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X) && !has_size) { if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X) && !has_size) {
enforce(size_u32 >= 10, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(size_u32 >= 10, Exiv2::ErrorCode::kerCorruptedMetadata);
has_size = true; has_size = true;
byte size_buf[WEBP_TAG_SIZE]; byte size_buf[WEBP_TAG_SIZE];
@ -202,7 +202,7 @@ void WebPImage::doWriteMetadata(BasicIo& outIo) {
} }
#endif #endif
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8) && !has_size) { if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8) && !has_size) {
enforce(size_u32 >= 10, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(size_u32 >= 10, Exiv2::ErrorCode::kerCorruptedMetadata);
has_size = true; has_size = true;
byte size_buf[2]; byte size_buf[2];
@ -220,13 +220,13 @@ void WebPImage::doWriteMetadata(BasicIo& outIo) {
/* Chunk with lossless image data. */ /* Chunk with lossless image data. */
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8L) && !has_alpha) { if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8L) && !has_alpha) {
enforce(size_u32 >= 5, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(size_u32 >= 5, Exiv2::ErrorCode::kerCorruptedMetadata);
if ((payload.read_uint8(4) & WEBP_VP8X_ALPHA_BIT) == WEBP_VP8X_ALPHA_BIT) { if ((payload.read_uint8(4) & WEBP_VP8X_ALPHA_BIT) == WEBP_VP8X_ALPHA_BIT) {
has_alpha = true; has_alpha = true;
} }
} }
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8L) && !has_size) { if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8L) && !has_size) {
enforce(size_u32 >= 5, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(size_u32 >= 5, Exiv2::ErrorCode::kerCorruptedMetadata);
has_size = true; has_size = true;
byte size_buf_w[2]; byte size_buf_w[2];
byte size_buf_h[3]; byte size_buf_h[3];
@ -250,13 +250,13 @@ void WebPImage::doWriteMetadata(BasicIo& outIo) {
/* Chunk with animation frame. */ /* Chunk with animation frame. */
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ANMF) && !has_alpha) { if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ANMF) && !has_alpha) {
enforce(size_u32 >= 6, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(size_u32 >= 6, Exiv2::ErrorCode::kerCorruptedMetadata);
if ((payload.read_uint8(5) & 0x2) == 0x2) { if ((payload.read_uint8(5) & 0x2) == 0x2) {
has_alpha = true; has_alpha = true;
} }
} }
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ANMF) && !has_size) { if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ANMF) && !has_size) {
enforce(size_u32 >= 12, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(size_u32 >= 12, Exiv2::ErrorCode::kerCorruptedMetadata);
has_size = true; has_size = true;
byte size_buf[WEBP_TAG_SIZE]; byte size_buf[WEBP_TAG_SIZE];
@ -294,7 +294,7 @@ void WebPImage::doWriteMetadata(BasicIo& outIo) {
io_->seek(+1, BasicIo::cur); // skip pad io_->seek(+1, BasicIo::cur); // skip pad
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X)) { if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X)) {
enforce(size_u32 >= 1, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(size_u32 >= 1, Exiv2::ErrorCode::kerCorruptedMetadata);
if (has_icc) { if (has_icc) {
const uint8_t x = payload.read_uint8(0); const uint8_t x = payload.read_uint8(0);
payload.write_uint8(0, x | WEBP_VP8X_ICC_BIT); payload.write_uint8(0, x | WEBP_VP8X_ICC_BIT);
@ -477,7 +477,7 @@ void WebPImage::readMetadata() {
io_->readOrThrow(data, WEBP_TAG_SIZE * 3, Exiv2::ErrorCode::kerCorruptedMetadata); io_->readOrThrow(data, WEBP_TAG_SIZE * 3, Exiv2::ErrorCode::kerCorruptedMetadata);
const uint32_t filesize = Safe::add(Exiv2::getULong(data + WEBP_TAG_SIZE, littleEndian), 8U); const uint32_t filesize = Safe::add(Exiv2::getULong(data + WEBP_TAG_SIZE, littleEndian), 8U);
enforce(filesize <= io_->size(), Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(filesize <= io_->size(), Exiv2::ErrorCode::kerCorruptedMetadata);
WebPImage::decodeChunks(filesize); WebPImage::decodeChunks(filesize);
@ -500,15 +500,15 @@ void WebPImage::decodeChunks(uint32_t filesize) {
const uint32_t size = Exiv2::getULong(size_buff, littleEndian); const uint32_t size = Exiv2::getULong(size_buff, littleEndian);
// Check that `size` is within bounds. // Check that `size` is within bounds.
enforce(io_->tell() <= filesize, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(io_->tell() <= filesize, Exiv2::ErrorCode::kerCorruptedMetadata);
enforce(size <= (filesize - io_->tell()), Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(size <= (filesize - io_->tell()), Exiv2::ErrorCode::kerCorruptedMetadata);
DataBuf payload(size); DataBuf payload(size);
if (payload.empty()) { if (payload.empty()) {
io_->seek(size, BasicIo::cur); io_->seek(size, BasicIo::cur);
} else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X) && !has_canvas_data) { } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X) && !has_canvas_data) {
enforce(size >= 10, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(size >= 10, Exiv2::ErrorCode::kerCorruptedMetadata);
has_canvas_data = true; has_canvas_data = true;
byte size_buf[WEBP_TAG_SIZE]; byte size_buf[WEBP_TAG_SIZE];
@ -525,7 +525,7 @@ void WebPImage::decodeChunks(uint32_t filesize) {
size_buf[3] = 0; size_buf[3] = 0;
pixelHeight_ = Exiv2::getULong(size_buf, littleEndian) + 1; pixelHeight_ = Exiv2::getULong(size_buf, littleEndian) + 1;
} else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8) && !has_canvas_data) { } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8) && !has_canvas_data) {
enforce(size >= 10, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(size >= 10, Exiv2::ErrorCode::kerCorruptedMetadata);
has_canvas_data = true; has_canvas_data = true;
io_->readOrThrow(payload.data(), payload.size(), Exiv2::ErrorCode::kerCorruptedMetadata); io_->readOrThrow(payload.data(), payload.size(), Exiv2::ErrorCode::kerCorruptedMetadata);
@ -543,7 +543,7 @@ void WebPImage::decodeChunks(uint32_t filesize) {
size_buf[3] = 0; size_buf[3] = 0;
pixelHeight_ = Exiv2::getULong(size_buf, littleEndian) & 0x3fff; pixelHeight_ = Exiv2::getULong(size_buf, littleEndian) & 0x3fff;
} else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8L) && !has_canvas_data) { } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8L) && !has_canvas_data) {
enforce(size >= 5, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(size >= 5, Exiv2::ErrorCode::kerCorruptedMetadata);
has_canvas_data = true; has_canvas_data = true;
byte size_buf_w[2]; byte size_buf_w[2];
@ -562,7 +562,7 @@ void WebPImage::decodeChunks(uint32_t filesize) {
size_buf_h[1] = ((size_buf_h[1] >> 6) & 0x3) | ((size_buf_h[2] & 0xFU) << 0x2); size_buf_h[1] = ((size_buf_h[1] >> 6) & 0x3) | ((size_buf_h[2] & 0xFU) << 0x2);
pixelHeight_ = Exiv2::getUShort(size_buf_h, littleEndian) + 1; pixelHeight_ = Exiv2::getUShort(size_buf_h, littleEndian) + 1;
} else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ANMF) && !has_canvas_data) { } else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ANMF) && !has_canvas_data) {
enforce(size >= 12, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(size >= 12, Exiv2::ErrorCode::kerCorruptedMetadata);
has_canvas_data = true; has_canvas_data = true;
byte size_buf[WEBP_TAG_SIZE]; byte size_buf[WEBP_TAG_SIZE];
@ -752,14 +752,14 @@ void WebPImage::inject_VP8X(BasicIo& iIo, bool has_xmp, bool has_exif, bool has_
} }
/* set width - stored in 24bits*/ /* set width - stored in 24bits*/
enforce(width > 0, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(width > 0, Exiv2::ErrorCode::kerCorruptedMetadata);
uint32_t w = width - 1; uint32_t w = width - 1;
data[4] = w & 0xFF; data[4] = w & 0xFF;
data[5] = (w >> 8) & 0xFF; data[5] = (w >> 8) & 0xFF;
data[6] = (w >> 16) & 0xFF; data[6] = (w >> 16) & 0xFF;
/* set height - stored in 24bits */ /* set height - stored in 24bits */
enforce(width > 0, Exiv2::ErrorCode::kerCorruptedMetadata); Internal::enforce(width > 0, Exiv2::ErrorCode::kerCorruptedMetadata);
uint32_t h = height - 1; uint32_t h = height - 1;
data[7] = h & 0xFF; data[7] = h & 0xFF;
data[8] = (h >> 8) & 0xFF; data[8] = (h >> 8) & 0xFF;

@ -9,21 +9,23 @@
TEST(enforce, errMessageCanBeRetrievedFromErrorException) { TEST(enforce, errMessageCanBeRetrievedFromErrorException) {
try { try {
enforce(false, Exiv2::ErrorCode::kerErrorMessage, "an error occurred"); Exiv2::Internal::enforce(false, Exiv2::ErrorCode::kerErrorMessage, "an error occurred");
} catch (const Exiv2::Error& e) { } catch (const Exiv2::Error& e) {
ASSERT_STREQ(e.what(), "an error occurred"); ASSERT_STREQ(e.what(), "an error occurred");
} }
} }
TEST(enforce, withTrueConditionDoesNotThrow) { TEST(enforce, withTrueConditionDoesNotThrow) {
ASSERT_NO_THROW(enforce(true, Exiv2::ErrorCode::kerErrorMessage)); ASSERT_NO_THROW(Exiv2::Internal::enforce(true, Exiv2::ErrorCode::kerErrorMessage));
} }
TEST(enforce, withFalseConditionThrows) { TEST(enforce, withFalseConditionThrows) {
ASSERT_THROW(enforce(false, Exiv2::ErrorCode::kerErrorMessage), Exiv2::Error); ASSERT_THROW(Exiv2::Internal::enforce(false, Exiv2::ErrorCode::kerErrorMessage), Exiv2::Error);
ASSERT_THROW(enforce(false, Exiv2::ErrorCode::kerErrorMessage, "error message"), Exiv2::Error); ASSERT_THROW(Exiv2::Internal::enforce(false, Exiv2::ErrorCode::kerErrorMessage, "error message"), Exiv2::Error);
ASSERT_THROW(enforce(false, Exiv2::ErrorCode::kerDataSourceOpenFailed, "path", "strerror"), Exiv2::Error); ASSERT_THROW(Exiv2::Internal::enforce(false, Exiv2::ErrorCode::kerDataSourceOpenFailed, "path", "strerror"),
ASSERT_THROW(enforce(false, Exiv2::ErrorCode::kerCallFailed, "path", "strerror", "function"), Exiv2::Error); Exiv2::Error);
ASSERT_THROW(enforce(false, Exiv2::ErrorCode::kerMallocFailed), Exiv2::Error); ASSERT_THROW(Exiv2::Internal::enforce(false, Exiv2::ErrorCode::kerCallFailed, "path", "strerror", "function"),
ASSERT_THROW(enforce<std::overflow_error>(false, "error message"), std::overflow_error); Exiv2::Error);
ASSERT_THROW(Exiv2::Internal::enforce(false, Exiv2::ErrorCode::kerMallocFailed), Exiv2::Error);
ASSERT_THROW(Exiv2::Internal::enforce<std::overflow_error>(false, "error message"), std::overflow_error);
} }

Loading…
Cancel
Save