Fix out-of-bounds read in bmffimage.cpp

This commit is contained in:
Kevin Backhouse 2021-04-19 12:36:17 +01:00 committed by Luis Díaz Más
parent 386e464e1f
commit 285e7a4e72
2 changed files with 19 additions and 3 deletions

View File

@ -28,6 +28,7 @@
#include "basicio.hpp"
#include "config.h"
#include "error.hpp"
#include "enforce.hpp"
#include "futils.hpp"
#include "image.hpp"
#include "image_int.hpp"
@ -219,9 +220,13 @@ namespace Exiv2
if (box.length == 1) {
DataBuf data(8);
io_->read(data.pData_, data.size_);
result = (long) getULongLong(data.pData_, endian_);
const uint64_t sz = getULongLong(data.pData_, endian_);
// Check that `sz` is safe to cast to `long`.
enforce(sz <= static_cast<uint64_t>(std::numeric_limits<long>::max()),
Exiv2::kerCorruptedMetadata);
result = (long) sz;
// sanity check
if (result < 8 || result+address > (long)io_->size()) {
if (result < 8 || result > (long)io_->size() - address) {
result = (long)io_->size();
box.length = result;
} else {
@ -231,6 +236,7 @@ namespace Exiv2
// read data in box and restore file position
long restore = io_->tell();
enforce(box.length >= 8, Exiv2::kerCorruptedMetadata);
DataBuf data(box.length - 8);
io_->read(data.pData_, data.size_);
io_->seek(restore, BasicIo::beg);
@ -240,6 +246,7 @@ namespace Exiv2
uint32_t flags = 0;
if (fullBox(box.type)) {
enforce(data.size_ - skip >= 4, Exiv2::kerCorruptedMetadata);
flags = getLong(data.pData_ + skip, endian_); // version/flags
version = (int8_t)flags >> 24;
version &= 0x00ffffff;
@ -248,6 +255,7 @@ namespace Exiv2
switch (box.type) {
case TAG_ftyp: {
enforce(data.size_ >= 4, Exiv2::kerCorruptedMetadata);
fileType_ = getLong(data.pData_, endian_);
if ( bTrace ) {
out << "brand: " << toAscii(fileType_);
@ -261,6 +269,7 @@ namespace Exiv2
bLF = false;
}
enforce(data.size_ - skip >= 2, Exiv2::kerCorruptedMetadata);
int n = getShort(data.pData_ + skip, endian_);
skip += 2;
@ -272,6 +281,7 @@ namespace Exiv2
// 8.11.6.2
case TAG_infe: { // .__._.__hvc1_ 2 0 0 1 0 1 0 0 104 118 99 49 0
enforce(data.size_ - skip >= 8, Exiv2::kerCorruptedMetadata);
/* getLong (data.pData_+skip,endian_) ; */ skip += 4;
uint16_t ID = getShort(data.pData_ + skip, endian_);
skip += 2;
@ -324,6 +334,7 @@ namespace Exiv2
// 8.11.3.1
case TAG_iloc: {
enforce(data.size_ - skip >= 2, Exiv2::kerCorruptedMetadata);
uint8_t u = data.pData_[skip++];
uint16_t offsetSize = u >> 4;
uint16_t lengthSize = u & 0xF;
@ -336,6 +347,7 @@ namespace Exiv2
#else
skip++;
#endif
enforce(data.size_ - skip >= (version < 2 ? 2 : 4), Exiv2::kerCorruptedMetadata);
uint32_t itemCount = version < 2 ? getShort(data.pData_ + skip, endian_)
: getLong(data.pData_ + skip, endian_);
skip += version < 2 ? 2 : 4;
@ -349,6 +361,8 @@ namespace Exiv2
uint32_t base = skip;
for (uint32_t i = 0; i < itemCount; i++) {
skip = base + i * step; // move in 14, 16 or 18 byte steps
enforce(data.size_ - skip >= (version > 2 ? 4 : 2), Exiv2::kerCorruptedMetadata);
enforce(data.size_ - skip >= step, Exiv2::kerCorruptedMetadata);
uint32_t ID = version > 2 ? getLong(data.pData_ + skip, endian_)
: getShort(data.pData_ + skip, endian_);
uint32_t offset = step==14 || step==16 ? getLong(data.pData_ + skip + step - 8, endian_)
@ -371,6 +385,7 @@ namespace Exiv2
} break;
case TAG_ispe: {
enforce(data.size_ - skip >= 12, Exiv2::kerCorruptedMetadata);
skip += 4;
int width = getLong(data.pData_ + skip, endian_);
skip += 4;

View File

@ -14,6 +14,7 @@ class BmffImageReadMetadataOutOfBoundsRead(metaclass=CaseMeta):
commands = ["$exiv2 $filename"]
stdout = [""]
stderr = [
"""$filename1: Could not write metadata to file: $kerCorruptedMetadata
"""Exiv2 exception in print action for file $filename:
$kerCorruptedMetadata
"""]
retval = [1]