Skip to content

Commit f683bbe

Browse files
committed
fix(iff): Handle non-zero origin, protect against buffer overflows
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 ff46d14 commit f683bbe

File tree

1 file changed

+20
-15
lines changed

1 file changed

+20
-15
lines changed

src/iff.imageio/iffinput.cpp

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -505,17 +505,24 @@ 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+
// tile size that we're reading -- consider if the tile overlaps the image
525+
// boundary.
519526
int w = m_header.width;
520527
int tw = std::min(x + static_cast<int>(m_header.tile_width),
521528
static_cast<int>(m_header.width))
@@ -525,16 +532,14 @@ IffInput::read_native_tile(int subimage, int miplevel, int x, int y, int /*z*/,
525532
- y;
526533

527534
// 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++;
535+
span<uint8_t> dataspan(static_cast<uint8_t*>(data),
536+
m_header.tile_width * m_header.tile_height
537+
* m_header.pixel_bytes());
538+
cspan<uint8_t> bufspan(m_buf);
539+
for (int oy = 0, iy = y; oy < th; ++oy, ++iy) {
540+
spancpy(dataspan, (oy * m_header.tile_width) * m_header.pixel_bytes(),
541+
bufspan, (iy * w + x) * m_header.pixel_bytes(),
542+
tw * m_header.pixel_bytes());
538543
}
539544
return true;
540545
}

0 commit comments

Comments
 (0)