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; }