File CVE-2020-19716.patch of Package exiv2-0_26.26338
From 109d5df7abd329f141b500c92a00178d35a6bef3 Mon Sep 17 00:00:00 2001
From: Kevin Backhouse <kev@semmle.com>
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
Index: exiv2-0.26/src/rafimage.cpp
===================================================================
--- exiv2-0.26.orig/src/rafimage.cpp
+++ exiv2-0.26/src/rafimage.cpp
@@ -39,6 +39,8 @@ EXIV2_RCSID("@(#) $Id$")
#include "basicio.hpp"
#include "error.hpp"
#include "futils.hpp"
+#include "enforce.hpp"
+#include "safe_op.hpp"
// + standard includes
#include <string>
@@ -295,16 +297,30 @@ 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<uint32_t>(std::numeric_limits<long>::max()),
+ kerCorruptedMetadata);
+ enforce(jpg_img_len_u32 <= static_cast<uint32_t>(std::numeric_limits<long>::max()),
+ kerCorruptedMetadata);
+#endif
+
+ long jpg_img_off = static_cast<long>(jpg_img_off_u32);
+ long jpg_img_len = static_cast<long>(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(14);
io_->seek(0,BasicIo::beg); // rewind