From 84c1e123e5c0385642bb102847d79aec523884b4 Mon Sep 17 00:00:00 2001 From: Caolán McNamara <caolanm@redhat.com> Date: Thu, 17 May 2012 09:59:21 +0000 Subject: Resolves: rhbz#822216 CVE-2012-1149 --- diff --git a/CVE-2012-1149.patch b/CVE-2012-1149.patch new file mode 100644 index 0000000..40e93c0 --- a/dev/null +++ b/CVE-2012-1149.patch @@ -0,0 +1,212 @@ +diff -ru libreoffice-3.3.4.1/basebmp/source/bitmapdevice.cxx libreoffice-3.3.4.1/basebmp/source/bitmapdevice.cxx +--- libreoffice-3.3.4.1/basebmp/source/bitmapdevice.cxx 2012-05-17 10:44:02.022601383 +0100 ++++ libreoffice-3.3.4.1/basebmp/source/bitmapdevice.cxx 2012-05-17 10:45:42.758685268 +0100 +@@ -1825,8 +1825,16 @@ + // factor in bottom-up scanline order case + nScanlineStride *= bTopDown ? 1 : -1; + +- const std::size_t nMemSize( +- (nScanlineStride < 0 ? -nScanlineStride : nScanlineStride)*rSize.getY() ); ++ const sal_uInt32 nWidth(nScanlineStride < 0 ? -nScanlineStride : nScanlineStride); ++ const sal_uInt32 nHeight(rSize.getY()); ++ ++ if (nHeight && nWidth && nWidth > SAL_MAX_INT32 / nHeight) ++ { ++ //suspicious massive alloc ++ return BitmapDeviceSharedPtr(); ++ } ++ ++ const std::size_t nMemSize(nWidth * nHeight); + + if( !pMem ) + { +diff -ru libreoffice-3.3.4.1/svtools/source/filter.vcl/jpeg/jpeg.cxx libreoffice-3.3.4.1/svtools/source/filter.vcl/jpeg/jpeg.cxx +--- libreoffice-3.3.4.1/svtools/source/filter.vcl/jpeg/jpeg.cxx 2012-05-17 10:44:00.558585642 +0100 ++++ libreoffice-3.3.4.1/svtools/source/filter.vcl/jpeg/jpeg.cxx 2012-05-17 10:49:03.665851751 +0100 +@@ -336,17 +336,26 @@ + + // ------------------------------------------------------------------------ + +-void* JPEGReader::CreateBitmap( void* pParam ) ++void* JPEGReader::CreateBitmap( void* _pParam ) + { +- Size aSize( ((JPEGCreateBitmapParam*)pParam)->nWidth, +- ((JPEGCreateBitmapParam*)pParam)->nHeight ); +- sal_Bool bGray = ((JPEGCreateBitmapParam*)pParam)->bGray != 0; ++ JPEGCreateBitmapParam *pParam = (JPEGCreateBitmapParam *) _pParam; ++ ++ if (pParam->nWidth > SAL_MAX_INT32/8 || pParam->nHeight > SAL_MAX_INT32/8) ++ return NULL; // avoid overflows later ++ ++ Size aSize( pParam->nWidth, pParam->nHeight ); ++ sal_Bool bGray = pParam->bGray != 0; + + void* pBmpBuf = NULL; + + if( pAcc ) + aBmp.ReleaseAccess( pAcc ); + ++ sal_uInt64 nSize = aSize.Width(); ++ nSize *= aSize.Height(); ++ if (nSize > SAL_MAX_INT32 / 24) ++ return NULL; ++ + if( bGray ) + { + BitmapPalette aGrayPal( 256 ); +@@ -367,12 +376,11 @@ + unsigned long nUnit = ((JPEGCreateBitmapParam*)pParam)->density_unit; + + if( ( ( 1 == nUnit ) || ( 2 == nUnit ) ) && +- ( (JPEGCreateBitmapParam*) pParam )->X_density && +- ( (JPEGCreateBitmapParam*) pParam )->Y_density ) ++ pParam->X_density && pParam->Y_density ) + { + Point aEmptyPoint; +- Fraction aFractX( 1, ((JPEGCreateBitmapParam*)pParam)->X_density ); +- Fraction aFractY( 1, ((JPEGCreateBitmapParam*)pParam)->Y_density ); ++ Fraction aFractX( 1, pParam->X_density ); ++ Fraction aFractY( 1, pParam->Y_density ); + MapMode aMapMode( nUnit == 1 ? MAP_INCH : MAP_CM, aEmptyPoint, aFractX, aFractY ); + Size aPrefSize = OutputDevice::LogicToLogic( aSize, aMapMode, MAP_100TH_MM ); + +@@ -385,8 +393,6 @@ + + if( pAcc ) + { +- long nAlignedWidth; +- + const ULONG nFormat = pAcc->GetScanlineFormat(); + + if( +@@ -395,16 +401,15 @@ + ) + { + pBmpBuf = pAcc->GetBuffer(); +- nAlignedWidth = pAcc->GetScanlineSize(); +- ((JPEGCreateBitmapParam*)pParam)->bTopDown = pAcc->IsTopDown(); ++ pParam->nAlignedWidth = pAcc->GetScanlineSize(); ++ pParam->bTopDown = pAcc->IsTopDown(); + } + else + { +- nAlignedWidth = AlignedWidth4Bytes( aSize.Width() * ( bGray ? 8 : 24 ) ); +- ((JPEGCreateBitmapParam*)pParam)->bTopDown = TRUE; +- pBmpBuf = pBuffer = rtl_allocateMemory( nAlignedWidth * aSize.Height() ); ++ pParam->nAlignedWidth = AlignedWidth4Bytes( aSize.Width() * ( bGray ? 8 : 24 ) ); ++ pParam->bTopDown = sal_True; ++ pBmpBuf = pBuffer = rtl_allocateMemory( pParam->nAlignedWidth * aSize.Height() ); + } +- ((JPEGCreateBitmapParam*)pParam)->nAlignedWidth = nAlignedWidth; + } + + return pBmpBuf; +diff -ru libreoffice-3.3.4.1/vcl/source/gdi/pngread.cxx libreoffice-3.3.4.1/vcl/source/gdi/pngread.cxx +--- libreoffice-3.3.4.1/vcl/source/gdi/pngread.cxx 2012-05-17 10:44:18.220775558 +0100 ++++ libreoffice-3.3.4.1/vcl/source/gdi/pngread.cxx 2012-05-17 10:51:41.549558607 +0100 +@@ -202,6 +202,8 @@ + mpScanPrior ( NULL ), + mpTransTab ( NULL ), + mpColorTable ( (sal_uInt8*) mpDefaultColorTable ), ++ mnPass ( 0 ), ++ mbPalette( sal_False ), + mbzCodecInUse ( sal_False ), + mbStatus( TRUE), + mbIDAT( FALSE ), +@@ -305,7 +307,7 @@ + nCRC32 = rtl_crc32( nCRC32, &rChunkData.aData[ 0 ], mnChunkLen ); + maDataIter = rChunkData.aData.begin(); + } +- sal_uInt32 nCheck; ++ sal_uInt32 nCheck(0); + mrPNGStream >> nCheck; + if( nCRC32 != nCheck ) + return false; +@@ -371,14 +373,23 @@ + // reset to the first chunk + maChunkIter = maChunkSeq.begin(); + +- // parse the chunks ++ // first chunk must be IDHR ++ if( mbStatus && ReadNextChunk() ) ++ { ++ if (mnChunkType == PNGCHUNK_IHDR) ++ mbStatus = ImplReadHeader( rPreviewSizeHint ); ++ else ++ mbStatus = false; ++ } ++ ++ // parse the remaining chunks + while( mbStatus && !mbIDAT && ReadNextChunk() ) + { + switch( mnChunkType ) + { + case PNGCHUNK_IHDR : + { +- mbStatus = ImplReadHeader( rPreviewSizeHint ); ++ mbStatus = false; //IHDR should only appear as the first chunk + } + break; + +@@ -635,14 +646,6 @@ + + mnScansize = static_cast< sal_uInt32 >( nScansize64 ); + +- // TODO: switch between both scanlines instead of copying +- mpInflateInBuf = new (std::nothrow) BYTE[ mnScansize ]; +- mpScanCurrent = mpInflateInBuf; +- mpScanPrior = new (std::nothrow) BYTE[ mnScansize ]; +- +- if ( !mpInflateInBuf || !mpScanPrior ) +- return FALSE; +- + // calculate target size from original size and the preview hint + if( rPreviewSizeHint.Width() || rPreviewSizeHint.Height() ) + { +@@ -677,6 +680,21 @@ + maTargetSize.Width() = (maOrigSize.Width() + mnPreviewMask) >> mnPreviewShift; + maTargetSize.Height() = (maOrigSize.Height() + mnPreviewMask) >> mnPreviewShift; + ++ //round bits up to nearest multiple of 8 and divide by 8 to get num of bytes per pixel ++ int nBytesPerPixel = ((mnTargetDepth + 7) & ~7)/8; ++ ++ //stupidly big, forget about it ++ if (maTargetSize.Width() >= SAL_MAX_INT32 / nBytesPerPixel / maTargetSize.Height()) ++ return sal_False; ++ ++ // TODO: switch between both scanlines instead of copying ++ mpInflateInBuf = new (std::nothrow) BYTE[ mnScansize ]; ++ mpScanCurrent = mpInflateInBuf; ++ mpScanPrior = new (std::nothrow) BYTE[ mnScansize ]; ++ ++ if ( !mpInflateInBuf || !mpScanPrior ) ++ return FALSE; ++ + mpBmp = new Bitmap( maTargetSize, mnTargetDepth ); + mpAcc = mpBmp->AcquireWriteAccess(); + if( !mpAcc ) +@@ -788,14 +806,18 @@ + { + if ( mnChunkLen <= 256 ) + { ++ mbTransparent = true; + mpTransTab = new BYTE [ 256 ]; + rtl_fillMemory( mpTransTab, 256, 0xff ); +- rtl_copyMemory( mpTransTab, &(*maDataIter), mnChunkLen ); +- maDataIter += mnChunkLen; +- mbTransparent = true; +- // need alpha transparency if not on/off masking +- for( int i = 0; i < mnChunkLen; ++i ) +- bNeedAlpha |= (mpTransTab[i]!=0x00) && (mpTransTab[i]!=0xFF); ++ if (mnChunkLen > 0) ++ { ++ rtl_copyMemory( mpTransTab, &(*maDataIter), mnChunkLen ); ++ maDataIter += mnChunkLen; ++ mbTransparent = true; ++ // need alpha transparency if not on/off masking ++ for( int i = 0; i < mnChunkLen; ++i ) ++ bNeedAlpha |= (mpTransTab[i]!=0x00) && (mpTransTab[i]!=0xFF); ++ } + } + } + break;