Skip to content

Commit 89568d6

Browse files
committed
fix(iff): Handle non-zero origin, protect against buffer overflows (#4925)
IffInput::read_native_tile was simply incorrect for images with nonzero data window origin. Fix! Also switch the forumulation to use spancpy rather than memcpy, to be a little more careful that we are't overwriting the presumed sizes of the buffers. And while I'm in there, I realized we can hold the mutex for less time. --------- Signed-off-by: Larry Gritz <[email protected]>
1 parent 677d4b0 commit 89568d6

File tree

1 file changed

+25
-15
lines changed

1 file changed

+25
-15
lines changed

src/iff.imageio/iffinput.cpp

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -505,17 +505,29 @@ bool
505505
IffInput::read_native_tile(int subimage, int miplevel, int x, int y, int /*z*/,
506506
void* data)
507507
{
508-
lock_guard lock(*this);
509508
if (!seek_subimage(subimage, miplevel))
510509
return false;
511510

512-
if (m_buf.empty()) {
513-
if (!readimg()) {
514-
return false;
511+
{
512+
lock_guard lock(*this);
513+
514+
if (m_buf.empty()) {
515+
if (!readimg())
516+
return false;
515517
}
516518
}
517519

518-
// tile size
520+
// Offset vs the image data origin
521+
x -= m_spec.x;
522+
y -= m_spec.y;
523+
524+
if (x < 0 || x >= m_spec.width || y < 0 || y >= m_spec.height) {
525+
errorfmt("Tile coordinate is not within the valid pixel data window");
526+
return false;
527+
}
528+
529+
// tile size that we're reading -- consider if the tile overlaps the image
530+
// boundary.
519531
int w = m_header.width;
520532
int tw = std::min(x + static_cast<int>(m_header.tile_width),
521533
static_cast<int>(m_header.width))
@@ -525,16 +537,14 @@ IffInput::read_native_tile(int subimage, int miplevel, int x, int y, int /*z*/,
525537
- y;
526538

527539
// tile data
528-
int oy = 0;
529-
for (int iy = y; iy < y + th; iy++) {
530-
// in
531-
uint8_t* in_p = m_buf.data() + (iy * w + x) * m_header.pixel_bytes();
532-
// out
533-
uint8_t* out_p = reinterpret_cast<uint8_t*>(data)
534-
+ (oy * m_header.tile_width) * m_header.pixel_bytes();
535-
// copy
536-
memcpy(out_p, in_p, tw * m_header.pixel_bytes());
537-
oy++;
540+
span<uint8_t> dataspan(static_cast<uint8_t*>(data),
541+
m_header.tile_width * m_header.tile_height
542+
* m_header.pixel_bytes());
543+
cspan<uint8_t> bufspan(m_buf);
544+
for (int oy = 0, iy = y; oy < th; ++oy, ++iy) {
545+
spancpy(dataspan, (oy * m_header.tile_width) * m_header.pixel_bytes(),
546+
bufspan, (iy * w + x) * m_header.pixel_bytes(),
547+
tw * m_header.pixel_bytes());
538548
}
539549
return true;
540550
}

0 commit comments

Comments
 (0)