From 698b418f730918f05cbb55b107e2a18f57789efa Mon Sep 17 00:00:00 2001 From: clanmills Date: Fri, 27 Mar 2020 15:08:22 +0000 Subject: [PATCH] fix_1097_0.27 --- src/crwimage_int.cpp | 20 ++++++++++++++++++-- test/data/issue_1097_poc.crw | Bin 0 -> 4858 bytes tests/bugfixes/github/test_issue_1097.py | 22 ++++++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 test/data/issue_1097_poc.crw create mode 100644 tests/bugfixes/github/test_issue_1097.py diff --git a/src/crwimage_int.cpp b/src/crwimage_int.cpp index d75d8b75..863c3089 100644 --- a/src/crwimage_int.cpp +++ b/src/crwimage_int.cpp @@ -4,6 +4,7 @@ #include "timegm.h" #include "unused.h" #include "error.hpp" +#include "enforce.hpp" #include #include @@ -234,7 +235,8 @@ namespace Exiv2 { uint32_t start, ByteOrder byteOrder) { - if (size < 10) throw Error(kerNotACrwImage); + // We're going read 10 bytes. Make sure they won't be out-of-bounds. + enforce(size >= 10 && start <= size - 10, kerNotACrwImage); tag_ = getUShort(pData + start, byteOrder); DataLocId dl = dataLocation(); @@ -243,8 +245,22 @@ namespace Exiv2 { if (dl == valueData) { size_ = getULong(pData + start + 2, byteOrder); offset_ = getULong(pData + start + 6, byteOrder); + + // Make sure that the sub-region does not overlap with the 10 bytes + // that we just read. (Otherwise a malicious file could cause an + // infinite recursion.) There are two cases two consider because + // the sub-region is allowed to be either before or after the 10 + // bytes in memory. + if (offset_ < start) { + // Sub-region is before in memory. + enforce(size_ <= start - offset_, kerOffsetOutOfRange); + } else { + // Sub-region is after in memory. + enforce(offset_ >= start + 10, kerOffsetOutOfRange); + enforce(offset_ <= size, kerOffsetOutOfRange); + enforce(size_ <= size - offset_, kerOffsetOutOfRange); + } } - if ( size_ > size || offset_ > size ) throw Error(kerOffsetOutOfRange); // #889 if (dl == directoryData) { size_ = 8; offset_ = start + 2; diff --git a/test/data/issue_1097_poc.crw b/test/data/issue_1097_poc.crw new file mode 100644 index 0000000000000000000000000000000000000000..a2bb436cadb3358422f379f3b77b02d8763feedc GIT binary patch literal 4858 zcmebEWnf@v@NjhuaCUYH`i~v_K@kROpdt{UqFH1br32JA2%JHt>qoVXhQMeDjE2By m2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S0y4*>u?ohW$# literal 0 HcmV?d00001 diff --git a/tests/bugfixes/github/test_issue_1097.py b/tests/bugfixes/github/test_issue_1097.py new file mode 100644 index 00000000..f2b4d01a --- /dev/null +++ b/tests/bugfixes/github/test_issue_1097.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- + +from system_tests import CaseMeta, path, check_no_ASAN_UBSAN_errors + + +class InfiniteRecursionInCiffDirectoryReadDirectory(metaclass=CaseMeta): + """ + Regression test for the bug described in: + https://github.com/Exiv2/exiv2/issues/1097 + + A malicious file can cause an infinite recursion. + """ + url = "https://github.com/Exiv2/exiv2/issues/1097" + + filename = path("$data_path/issue_1097_poc.crw") + commands = ["$exiv2 $filename"] + stdout = [""] + stderr = [ + """$exiv2_exception_message $filename: +$kerOffsetOutOfRange +"""] + retval = [1]