Skip to content

Commit a79fac6

Browse files
committed
fix(bmp): use check_open to guard against corrupt resolutions (#5086)
Also change the x and y counters to uint64_t to prevent any possible overflow as it's computing offsets. --------- Signed-off-by: Larry Gritz <lg@larrygritz.com>
1 parent 39fe817 commit a79fac6

4 files changed

Lines changed: 11 additions & 12 deletions

File tree

src/bmp.imageio/bmpinput.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -186,20 +186,14 @@ BmpInput::open(const std::string& name, ImageSpec& newspec,
186186
const int height = (m_dib_header.height >= 0) ? m_dib_header.height
187187
: -m_dib_header.height;
188188
m_spec = ImageSpec(m_dib_header.width, height, nchannels, TypeDesc::UINT8);
189+
if (!check_open(m_spec, { 0, 1 << 16, 0, 1 << 16, 0, 1, 0, 4 }))
190+
return false;
191+
189192
if (m_dib_header.hres > 0 && m_dib_header.vres > 0) {
190193
m_spec.attribute("XResolution", (int)m_dib_header.hres);
191194
m_spec.attribute("YResolution", (int)m_dib_header.vres);
192195
m_spec.attribute("ResolutionUnit", "m");
193196
}
194-
if (m_spec.width < 1 || m_spec.height < 1 || m_spec.nchannels < 1
195-
|| m_spec.image_bytes() < 1
196-
|| m_spec.image_pixels() > std::numeric_limits<uint32_t>::max()) {
197-
errorfmt(
198-
"Invalid image size {} x {} ({} chans, {}), is likely corrupted",
199-
m_spec.width, m_spec.height, m_spec.nchannels, m_spec.format);
200-
close();
201-
return false;
202-
}
203197

204198
// Compute channel shifts & masks (only relevant for 16bpp case)
205199
if (m_dib_header.red_mask == 0 || m_dib_header.green_mask == 0
@@ -309,8 +303,8 @@ BmpInput::read_rle_image()
309303
m_uncompressed.clear();
310304
m_uncompressed.resize(m_spec.image_pixels());
311305
// Note: the clear+resize zeroes out the buffer
312-
bool ok = true;
313-
int y = 0, x = 0;
306+
bool ok = true;
307+
int64_t y = 0, x = 0;
314308
while (ok) {
315309
// Strutil::print("currently at {},{}\n", x, y);
316310
unsigned char rle_pair[2];
@@ -402,7 +396,8 @@ BmpInput::read_native_scanline(int subimage, int miplevel, int y, int /*z*/,
402396
|| m_dib_header.compression == RLE8_COMPRESSION)
403397
&& m_colortable.size()) {
404398
for (int x = 0; x < m_spec.width; ++x) {
405-
int p = m_uncompressed[(m_spec.height - 1 - y) * m_spec.width + x];
399+
int p = m_uncompressed[int64_t(m_spec.height - 1 - y) * m_spec.width
400+
+ x];
406401
auto& c = colortable(p);
407402
mscanline[3 * x] = c.r;
408403
mscanline[3 * x + 1] = c.g;

testsuite/bmp/ref/out.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,3 +301,6 @@ Full command line was:
301301
oiiotool ERROR: read : "src/palette32bit-corrupt.bmp": BMP error: bad BPP (32) for palette image -- presumed corrupt file
302302
Full command line was:
303303
> oiiotool --info -v -a --hash src/palette32bit-corrupt.bmp
304+
oiiotool ERROR: read : "src/huge-width.bmp": bmp image resolution may not exceed 65536x65536, but the file appears to be 536870911x8. Possible corrupt input?
305+
Full command line was:
306+
> oiiotool --info -v -a --hash src/huge-width.bmp

testsuite/bmp/run.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,4 @@
3434
command += info_command ("src/decodecolormap-corrupt.bmp")
3535
command += info_command ("src/bad-y.bmp")
3636
command += info_command ("src/palette32bit-corrupt.bmp")
37+
command += info_command ("src/huge-width.bmp")

testsuite/bmp/src/huge-width.bmp

86 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)