namespace enforce.hpp functions to Internal
Signed-off-by: Rosen Penev <rosenp@gmail.com>
This commit is contained in:
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…
Reference in New Issue
Block a user