ofz#2869 avoid oom with bmp rle images

and to the sanity checks on remaining data size *after*
the seek to the offset, which requires moving the read
of the palette to remain before that seek

Change-Id: I687a79fb3f109556c1a7aaa9423f77a1eb98a3cf
Reviewed-on: https://gerrit.libreoffice.org/42461
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
This commit is contained in:
Caolán McNamara
2017-09-19 11:43:16 +01:00
parent 71ee09947d
commit c66cd02786

View File

@@ -872,6 +872,22 @@ bool ImplReadDIBBody(SvStream& rIStm, Bitmap& rBmp, AlphaMask* pBmpAlpha, sal_uL
pIStm = &rIStm; pIStm = &rIStm;
} }
// read palette
BitmapPalette aPalette;
if (nColors)
{
aPalette.SetEntryCount(nColors);
ImplReadDIBPalette(*pIStm, aPalette, aHeader.nSize != DIBCOREHEADERSIZE);
}
if (pIStm->GetError())
return false;
if (nOffset)
{
pIStm->SeekRel(nOffset - (pIStm->Tell() - nStmPos));
}
const sal_Int64 nBitsPerLine (static_cast<sal_Int64>(aHeader.nWidth) * static_cast<sal_Int64>(aHeader.nBitCount)); const sal_Int64 nBitsPerLine (static_cast<sal_Int64>(aHeader.nWidth) * static_cast<sal_Int64>(aHeader.nBitCount));
if (nBitsPerLine > SAL_MAX_UINT32) if (nBitsPerLine > SAL_MAX_UINT32)
return false; return false;
@@ -880,13 +896,30 @@ bool ImplReadDIBBody(SvStream& rIStm, Bitmap& rBmp, AlphaMask* pBmpAlpha, sal_uL
switch (aHeader.nCompression) switch (aHeader.nCompression)
{ {
case RLE_8: case RLE_8:
{
if (aHeader.nBitCount != 8) if (aHeader.nBitCount != 8)
return false; return false;
break; // (partially) check the image dimensions to avoid potential large bitmap allocation if the input is damaged
case RLE_4: sal_uInt64 nMaxWidth = pIStm->remainingSize();
if (aHeader.nBitCount != 4) nMaxWidth *= 256; //assume generous compression ratio
if (aHeader.nHeight != 0)
nMaxWidth /= aHeader.nHeight;
if (nMaxWidth < static_cast<sal_uInt64>(aHeader.nWidth))
return false; return false;
break; break;
}
case RLE_4:
{
if (aHeader.nBitCount != 4)
return false;
sal_uInt64 nMaxWidth = pIStm->remainingSize();
nMaxWidth *= 512; //assume generous compression ratio
if (aHeader.nHeight != 0)
nMaxWidth /= aHeader.nHeight;
if (nMaxWidth < static_cast<sal_uInt64>(aHeader.nWidth))
return false;
break;
}
case BITFIELDS: case BITFIELDS:
break; break;
case ZCOMPRESS: case ZCOMPRESS:
@@ -931,17 +964,6 @@ bool ImplReadDIBBody(SvStream& rIStm, Bitmap& rBmp, AlphaMask* pBmpAlpha, sal_uL
pAccAlpha = AlphaMask::ScopedWriteAccess(aNewBmpAlpha); pAccAlpha = AlphaMask::ScopedWriteAccess(aNewBmpAlpha);
} }
// read palette
BitmapPalette aPalette;
if (nColors)
{
aPalette.SetEntryCount(nColors);
ImplReadDIBPalette(*pIStm, aPalette, aHeader.nSize != DIBCOREHEADERSIZE);
}
if (pIStm->GetError())
return false;
sal_uInt16 nBitCount(discretizeBitcount(aHeader.nBitCount)); sal_uInt16 nBitCount(discretizeBitcount(aHeader.nBitCount));
const BitmapPalette* pPal = &aPalette; const BitmapPalette* pPal = &aPalette;
//ofz#948 match the surrounding logic of case TransparentType::Bitmap of //ofz#948 match the surrounding logic of case TransparentType::Bitmap of
@@ -964,11 +986,6 @@ bool ImplReadDIBBody(SvStream& rIStm, Bitmap& rBmp, AlphaMask* pBmpAlpha, sal_uL
return false; return false;
} }
if(nOffset)
{
pIStm->SeekRel(nOffset - (pIStm->Tell() - nStmPos));
}
// read bits // read bits
bool bAlphaUsed(false); bool bAlphaUsed(false);
bool bRet = ImplReadDIBBits(*pIStm, aHeader, *pAcc, aPalette, pAccAlpha.get(), bTopDown, bAlphaUsed, nAlignedWidth, bForceToMonoWhileReading); bool bRet = ImplReadDIBBits(*pIStm, aHeader, *pAcc, aPalette, pAccAlpha.get(), bTopDown, bAlphaUsed, nAlignedWidth, bForceToMonoWhileReading);