From 984bb7858f678fa6d49479d86aca6f9807b6a449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= Date: Tue, 22 Sep 2026 15:21:01 +0000 Subject: [PATCH] check the byte ranges of a pdf signature against the file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The offsets and lengths come from the document, so a range that is not inside the file leaves the signature unchecked now. Signed-off-by: Caolán McNamara Change-Id: I4c293d4c49326cb08336295714dec91d833bbd88 Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/13334 Tested-by: Jenkins CPCI Reviewed-by: Noel Grandin (cherry picked from commit 2fb3bbcf0afd5d13f41d526551835a24a0d8b5aa) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/211454 Tested-by: Jenkins Reviewed-by: Xisco Fauli --- svl/source/crypto/cryptosign.cxx | 9 +++++++++ xmlsecurity/source/helper/pdfsignaturehelper.cxx | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/svl/source/crypto/cryptosign.cxx b/svl/source/crypto/cryptosign.cxx index b245de24f103..f9e23c54d89a 100644 --- a/svl/source/crypto/cryptosign.cxx +++ b/svl/source/crypto/cryptosign.cxx @@ -2203,9 +2203,18 @@ bool Signing::Verify(SvStream& rStream, #if USE_CRYPTO_ANY std::vector buffer; + const sal_uInt64 nStreamSize = rStream.TellEnd(); + // Copy the byte ranges into a single buffer. for (const auto& rByteRange : aByteRanges) { + // A signature covers a part of the file, so both ends of every range are inside it. + if (rByteRange.first > nStreamSize || rByteRange.second > nStreamSize - rByteRange.first) + { + SAL_WARN("svl.crypto", "Verify: byte range is outside the stream"); + return false; + } + rStream.Seek(rByteRange.first); const size_t size = buffer.size(); buffer.resize(size + rByteRange.second); diff --git a/xmlsecurity/source/helper/pdfsignaturehelper.cxx b/xmlsecurity/source/helper/pdfsignaturehelper.cxx index 9e443f4a01a2..c7e980b7a131 100644 --- a/xmlsecurity/source/helper/pdfsignaturehelper.cxx +++ b/xmlsecurity/source/helper/pdfsignaturehelper.cxx @@ -131,6 +131,14 @@ void GetByteRangesFromPDF(const std::unique_ptr& pSig size_t nByteRangeOffset = 0; for (size_t i = 0; i < aByteRange.size(); ++i) { + // Only offsets and lengths that are zero or more describe a part of the file. + if (aByteRange[i] < 0) + { + SAL_WARN("xmlsecurity.helper", "GetByteRangesFromPDF: negative byte range"); + rByteRanges.clear(); + return; + } + if (i % 2 == 0) { nByteRangeOffset = aByteRange[i];