mirror of
https://github.com/reactos/reactos.git
synced 2024-11-30 15:03:32 +08:00
[WIN32K]
Properly check the bitmap size in IntSetDIBits, taking into account that it might be set to 0, then we have to calculate it ourselves. Fixes a crash when invalid data is passed to NtGdiCreateDIBitmapInternal. [GDI32] Convert COREINFOHEADER to BITMAPINFOHEADER before passing it to NtGdiCreateDIBitmapInternal, which doesn't support it. CORE-10583 #resolve svn path=/trunk/; revision=70464
This commit is contained in:
parent
64820cf82f
commit
89cb03b072
@ -408,23 +408,30 @@ CreateDIBitmap(
|
|||||||
// PDC_ATTR pDc_Attr;
|
// PDC_ATTR pDc_Attr;
|
||||||
UINT InfoSize = 0;
|
UINT InfoSize = 0;
|
||||||
UINT cjBmpScanSize = 0;
|
UINT cjBmpScanSize = 0;
|
||||||
HBITMAP hBmp;
|
HBITMAP hBmp = NULL;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
PBITMAPINFO pbmiConverted;
|
||||||
|
UINT cjInfoSize;
|
||||||
|
|
||||||
|
/* Convert the BITMAPINFO if it is a COREINFO */
|
||||||
|
pbmiConverted = ConvertBitmapInfo(Data, ColorUse, &cjInfoSize, FALSE);
|
||||||
|
|
||||||
/* Check for CBM_CREATDIB */
|
/* Check for CBM_CREATDIB */
|
||||||
if (Init & CBM_CREATDIB)
|
if (Init & CBM_CREATDIB)
|
||||||
{
|
{
|
||||||
/* CBM_CREATDIB needs Data. */
|
/* CBM_CREATDIB needs Data. */
|
||||||
if (!Data)
|
if (pbmiConverted == NULL)
|
||||||
{
|
{
|
||||||
return 0;
|
DPRINT1("CBM_CREATDIB needs a BITMAINFO!\n");
|
||||||
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* It only works with PAL or RGB */
|
/* It only works with PAL or RGB */
|
||||||
if (ColorUse > DIB_PAL_COLORS)
|
if (ColorUse > DIB_PAL_COLORS)
|
||||||
{
|
{
|
||||||
|
DPRINT1("Invalid ColorUse: %lu\n", ColorUse);
|
||||||
GdiSetLastError(ERROR_INVALID_PARAMETER);
|
GdiSetLastError(ERROR_INVALID_PARAMETER);
|
||||||
return 0;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use the header from the data */
|
/* Use the header from the data */
|
||||||
@ -434,38 +441,48 @@ CreateDIBitmap(
|
|||||||
/* Header is required */
|
/* Header is required */
|
||||||
if (!Header)
|
if (!Header)
|
||||||
{
|
{
|
||||||
|
DPRINT1("Header is NULL\n");
|
||||||
GdiSetLastError(ERROR_INVALID_PARAMETER);
|
GdiSetLastError(ERROR_INVALID_PARAMETER);
|
||||||
return 0;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the bitmap format and dimensions */
|
/* Get the bitmap format and dimensions */
|
||||||
if (DIB_GetBitmapInfo(Header, &width, &height, &planes, &bpp, &compr, &dibsize) == -1)
|
if (DIB_GetBitmapInfo(Header, &width, &height, &planes, &bpp, &compr, &dibsize) == -1)
|
||||||
{
|
{
|
||||||
|
DPRINT1("DIB_GetBitmapInfo failed!\n");
|
||||||
GdiSetLastError(ERROR_INVALID_PARAMETER);
|
GdiSetLastError(ERROR_INVALID_PARAMETER);
|
||||||
return NULL;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the Compr is incompatible */
|
/* Check if the Compr is incompatible */
|
||||||
if ((compr == BI_JPEG) || (compr == BI_PNG) || (compr == BI_BITFIELDS))
|
if ((compr == BI_JPEG) || (compr == BI_PNG) || (compr == BI_BITFIELDS))
|
||||||
return 0;
|
{
|
||||||
|
DPRINT1("invalid compr: %lu!\n", compr);
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
/* Only DIB_RGB_COLORS (0), DIB_PAL_COLORS (1) and 2 are valid. */
|
/* Only DIB_RGB_COLORS (0), DIB_PAL_COLORS (1) and 2 are valid. */
|
||||||
if (ColorUse > DIB_PAL_COLORS + 1)
|
if (ColorUse > DIB_PAL_COLORS + 1)
|
||||||
{
|
{
|
||||||
|
DPRINT1("invalid compr: %lu!\n", compr);
|
||||||
GdiSetLastError(ERROR_INVALID_PARAMETER);
|
GdiSetLastError(ERROR_INVALID_PARAMETER);
|
||||||
return 0;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If some Bits are given, only DIB_PAL_COLORS and DIB_RGB_COLORS are valid */
|
/* If some Bits are given, only DIB_PAL_COLORS and DIB_RGB_COLORS are valid */
|
||||||
if (Bits && (ColorUse > DIB_PAL_COLORS))
|
if (Bits && (ColorUse > DIB_PAL_COLORS))
|
||||||
{
|
{
|
||||||
|
DPRINT1("Invalid ColorUse: %lu\n", ColorUse);
|
||||||
GdiSetLastError(ERROR_INVALID_PARAMETER);
|
GdiSetLastError(ERROR_INVALID_PARAMETER);
|
||||||
return 0;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Negative width is not allowed */
|
/* Negative width is not allowed */
|
||||||
if (width < 0)
|
if (width < 0)
|
||||||
return 0;
|
{
|
||||||
|
DPRINT1("Negative width: %li\n", width);
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
/* Top-down DIBs have a negative height. */
|
/* Top-down DIBs have a negative height. */
|
||||||
height = abs(height);
|
height = abs(height);
|
||||||
@ -473,13 +490,13 @@ CreateDIBitmap(
|
|||||||
// For Icm support.
|
// For Icm support.
|
||||||
// GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
|
// GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
|
||||||
|
|
||||||
if (Data)
|
if (pbmiConverted)
|
||||||
{
|
{
|
||||||
_SEH2_TRY
|
_SEH2_TRY
|
||||||
{
|
{
|
||||||
cjBmpScanSize = GdiGetBitmapBitsSize((BITMAPINFO *) Data);
|
cjBmpScanSize = GdiGetBitmapBitsSize(pbmiConverted);
|
||||||
CalculateColorTableSize(&Data->bmiHeader, &ColorUse, &InfoSize);
|
CalculateColorTableSize(&pbmiConverted->bmiHeader, &ColorUse, &InfoSize);
|
||||||
InfoSize += Data->bmiHeader.biSize;
|
InfoSize += pbmiConverted->bmiHeader.biSize;
|
||||||
}
|
}
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
@ -490,8 +507,9 @@ CreateDIBitmap(
|
|||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
DPRINT1("Got an exception!\n");
|
||||||
GdiSetLastError(ERROR_INVALID_PARAMETER);
|
GdiSetLastError(ERROR_INVALID_PARAMETER);
|
||||||
return NULL;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("pBMI %p, Size bpp %u, dibsize %d, Conv %u, BSS %u\n", Data, bpp, dibsize, InfoSize,
|
DPRINT("pBMI %p, Size bpp %u, dibsize %d, Conv %u, BSS %u\n", Data, bpp, dibsize, InfoSize,
|
||||||
@ -501,9 +519,18 @@ CreateDIBitmap(
|
|||||||
hBmp = GetStockObject(DEFAULT_BITMAP);
|
hBmp = GetStockObject(DEFAULT_BITMAP);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hBmp = NtGdiCreateDIBitmapInternal(hDC, width, height, Init, (LPBYTE) Bits,
|
hBmp = NtGdiCreateDIBitmapInternal(hDC, width, height, Init, (LPBYTE)Bits,
|
||||||
(LPBITMAPINFO) Data, ColorUse, InfoSize, cjBmpScanSize, 0, 0);
|
(LPBITMAPINFO)pbmiConverted, ColorUse, InfoSize, cjBmpScanSize, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Exit:
|
||||||
|
|
||||||
|
/* Cleanup converted BITMAPINFO */
|
||||||
|
if ((pbmiConverted != NULL) && (pbmiConverted != Data))
|
||||||
|
{
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, pbmiConverted);
|
||||||
|
}
|
||||||
|
|
||||||
return hBmp;
|
return hBmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,11 +259,37 @@ IntSetDIBits(
|
|||||||
POINTL ptSrc;
|
POINTL ptSrc;
|
||||||
EXLATEOBJ exlo;
|
EXLATEOBJ exlo;
|
||||||
PPALETTE ppalDIB = 0;
|
PPALETTE ppalDIB = 0;
|
||||||
|
ULONG cjSizeImage;
|
||||||
|
|
||||||
if (!bmi) return 0;
|
if (!bmi) return 0;
|
||||||
|
|
||||||
if (bmi->bmiHeader.biSizeImage > cjMaxBits)
|
/* Check if the header provided an image size */
|
||||||
|
if (bmi->bmiHeader.biSizeImage != 0)
|
||||||
{
|
{
|
||||||
|
/* Use the given size */
|
||||||
|
cjSizeImage = bmi->bmiHeader.biSizeImage;
|
||||||
|
}
|
||||||
|
/* Otherwise check for uncompressed formats */
|
||||||
|
else if ((bmi->bmiHeader.biCompression == BI_RGB) ||
|
||||||
|
(bmi->bmiHeader.biCompression == BI_BITFIELDS))
|
||||||
|
{
|
||||||
|
/* Calculate the image size */
|
||||||
|
cjSizeImage = DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
|
||||||
|
ScanLines,
|
||||||
|
bmi->bmiHeader.biBitCount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Compressed format without a size. This is invalid. */
|
||||||
|
DPRINT1("Compressed format without a size!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the size that we have is ok */
|
||||||
|
if (cjSizeImage > cjMaxBits)
|
||||||
|
{
|
||||||
|
DPRINT1("Size too large! cjSizeImage = %lu, cjMaxBits = %lu\n",
|
||||||
|
cjSizeImage, cjMaxBits);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +299,7 @@ IntSetDIBits(
|
|||||||
BitmapFormat(bmi->bmiHeader.biBitCount,
|
BitmapFormat(bmi->bmiHeader.biBitCount,
|
||||||
bmi->bmiHeader.biCompression),
|
bmi->bmiHeader.biCompression),
|
||||||
bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
|
bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
|
||||||
bmi->bmiHeader.biSizeImage,
|
cjSizeImage,
|
||||||
(PVOID)Bits,
|
(PVOID)Bits,
|
||||||
0);
|
0);
|
||||||
if (!SourceBitmap)
|
if (!SourceBitmap)
|
||||||
@ -315,6 +341,8 @@ IntSetDIBits(
|
|||||||
ptSrc.x = 0;
|
ptSrc.x = 0;
|
||||||
ptSrc.y = 0;
|
ptSrc.y = 0;
|
||||||
|
|
||||||
|
NT_ASSERT(psurfSrc->SurfObj.cjBits <= cjMaxBits);
|
||||||
|
|
||||||
result = IntEngCopyBits(&psurfDst->SurfObj,
|
result = IntEngCopyBits(&psurfDst->SurfObj,
|
||||||
&psurfSrc->SurfObj,
|
&psurfSrc->SurfObj,
|
||||||
NULL,
|
NULL,
|
||||||
@ -1366,7 +1394,11 @@ IntCreateDIBitmap(
|
|||||||
/* Undocumented flag which creates a DDB of the format specified by the bitmap info. */
|
/* Undocumented flag which creates a DDB of the format specified by the bitmap info. */
|
||||||
handle = IntCreateCompatibleBitmap(Dc, width, height, planes, bpp);
|
handle = IntCreateCompatibleBitmap(Dc, width, height, planes, bpp);
|
||||||
if (!handle)
|
if (!handle)
|
||||||
|
{
|
||||||
|
DPRINT1("IntCreateCompatibleBitmap() failed!\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* The palette must also match the given data */
|
/* The palette must also match the given data */
|
||||||
Surface = SURFACE_ShareLockSurface(handle);
|
Surface = SURFACE_ShareLockSurface(handle);
|
||||||
ASSERT(Surface);
|
ASSERT(Surface);
|
||||||
@ -1430,6 +1462,7 @@ NtGdiCreateDIBitmapInternal(
|
|||||||
safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
|
safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
|
||||||
if(!safeBits)
|
if(!safeBits)
|
||||||
{
|
{
|
||||||
|
DPRINT1("Failed to allocate %lu bytes\n", cjMaxBits);
|
||||||
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1452,6 +1485,7 @@ NtGdiCreateDIBitmapInternal(
|
|||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
if(!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
DPRINT1("Got an exception! pjInit = %p\n", pjInit);
|
||||||
SetLastNtError(Status);
|
SetLastNtError(Status);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -1498,6 +1532,7 @@ GreCreateDIBitmapInternal(
|
|||||||
hdcDest = NtGdiCreateCompatibleDC(0);
|
hdcDest = NtGdiCreateCompatibleDC(0);
|
||||||
if(!hdcDest)
|
if(!hdcDest)
|
||||||
{
|
{
|
||||||
|
DPRINT1("NtGdiCreateCompatibleDC failed\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1509,6 +1544,7 @@ GreCreateDIBitmapInternal(
|
|||||||
Dc = DC_LockDc(hdcDest);
|
Dc = DC_LockDc(hdcDest);
|
||||||
if (!Dc)
|
if (!Dc)
|
||||||
{
|
{
|
||||||
|
DPRINT1("Failed to lock hdcDest %p\n", hdcDest);
|
||||||
EngSetLastError(ERROR_INVALID_HANDLE);
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user