Skip to content

Commit b7a9785

Browse files
authored
Merge pull request #946 from kevinbackhouse/mrmimage_bounds_checking
mrwimage bounds checking
2 parents 1a9bae4 + be875ce commit b7a9785

File tree

4 files changed

+40
-7
lines changed

4 files changed

+40
-7
lines changed

src/mrwimage.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "image.hpp"
3333
#include "basicio.hpp"
3434
#include "error.hpp"
35+
#include "enforce.hpp"
3536
#include "futils.hpp"
3637

3738
// + standard includes
@@ -114,26 +115,33 @@ namespace Exiv2 {
114115
uint32_t const end = getULong(tmp + 4, bigEndian);
115116

116117
pos += len;
117-
if (pos > end) throw Error(kerFailedToReadImageData);
118+
enforce(pos <= end, kerFailedToReadImageData);
118119
io_->read(tmp, len);
119120
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData);
120121

121122
while (memcmp(tmp + 1, "TTW", 3) != 0) {
122123
uint32_t const siz = getULong(tmp + 4, bigEndian);
124+
enforce(siz <= end - pos, kerFailedToReadImageData);
123125
pos += siz;
124-
if (pos > end) throw Error(kerFailedToReadImageData);
125126
io_->seek(siz, BasicIo::cur);
126-
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData);
127+
enforce(!io_->error() && !io_->eof(), kerFailedToReadImageData);
127128

129+
enforce(len <= end - pos, kerFailedToReadImageData);
128130
pos += len;
129-
if (pos > end) throw Error(kerFailedToReadImageData);
130131
io_->read(tmp, len);
131-
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData);
132+
enforce(!io_->error() && !io_->eof(), kerFailedToReadImageData);
132133
}
133134

134-
DataBuf buf(getULong(tmp + 4, bigEndian));
135+
const uint32_t siz = getULong(tmp + 4, bigEndian);
136+
// First do an approximate bounds check of siz, so that we don't
137+
// get DOS-ed by a 4GB allocation on the next line. If siz is
138+
// greater than io_->size() then it is definitely invalid. But the
139+
// exact bounds checking is done by the call to io_->read, which
140+
// will fail if there are fewer than siz bytes left to read.
141+
enforce(siz <= io_->size(), kerFailedToReadImageData);
142+
DataBuf buf(siz);
135143
io_->read(buf.pData_, buf.size_);
136-
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData);
144+
enforce(!io_->error() && !io_->eof(), kerFailedToReadImageData);
137145

138146
ByteOrder bo = TiffParser::decode(exifData_,
139147
iptcData_,

test/data/issue_943_poc1.mrm

37 Bytes
Binary file not shown.

test/data/issue_943_poc2.mrm

25 Bytes
Binary file not shown.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from system_tests import CaseMeta, path
4+
5+
6+
class MrmImageLargeAllocation(metaclass=CaseMeta):
7+
"""
8+
Regression test for the bug described in:
9+
https://github.com/Exiv2/exiv2/pull/943
10+
"""
11+
url = "https://github.com/Exiv2/exiv2/pull/943"
12+
13+
filename1 = path("$data_path/issue_943_poc1.mrm")
14+
filename2 = path("$data_path/issue_943_poc2.mrm")
15+
commands = ["$exiv2 $filename1", "$exiv2 $filename2"]
16+
stdout = ["",""]
17+
stderr = [
18+
"""Exiv2 exception in print action for file $filename1:
19+
Failed to read image data
20+
""",
21+
"""Exiv2 exception in print action for file $filename2:
22+
Failed to read image data
23+
"""
24+
]
25+
retval = [1,1]

0 commit comments

Comments
 (0)