check for short reads
diff --git a/sw/source/filter/ww8/ww8scan.cxx b/sw/source/filter/ww8/ww8scan.cxx
index 5c5b32d..b4cceca 100644
--- a/sw/source/filter/ww8/ww8scan.cxx
+++ b/sw/source/filter/ww8/ww8scan.cxx
@@ -926,9 +926,9 @@ void WW8SprmIter::UpdateMyMembers()
const sal_uInt8* WW8SprmIter::FindSprm(sal_uInt16 nId)
{
while(GetSprms())
while (GetSprms())
{
if( GetAktId() == nId )
if (GetAktId() == nId)
return GetAktParams(); // SPRM found!
advance();
}
@@ -1713,7 +1713,7 @@ WW8ScannerBase::WW8ScannerBase( SvStream* pSt, SvStream* pTblSt,
}
// PLCF fuer TextBox-Stories im Maintext
long nLenTxBxS = (8 > pWw8Fib->nVersion) ? 0 : 22;
sal_uInt32 nLenTxBxS = (8 > pWw8Fib->nVersion) ? 0 : 22;
if( pWwFib->fcPlcftxbxTxt && pWwFib->lcbPlcftxbxTxt )
{
pMainTxbx = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcftxbxTxt,
@@ -2019,18 +2019,25 @@ xub_StrLen WW8ScannerBase::WW8ReadString( SvStream& rStrm, String& rStr,
// WW8PLCFspecial
//-----------------------------------------
WW8PLCFspecial::WW8PLCFspecial(SvStream* pSt, long nFilePos, long nPLCF,
long nStruct)
WW8PLCFspecial::WW8PLCFspecial(SvStream* pSt, sal_uInt32 nFilePos,
sal_uInt32 nPLCF, sal_uInt32 nStruct)
: nIdx(0), nStru(nStruct)
{
nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
const sal_uInt32 nValidMin=4;
sal_Size nOldPos = pSt->Tell();
bool bValid = checkSeek(*pSt, nFilePos);
nPLCF = bValid ? std::min(nPLCF, nValidMin) : nValidMin;
// Pointer auf Pos- u. Struct-Array
pPLCF_PosArray = new sal_Int32[ ( nPLCF + 3 ) / 4 ];
pPLCF_PosArray[0] = 0;
long nOldPos = pSt->Tell();
nPLCF = bValid ? pSt->Read(pPLCF_PosArray, nPLCF) : nValidMin;
pSt->Seek( nFilePos );
pSt->Read( pPLCF_PosArray, nPLCF );
nPLCF = std::min(nPLCF, nValidMin);
nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
#ifdef OSL_BIGENDIAN
for( nIdx = 0; nIdx <= nIMax; nIdx++ )
pPLCF_PosArray[nIdx] = SWAPLONG( pPLCF_PosArray[nIdx] );
@@ -2041,7 +2048,7 @@ WW8PLCFspecial::WW8PLCFspecial(SvStream* pSt, long nFilePos, long nPLCF,
else
pPLCF_Contents = 0; // kein Inhalt
pSt->Seek( nOldPos );
pSt->Seek(nOldPos);
}
// WW8PLCFspecial::SeekPos() stellt den WW8PLCFspecial auf die Stelle nPos, wobei auch noch der
@@ -2173,23 +2180,18 @@ WW8PLCF::WW8PLCF( SvStream* pSt, WW8_FC nFilePos, sal_Int32 nPLCF, int nStruct,
void WW8PLCF::ReadPLCF( SvStream* pSt, WW8_FC nFilePos, sal_Int32 nPLCF )
{
bool failure = false;
// Pointer auf Pos-Array
pPLCF_PosArray = new WW8_CP[ ( nPLCF + 3 ) / 4 ];
sal_Size nOldPos = pSt->Tell();
pSt->Seek( nFilePos );
failure = pSt->GetError();
bool bValid = checkSeek(*pSt, nFilePos);
if (!failure)
if (bValid)
{
pSt->Read( pPLCF_PosArray, nPLCF );
failure = pSt->GetError();
// Pointer auf Pos-Array
pPLCF_PosArray = new WW8_CP[ ( nPLCF + 3 ) / 4 ];
bValid = checkRead(*pSt, pPLCF_PosArray, nPLCF);
}
if (!failure)
if (bValid)
{
#ifdef OSL_BIGENDIAN
for( nIdx = 0; nIdx <= nIMax; nIdx++ )
@@ -2200,12 +2202,12 @@ void WW8PLCF::ReadPLCF( SvStream* pSt, WW8_FC nFilePos, sal_Int32 nPLCF )
pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
}
pSt->Seek( nOldPos );
OSL_ENSURE(bValid, "Document has corrupt PLCF, ignoring it");
OSL_ENSURE( !failure, "Document has corrupt PLCF, ignoring it" );
if (failure)
if (!bValid)
MakeFailedPLCF();
pSt->Seek(nOldPos);
}
void WW8PLCF::MakeFailedPLCF()
@@ -2341,16 +2343,23 @@ WW8_CP WW8PLCF::Where() const
// WW8PLCFpcd
//-----------------------------------------
WW8PLCFpcd::WW8PLCFpcd( SvStream* pSt, long nFilePos, long nPLCF, long nStruct )
:nStru( nStruct )
WW8PLCFpcd::WW8PLCFpcd(SvStream* pSt, sal_uInt32 nFilePos,
sal_uInt32 nPLCF, sal_uInt32 nStruct)
: nStru( nStruct )
{
nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
const sal_uInt32 nValidMin=4;
sal_Size nOldPos = pSt->Tell();
bool bValid = checkSeek(*pSt, nFilePos);
nPLCF = bValid ? std::min(nPLCF, nValidMin) : nValidMin;
pPLCF_PosArray = new sal_Int32[ ( nPLCF + 3 ) / 4 ]; // Pointer auf Pos-Array
pPLCF_PosArray[0] = 0;
long nOldPos = pSt->Tell();
nPLCF = bValid ? pSt->Read(pPLCF_PosArray, nPLCF) : nValidMin;
nPLCF = std::min(nPLCF, nValidMin);
pSt->Seek( nFilePos );
pSt->Read( pPLCF_PosArray, nPLCF );
nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
#ifdef OSL_BIGENDIAN
for( long nI = 0; nI <= nIMax; nI++ )
pPLCF_PosArray[nI] = SWAPLONG( pPLCF_PosArray[nI] );
@@ -2565,7 +2574,8 @@ WW8PLCFx_Fc_FKP::WW8Fkp::WW8Fkp(ww::WordVersion eVersion, SvStream* pSt,
aEntry.mpData =
new sal_uInt8[aEntry.mnLen + nOrigLen];
aEntry.mbMustDelete = true;
pDataSt->Read(aEntry.mpData, aEntry.mnLen);
aEntry.mnLen =
pDataSt->Read(aEntry.mpData, aEntry.mnLen);
pDataSt->Seek( nCurr );
@@ -7311,12 +7321,16 @@ sal_uInt8* wwSprmParser::findSprmData(sal_uInt16 nId, sal_uInt8* pSprms,
while (nLen > (getVersion()?1:0))
{
sal_uInt16 nAktId = GetSprmId(pSprms);
if (nAktId == nId) // Sprm found
return pSprms + DistanceToData(nId);
// gib Zeiger auf Daten
sal_uInt16 nSize = GetSprmSize(nAktId, pSprms);
OSL_ENSURE(nSize <= nLen, "sprm longer than remaining bytes");
bool bValid = nSize <= nLen;
OSL_ENSURE(bValid, "sprm longer than remaining bytes");
if (nAktId == nId && bValid) // Sprm found
return pSprms + DistanceToData(nId);
//Clip to available size if wrong
nSize = std::min(nSize, nLen);
pSprms += nSize;
@@ -7344,9 +7358,14 @@ SEPr::SEPr() :
memset(rgdxaColumnWidthSpacing, 0, sizeof(rgdxaColumnWidthSpacing));
}
bool checkSeek(SvStream &rSt, WW8_FC nOffset)
bool checkSeek(SvStream &rSt, sal_uInt32 nOffset)
{
return (rSt.Seek(nOffset) == static_cast<sal_Size>(nOffset));
}
bool checkRead(SvStream &rSt, void *pDest, sal_uInt32 nLength)
{
return (rSt.Read(pDest, nLength) == static_cast<sal_Size>(nLength));
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8scan.hxx b/sw/source/filter/ww8/ww8scan.hxx
index 18f6236..a592c83 100644
--- a/sw/source/filter/ww8/ww8scan.hxx
+++ b/sw/source/filter/ww8/ww8scan.hxx
@@ -218,10 +218,10 @@ private:
sal_uInt8* pPLCF_Contents; ///< Pointer auf Inhalts-Array-Teil des Pos-Array
long nIMax; ///< Anzahl der Elemente
long nIdx; ///< Merker, wo wir gerade sind
long nStru;
sal_uInt32 nStru;
public:
WW8PLCFspecial( SvStream* pSt, long nFilePos, long nPLCF,
long nStruct );
WW8PLCFspecial(SvStream* pSt, sal_uInt32 nFilePos, sal_uInt32 nPLCF,
sal_uInt32 nStruct);
~WW8PLCFspecial() { delete[] pPLCF_PosArray; }
long GetIdx() const { return nIdx; }
void SetIdx( long nI ) { nIdx = nI; }
@@ -328,9 +328,10 @@ friend class WW8PLCFpcd_Iter;
sal_Int32* pPLCF_PosArray; // Pointer auf Pos-Array und auf ganze Struktur
sal_uInt8* pPLCF_Contents; // Pointer auf Inhalts-Array-Teil des Pos-Array
long nIMax;
long nStru;
sal_uInt32 nStru;
public:
WW8PLCFpcd( SvStream* pSt, long nFilePos, long nPLCF, long nStruct );
WW8PLCFpcd(SvStream* pSt, sal_uInt32 nFilePos, sal_uInt32 nPLCF,
sal_uInt32 nStruct);
~WW8PLCFpcd(){ delete[] pPLCF_PosArray; }
};
@@ -1780,7 +1781,8 @@ std::vector<sal_uInt8> ChpxToSprms(const Word2CHPX &rChpx);
sal_uLong SafeReadString(ByteString &rStr,sal_uInt16 nLen,SvStream &rStrm);
bool checkSeek(SvStream &rSt, WW8_FC nOffset);
bool checkSeek(SvStream &rSt, sal_uInt32 nOffset);
bool checkRead(SvStream &rSt, void *pDest, sal_uInt32 nLength);
//MS has a (slightly) inaccurate view of how many twips
//are in the default letter size of a page