From 19d65cc2d376141f3daac8798b8ac5ac0047875c Mon Sep 17 00:00:00 2001 From: Larry Gritz Date: Fri, 26 Jun 2026 22:33:40 -0400 Subject: [PATCH] fix(filesystem): overflow-safe bounds check in IOMemReader::pread IOMemReader::pread guarded its memcpy with `size + size_t(offset) > m_buf.size()`. For a large or negative offset, that addition wraps around size_t and can compare as in-bounds, skipping both the error path and the size clamp, so the memcpy reads past (or before) the buffer. Assisted-by: Claude Code / Claude Opus 4.8 Signed-off-by: Larry Gritz --- src/libutil/filesystem.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/libutil/filesystem.cpp b/src/libutil/filesystem.cpp index c9cce650a5..b449e14695 100644 --- a/src/libutil/filesystem.cpp +++ b/src/libutil/filesystem.cpp @@ -1423,15 +1423,16 @@ Filesystem::IOMemReader::pread(void* buf, size_t size, int64_t offset) // N.B. No lock necessary if (!m_buf.size() || !size) return 0; - if (size + size_t(offset) > std::size(m_buf)) { - if (offset < 0 || size_t(offset) >= std::size(m_buf)) { - error(Strutil::fmt::format( - "Invalid pread offset {} for an IOMemReader buffer of size {}", - offset, m_buf.size())); - return 0; - } - size = std::size(m_buf) - size_t(offset); + // Validate the offset before any arithmetic that could overflow. + if (offset < 0 || size_t(offset) >= m_buf.size()) { + error(Strutil::format( + "Invalid pread offset {} for an IOMemReader buffer of size {}", + offset, m_buf.size())); + return 0; } + // offset is now known to be in [0, buffer size), so this subtraction + // cannot underflow. Clamp the read to the bytes actually available. + size = std::min(size, m_buf.size() - size_t(offset)); memcpy(buf, m_buf.data() + offset, size); return size; }