From 37fd5b78b08bcd249c3583a4d8f116ed3211161d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= Date: Sun, 13 Sep 2026 20:15:51 +0000 Subject: [PATCH] ofz#541854037 Timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the polygon point counts were checked against the space left in the whole file, and a small record inside a large file could claim far more points than it holds so bound them by the size of the record instead Signed-off-by: Caolán McNamara Change-Id: I0770546d0d48f9b306461da5e9c0117977079483 Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/12367 Reviewed-by: Noel Grandin Tested-by: Jenkins CPCI (cherry picked from commit 292bae6e2ee1d8749040b258cd7bf415cf6241b4) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/211410 Tested-by: Jenkins Reviewed-by: Xisco Fauli --- emfio/source/reader/wmfreader.cxx | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/emfio/source/reader/wmfreader.cxx b/emfio/source/reader/wmfreader.cxx index b118d531e47e..ac8113af4c8a 100644 --- a/emfio/source/reader/wmfreader.cxx +++ b/emfio/source/reader/wmfreader.cxx @@ -348,6 +348,17 @@ namespace emfio return Size( nW, nH ); } + // The number of points that fit in a record of nRecordSize words. A record starts with + // three words of header followed by nParameterWords of other parameters, and each point + // takes two words. + static sal_uInt32 MaxPointsInRecord(sal_uInt32 nRecordSize, sal_uInt32 nParameterWords) + { + const sal_uInt32 nUsedWords = 3 + nParameterWords; + if (nRecordSize <= nUsedWords) + return 0; + return (nRecordSize - nUsedWords) / 2; + } + void WmfReader::ReadRecordParams( sal_uInt32 nRecordSize, sal_uInt16 nFunc ) { bool bRecordOk = true; @@ -575,7 +586,7 @@ namespace emfio sal_uInt16 nPoints(0); mpInputStream->ReadUInt16(nPoints); - if (nPoints > mpInputStream->remainingSize() / (2 * sizeof(sal_uInt16))) + if (nPoints > MaxPointsInRecord(nRecordSize, 1)) { bRecordOk = false; } @@ -600,7 +611,9 @@ namespace emfio mpInputStream->ReadUInt16( nPolyCount ); if (nPolyCount && mpInputStream->good()) { - if (nPolyCount > mpInputStream->remainingSize() / sizeof(sal_uInt16)) + // One word per polygon holds its point count, and those words sit between + // the polygon count and the points themselves. + if (nRecordSize < 4 || nPolyCount > nRecordSize - 4) break; // Number of points of each polygon. Determine total number of points @@ -623,6 +636,12 @@ namespace emfio SAL_WARN_IF(!bRecordOk, "emfio", "polypolygon record has more polygons than we can handle"); + if (nPoints > MaxPointsInRecord(nRecordSize, 1 + nPolyCount)) + { + SAL_WARN("emfio", "polypolygon record has more points than it can hold"); + bRecordOk = false; + } + bRecordOk &= mpInputStream->good(); if (!bRecordOk) @@ -665,7 +684,7 @@ namespace emfio sal_uInt16 nPoints(0); mpInputStream->ReadUInt16(nPoints); - if (nPoints > mpInputStream->remainingSize() / (2 * sizeof(sal_uInt16))) + if (nPoints > MaxPointsInRecord(nRecordSize, 1)) { bRecordOk = false; }