From 1819fda4800af68bf688c7e111504f36f0ea5854 Mon Sep 17 00:00:00 2001 From: Acts1631 <69813585+acts-1631@users.noreply.github.com> Date: Wed, 4 Nov 2026 11:07:19 -0500 Subject: [PATCH] Validate Ogg page bounds before saving (#1491) Ogg page lacing values can declare payload beyond EOF. During an in-memory tag update, that replacement span can underflow the length passed to memmove and crash the process. Reject truncated pages and make ByteVectorStream::insert ignore invalid replacement ranges before doing offset arithmetic. --- taglib/ogg/oggpageheader.cpp | 7 +++++++ taglib/toolkit/tbytevectorstream.cpp | 11 ++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/taglib/ogg/oggpageheader.cpp b/taglib/ogg/oggpageheader.cpp index 6ed844ad..18aeba8f 100644 --- a/taglib/ogg/oggpageheader.cpp +++ b/taglib/ogg/oggpageheader.cpp @@ -272,6 +272,13 @@ void Ogg::PageHeader::read(Ogg::File *file, offset_t pageOffset) else d->lastPacketCompleted = true; + const offset_t streamLength = file->length(); + if(streamLength < 0 || pageOffset > streamLength || + d->size + d->dataSize > streamLength - pageOffset) { + debug("Ogg::PageHeader::read() -- page data exceeds stream length"); + return; + } + d->isValid = true; } diff --git a/taglib/toolkit/tbytevectorstream.cpp b/taglib/toolkit/tbytevectorstream.cpp index 1c369643..03e0e57e 100644 --- a/taglib/toolkit/tbytevectorstream.cpp +++ b/taglib/toolkit/tbytevectorstream.cpp @@ -27,6 +27,7 @@ #include +#include "tdebug.h" #include "tstring.h" using namespace TagLib; @@ -82,7 +83,15 @@ void ByteVectorStream::writeBlock(const ByteVector &data) void ByteVectorStream::insert(const ByteVector &data, offset_t start, size_t replace) { - offset_t sizeDiff = data.size() - replace; + const offset_t streamLength = length(); + if(start < 0 || start > streamLength || + replace > static_cast(streamLength - start)) { + debug("ByteVectorStream::insert() -- replacement range is out of bounds"); + return; + } + + const offset_t sizeDiff = static_cast(data.size()) - + static_cast(replace); if(sizeDiff < 0) { removeBlock(start + data.size(), -sizeDiff); }