From 109d5df7abd329f141b500c92a00178d35a6bef3 Mon Sep 17 00:00:00 2001 From: Kevin Backhouse Date: Thu, 16 May 2019 14:30:12 +0100 Subject: [PATCH] Check bounds of jpg_img_off and jpg_img_len. (#858) --- src/rafimage.cpp | 30 ++++++++++++++++++------ test/data/issue_857_coverage.raf | Bin 0 -> 5550 bytes test/data/issue_857_poc.raf | Bin 0 -> 5550 bytes tests/bugfixes/github/test_issue_857.py | 28 ++++++++++++++++++++++ 4 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 test/data/issue_857_coverage.raf create mode 100644 test/data/issue_857_poc.raf create mode 100644 tests/bugfixes/github/test_issue_857.py diff --git a/src/rafimage.cpp b/src/rafimage.cpp index 0c23712e..bf3d29c7 100644 --- a/src/rafimage.cpp +++ b/src/rafimage.cpp @@ -34,6 +34,8 @@ #include "basicio.hpp" #include "error.hpp" #include "futils.hpp" +#include "enforce.hpp" +#include "safe_op.hpp" // + standard includes #include @@ -289,17 +291,31 @@ namespace Exiv2 { clearMetadata(); - io_->seek(84,BasicIo::beg); + if (io_->seek(84,BasicIo::beg) != 0) throw Error(kerFailedToReadImageData); byte jpg_img_offset [4]; - io_->read(jpg_img_offset, 4); + if (io_->read(jpg_img_offset, 4) != 4) throw Error(kerFailedToReadImageData); byte jpg_img_length [4]; - io_->read(jpg_img_length, 4); - long jpg_img_off = Exiv2::getULong((const byte *) jpg_img_offset, bigEndian); - long jpg_img_len = Exiv2::getULong((const byte *) jpg_img_length, bigEndian); + if (io_->read(jpg_img_length, 4) != 4) throw Error(kerFailedToReadImageData); + uint32_t jpg_img_off_u32 = Exiv2::getULong((const byte *) jpg_img_offset, bigEndian); + uint32_t jpg_img_len_u32 = Exiv2::getULong((const byte *) jpg_img_length, bigEndian); + + enforce(Safe::add(jpg_img_off_u32, jpg_img_len_u32) <= io_->size(), kerCorruptedMetadata); + +#if LONG_MAX < UINT_MAX + enforce(jpg_img_off_u32 <= static_cast(std::numeric_limits::max()), + kerCorruptedMetadata); + enforce(jpg_img_len_u32 <= static_cast(std::numeric_limits::max()), + kerCorruptedMetadata); +#endif + + long jpg_img_off = static_cast(jpg_img_off_u32); + long jpg_img_len = static_cast(jpg_img_len_u32); + + enforce(jpg_img_len >= 12, kerCorruptedMetadata); DataBuf buf(jpg_img_len - 12); - io_->seek(jpg_img_off + 12,BasicIo::beg); - io_->read(buf.pData_, buf.size_ - 12); + if (io_->seek(jpg_img_off + 12,BasicIo::beg) != 0) throw Error(kerFailedToReadImageData); + io_->read(buf.pData_, buf.size_); if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData); io_->seek(0,BasicIo::beg); // rewind diff --git a/test/data/issue_857_coverage.raf b/test/data/issue_857_coverage.raf new file mode 100644 index 0000000000000000000000000000000000000000..3af0bea30a06fcc19dfd5552f893b75a7838dbdf GIT binary patch literal 5550 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 literal 0 HcmV?d00001 diff --git a/tests/bugfixes/github/test_issue_857.py b/tests/bugfixes/github/test_issue_857.py new file mode 100644 index 00000000..266bebcd --- /dev/null +++ b/tests/bugfixes/github/test_issue_857.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- + +from system_tests import CaseMeta, path + + +class OutOfMemoryInRafImageReadMetadata(metaclass=CaseMeta): + """ + Regression test for the bug described in: + https://github.com/Exiv2/exiv2/issues/857 + + There is no bounds check on the value of jpg_img_len in + RafImage::readMetadata(), leading to an out-of-memory error. + """ + url = "https://github.com/Exiv2/exiv2/issues/857" + + filename1 = path("$data_path/issue_857_poc.raf") + filename2 = path("$data_path/issue_857_coverage.raf") + commands = ["$exiv2 $filename1", "$exiv2 $filename2"] + stdout = ["", ""] + stderr = [ +"""Exiv2 exception in print action for file $filename1: +$kerCorruptedMetadata +""", +"""Exiv2 exception in print action for file $filename2: +This does not look like a TIFF image +""" +] + retval = [1,1]