summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vcl/source/gdi/dibtools.cxx64
1 files changed, 48 insertions, 16 deletions
diff --git a/vcl/source/gdi/dibtools.cxx b/vcl/source/gdi/dibtools.cxx
index 75e39e6f018e..f45fa3d206c8 100644
--- a/vcl/source/gdi/dibtools.cxx
+++ b/vcl/source/gdi/dibtools.cxx
@@ -331,6 +331,22 @@ bool ImplReadDIBPalette( SvStream& rIStm, BitmapWriteAccess& rAcc, bool bQuad )
return( rIStm.GetError() == 0UL );
}
+namespace
+{
+ sal_uInt8 SanitizePaletteIndex(sal_uInt8 nIndex, bool bHasPalette, sal_uInt16 nPaletteEntryCount)
+ {
+ if (bHasPalette && nIndex >= nPaletteEntryCount)
+ {
+ auto nSanitizedIndex = nIndex % nPaletteEntryCount;
+ SAL_WARN_IF(nIndex != nSanitizedIndex, "vcl", "invalid colormap index: "
+ << static_cast<unsigned int>(nIndex) << ", colormap len is: "
+ << nPaletteEntryCount);
+ nIndex = nSanitizedIndex;
+ }
+ return nIndex;
+ }
+}
+
bool ImplDecodeRLE( sal_uInt8* pBuffer, DIBV5Header& rHeader, BitmapWriteAccess& rAcc, bool bRLE4 )
{
Scanline pRLE = pBuffer;
@@ -342,6 +358,8 @@ bool ImplDecodeRLE( sal_uInt8* pBuffer, DIBV5Header& rHeader, BitmapWriteAccess&
sal_uLong nX = 0UL;
sal_uInt8 cTmp;
bool bEndDecoding = false;
+ const bool bHasPalette = rAcc.HasPalette();
+ const sal_uInt16 nPaletteEntryCount = rAcc.GetPaletteEntryCount();
do
{
@@ -367,10 +385,10 @@ bool ImplDecodeRLE( sal_uInt8* pBuffer, DIBV5Header& rHeader, BitmapWriteAccess&
cTmp = *pRLE++;
if( nX < nWidth )
- rAcc.SetPixelIndex( nY, nX++, cTmp >> 4 );
+ rAcc.SetPixelIndex(nY, nX++, SanitizePaletteIndex(cTmp >> 4, bHasPalette, nPaletteEntryCount));
if( nX < nWidth )
- rAcc.SetPixelIndex( nY, nX++, cTmp & 0x0f );
+ rAcc.SetPixelIndex(nY, nX++, SanitizePaletteIndex(cTmp & 0x0f, bHasPalette, nPaletteEntryCount));
}
if( nRunByte & 1 )
@@ -379,7 +397,7 @@ bool ImplDecodeRLE( sal_uInt8* pBuffer, DIBV5Header& rHeader, BitmapWriteAccess&
return false;
if( nX < nWidth )
- rAcc.SetPixelIndex( nY, nX++, *pRLE >> 4 );
+ rAcc.SetPixelIndex(nY, nX++, SanitizePaletteIndex(*pRLE >> 4, bHasPalette, nPaletteEntryCount));
pRLE++;
}
@@ -400,7 +418,7 @@ bool ImplDecodeRLE( sal_uInt8* pBuffer, DIBV5Header& rHeader, BitmapWriteAccess&
return false;
if( nX < nWidth )
- rAcc.SetPixelIndex( nY, nX++, *pRLE );
+ rAcc.SetPixelIndex(nY, nX++, SanitizePaletteIndex(*pRLE, bHasPalette, nPaletteEntryCount));
pRLE++;
}
@@ -447,19 +465,19 @@ bool ImplDecodeRLE( sal_uInt8* pBuffer, DIBV5Header& rHeader, BitmapWriteAccess&
for( sal_uLong i = 0UL; i < nRunByte; i++ )
{
if( nX < nWidth )
- rAcc.SetPixelIndex( nY, nX++, cTmp >> 4 );
+ rAcc.SetPixelIndex(nY, nX++, SanitizePaletteIndex(cTmp >> 4, bHasPalette, nPaletteEntryCount));
if( nX < nWidth )
- rAcc.SetPixelIndex( nY, nX++, cTmp & 0x0f );
+ rAcc.SetPixelIndex(nY, nX++, SanitizePaletteIndex(cTmp & 0x0f, bHasPalette, nPaletteEntryCount));
}
if( ( nCountByte & 1 ) && ( nX < nWidth ) )
- rAcc.SetPixelIndex( nY, nX++, cTmp >> 4 );
+ rAcc.SetPixelIndex(nY, nX++, SanitizePaletteIndex(cTmp >> 4, bHasPalette, nPaletteEntryCount));
}
else
{
for( sal_uLong i = 0UL; ( i < nCountByte ) && ( nX < nWidth ); i++ )
- rAcc.SetPixelIndex( nY, nX++, cTmp );
+ rAcc.SetPixelIndex(nY, nX++, SanitizePaletteIndex(cTmp, bHasPalette, nPaletteEntryCount));
}
}
}
@@ -481,10 +499,10 @@ bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& r
switch(rAcc.GetScanlineFormat())
{
case ScanlineFormat::N1BitMsbPal:
- case ScanlineFormat::N4BitMsnPal:
- case ScanlineFormat::N8BitPal:
case ScanlineFormat::N24BitTcBgr:
{
+ // we can't trust arbitrary-sourced index based formats to have correct indexes, so we exclude the pal formats
+ // from raw read and force checking their colormap indexes
bNative = ( ( static_cast< bool >(rAcc.IsBottomUp()) != bTopDown ) && !bRLE && !bTCMask && ( rAcc.GetScanlineSize() == nAlignedWidth ) );
break;
}
@@ -496,7 +514,7 @@ bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& r
}
// Read data
- if(bNative)
+ if (bNative)
{
if (nAlignedWidth
> std::numeric_limits<sal_Size>::max() / rHeader.nHeight)
@@ -520,7 +538,7 @@ bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& r
rIStm.ReadUInt32( nBMask );
}
- if(bRLE)
+ if (bRLE)
{
if(!rHeader.nSizeImage)
{
@@ -550,6 +568,9 @@ bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& r
{
case 1:
{
+ const bool bHasPalette = rAcc.HasPalette();
+ const sal_uInt16 nPaletteEntryCount = rAcc.GetPaletteEntryCount();
+
for( ; nCount--; nY += nI )
{
sal_uInt8* pTmp;
@@ -568,7 +589,8 @@ bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& r
cTmp = *pTmp++;
}
- rAcc.SetPixelIndex( nY, nX, (cTmp >> --nShift) & 1);
+ auto nIndex = (cTmp >> --nShift) & 1;
+ rAcc.SetPixelIndex(nY, nX, SanitizePaletteIndex(nIndex, bHasPalette, nPaletteEntryCount));
}
}
}
@@ -576,6 +598,9 @@ bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& r
case 4:
{
+ const bool bHasPalette = rAcc.HasPalette();
+ const sal_uInt16 nPaletteEntryCount = rAcc.GetPaletteEntryCount();
+
for( ; nCount--; nY += nI )
{
sal_uInt8* pTmp;
@@ -594,7 +619,8 @@ bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& r
cTmp = *pTmp++;
}
- rAcc.SetPixelIndex( nY, nX, (cTmp >> ( --nShift << 2UL ) ) & 0x0f);
+ auto nIndex = (cTmp >> ( --nShift << 2UL ) ) & 0x0f;
+ rAcc.SetPixelIndex(nY, nX, SanitizePaletteIndex(nIndex, bHasPalette, nPaletteEntryCount));
}
}
}
@@ -602,6 +628,9 @@ bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& r
case 8:
{
+ const bool bHasPalette = rAcc.HasPalette();
+ const sal_uInt16 nPaletteEntryCount = rAcc.GetPaletteEntryCount();
+
for( ; nCount--; nY += nI )
{
sal_uInt8* pTmp;
@@ -612,7 +641,10 @@ bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& r
}
for( long nX = 0L; nX < nWidth; nX++ )
- rAcc.SetPixelIndex( nY, nX, *pTmp++ );
+ {
+ auto nIndex = *pTmp++;
+ rAcc.SetPixelIndex(nY, nX, SanitizePaletteIndex(nIndex, bHasPalette, nPaletteEntryCount));
+ }
}
}
break;
@@ -895,7 +927,7 @@ bool ImplReadDIBBody( SvStream& rIStm, Bitmap& rBmp, AlphaMask* pBmpAlpha, sal_u
}
// read palette
- if(nColors)
+ if (nColors)
{
pAcc->SetPaletteEntryCount(nColors);
ImplReadDIBPalette(*pIStm, *pAcc, aHeader.nSize != DIBCOREHEADERSIZE);