From a2bf0e202371fb4bd4c5996e015c656b0633e424 Mon Sep 17 00:00:00 2001 From: Kamil Hornicek Date: Sat, 4 Mar 2017 10:37:00 +0000 Subject: [PATCH] [WIN32K] - GreGetDIBitsInternal: - Prevent an access violation in DIB_FreeConvertedBitmapInfo by initializing the bit count before calling DIB_ConvertBitmapInfo and setting clrUsed. - Validate input parameters and return correct values - only return number of scan lines if bits are not null and bpp is not zero. Otherwise return 1 on success. - We now pass more gdi32:GetDIBits and gdi32:bitmap tests. CORE-9270 svn path=/trunk/; revision=74046 --- reactos/win32ss/gdi/ntgdi/dibobj.c | 132 ++++++++++++++++++----------- 1 file changed, 84 insertions(+), 48 deletions(-) diff --git a/reactos/win32ss/gdi/ntgdi/dibobj.c b/reactos/win32ss/gdi/ntgdi/dibobj.c index 989373ce004..e56e65469dd 100644 --- a/reactos/win32ss/gdi/ntgdi/dibobj.c +++ b/reactos/win32ss/gdi/ntgdi/dibobj.c @@ -719,36 +719,6 @@ GreGetDIBitsInternal( if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap) return 0; - colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize; - rgbQuads = colorPtr; - - bitmap_type = DIB_GetBitmapInfo(&Info->bmiHeader, - &width, - &height, - &planes, - &bpp, - &compr, - &size); - if(bitmap_type == -1) - { - DPRINT("Wrong bitmap format\n"); - EngSetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - else if(bitmap_type == 0) - { - /* We need a BITMAPINFO to create a DIB, but we have to fill - * the BITMAPCOREINFO we're provided */ - pbmci = (BITMAPCOREINFO*)Info; - Info = DIB_ConvertBitmapInfo((BITMAPINFO*)pbmci, Usage); - if(Info == NULL) - { - DPRINT1("Error, could not convert the BITMAPCOREINFO!\n"); - return 0; - } - rgbQuads = Info->bmiColors; - } - pDC = DC_LockDc(hDC); if (pDC == NULL || pDC->dctype == DC_TYPE_INFO) { @@ -764,6 +734,62 @@ GreGetDIBitsInternal( goto done; } + colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize; + rgbQuads = colorPtr; + + bitmap_type = DIB_GetBitmapInfo(&Info->bmiHeader, + &width, + &height, + &planes, + &bpp, + &compr, + &size); + if(bitmap_type == -1) + { + DPRINT("Wrong bitmap format\n"); + EngSetLastError(ERROR_INVALID_PARAMETER); + ScanLines = 0; + goto done; + } + else if(bitmap_type == 0) + { + /* We need a BITMAPINFO to create a DIB, but we have to fill + * the BITMAPCOREINFO we're provided */ + pbmci = (BITMAPCOREINFO*)Info; + /* fill in the the bit count, so we can calculate the right ColorsSize during the conversion */ + pbmci->bmciHeader.bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat); + Info = DIB_ConvertBitmapInfo((BITMAPINFO*)pbmci, Usage); + if(Info == NULL) + { + DPRINT1("Error, could not convert the BITMAPCOREINFO!\n"); + ScanLines = 0; + goto done; + } + rgbQuads = Info->bmiColors; + } + + /* Validate input: + - negative width is always an invalid value + - non-null Bits and zero bpp is an invalid combination + - only check the rest of the input params if either bpp is non-zero or Bits are set */ + if (width < 0 || (bpp == 0 && Bits)) + { + ScanLines = 0; + goto done; + } + + if (Bits || bpp) + { + if ((height == 0 || planes < 0 || width == 0) || (compr && compr != BI_BITFIELDS && compr != BI_RGB)) + { + ScanLines = 0; + goto done; + } + } + + Info->bmiHeader.biClrUsed = 0; + Info->bmiHeader.biClrImportant = 0; + /* Fill in the structure */ switch(bpp) { @@ -777,27 +803,21 @@ GreGetDIBitsInternal( Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( Info->bmiHeader.biWidth, Info->bmiHeader.biHeight, Info->bmiHeader.biBitCount); - - if ((Info->bmiHeader.biBitCount == 16) || - (Info->bmiHeader.biBitCount == 32)) - { - Info->bmiHeader.biCompression = BI_BITFIELDS; - } - else - { - Info->bmiHeader.biCompression = BI_RGB; - } + Info->bmiHeader.biCompression = (Info->bmiHeader.biBitCount == 16 || Info->bmiHeader.biBitCount == 32) ? + BI_BITFIELDS : BI_RGB; Info->bmiHeader.biXPelsPerMeter = 0; Info->bmiHeader.biYPelsPerMeter = 0; - Info->bmiHeader.biClrUsed = 0; - Info->bmiHeader.biClrImportant = 0; - ScanLines = abs(Info->bmiHeader.biHeight); + + if (Info->bmiHeader.biBitCount <= 8 && Info->bmiHeader.biClrUsed == 0) + Info->bmiHeader.biClrUsed = 1 << Info->bmiHeader.biBitCount; + + ScanLines = 1; goto done; case 1: case 4: case 8: - Info->bmiHeader.biClrUsed = 0; + Info->bmiHeader.biClrUsed = 1 << bpp; /* If the bitmap is a DIB section and has the same format as what * is requested, go ahead! */ @@ -931,8 +951,14 @@ GreGetDIBitsInternal( } } break; + + default: + ScanLines = 0; + goto done; } + Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(width, height, bpp); + Info->bmiHeader.biPlanes = 1; if(Bits && ScanLines) { @@ -1019,13 +1045,22 @@ GreGetDIBitsInternal( GreDeleteObject(hBmpDest); EXLATEOBJ_vCleanup(&exlo); } - else ScanLines = abs(height); + else + { + /* Signals success and not the actual number of scan lines*/ + ScanLines = 1; + } done: - if(pDC) DC_UnlockDc(pDC); - if(psurf) SURFACE_ShareUnlockSurface(psurf); - if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci, Usage); + if (pbmci) + DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci, Usage); + + if (psurf) + SURFACE_ShareUnlockSurface(psurf); + + if (pDC) + DC_UnlockDc(pDC); return ScanLines; } @@ -2074,6 +2109,7 @@ DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage) pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth, pNewBmi->bmiHeader.biHeight, pNewBmi->bmiHeader.biBitCount); + pNewBmi->bmiHeader.biClrUsed = numColors; if(Usage == DIB_PAL_COLORS) {