- Pass bitmap buffer size to SURFACE_AllocSurface and validate it
- Fix arithmetic overflow checks by using RtlULongMult
- GreExtTextOutW: do not allocate / blit zero sized bitmaps
- NtGdiStretchDIBitsInternal: do not pass negative y size to GreCreateBitmapEx
- DIB_CreateDIBSection: use calculated bitmap size, instead of biSizeImage when calculating the section view size and as size parameter to GreCreateBitmapEx
CORE-9245 #resolve

svn path=/trunk/; revision=66611
This commit is contained in:
Timo Kreuzer 2015-03-08 17:25:44 +00:00
parent 15f19bca32
commit ff14566384
8 changed files with 116 additions and 72 deletions

View file

@ -1078,6 +1078,7 @@ IntEngMaskBlt(
psoDest->iBitmapFormat,
0,
0,
0,
NULL);
if (psurfTemp == NULL)
{

View file

@ -120,6 +120,7 @@ SURFACE_AllocSurface(
_In_ ULONG iFormat,
_In_ ULONG fjBitmap,
_In_opt_ ULONG cjWidth,
_In_opt_ ULONG cjBufSize,
_In_opt_ PVOID pvBits)
{
ULONG cBitsPixel, cjBits, cjObject;
@ -127,7 +128,9 @@ SURFACE_AllocSurface(
SURFOBJ *pso;
PVOID pvSection;
ASSERT(!pvBits || (iType == STYPE_BITMAP));
NT_ASSERT(!pvBits || (iType == STYPE_BITMAP));
NT_ASSERT((iFormat <= BMF_32BPP) || (cjBufSize != 0));
NT_ASSERT((LONG)cy > 0);
/* Verify format */
if ((iFormat < BMF_1BPP) || (iFormat > BMF_PNG))
@ -151,8 +154,35 @@ SURFACE_AllocSurface(
cjWidth = WIDTH_BYTES_ALIGN32(cx, cBitsPixel);
}
/* Calculate the bitmap size in bytes */
cjBits = cjWidth * cy;
/* Is this an uncompressed format? */
if (iFormat <= BMF_32BPP)
{
/* Calculate the correct bitmap size in bytes */
if (!NT_SUCCESS(RtlULongMult(cjWidth, cy, &cjBits)))
{
DPRINT1("Overflow calculating size: cjWidth %lu, cy %lu\n",
cjWidth, cy);
return NULL;
}
/* Did we get a buffer and size? */
if ((pvBits != NULL) && (cjBufSize != 0))
{
/* Make sure the buffer is large enough */
if (cjBufSize < cjBits)
{
DPRINT1("Buffer is too small, required: %lu, got %lu\n",
cjBits, cjBufSize);
return NULL;
}
}
}
else
{
/* Compressed format, use the provided size */
NT_ASSERT(cjBufSize != 0);
cjBits = cjBufSize;
}
/* Check if we need an extra large object */
if ((iType == STYPE_BITMAP) && (pvBits == NULL) &&
@ -168,9 +198,10 @@ SURFACE_AllocSurface(
}
/* Check for arithmetic overflow */
if ((cjBits < cjWidth) || (cjObject < sizeof(SURFACE)))
if (cjObject < sizeof(SURFACE))
{
/* Fail! */
DPRINT1("Overflow calculating cjObject: cjBits %lu\n", cjBits);
return NULL;
}
@ -289,6 +320,7 @@ EngCreateBitmap(
iFormat,
fl,
lWidth,
0,
pvBits);
if (!psurf)
{
@ -327,6 +359,7 @@ EngCreateDeviceBitmap(
iFormat,
0,
0,
0,
NULL);
if (!psurf)
{
@ -365,6 +398,7 @@ EngCreateDeviceSurface(
iFormat,
0,
0,
0,
NULL);
if (!psurf)
{

View file

@ -123,6 +123,7 @@ SURFACE_AllocSurface(
_In_ ULONG iFormat,
_In_ ULONG fjBitmap,
_In_opt_ ULONG cjWidth,
_In_opt_ ULONG cjBits,
_In_opt_ PVOID pvBits);
FORCEINLINE

View file

@ -1453,6 +1453,7 @@ NtGdiGetPixel(
BMF_32BPP,
0,
0,
0,
&ulRGBColor);
if (psurfDest)
{

View file

@ -103,6 +103,7 @@ GreCreateBitmapEx(
pvCompressedBits = pvBits;
pvBits = NULL;
iFormat = (iFormat == BMF_4RLE) ? BMF_4BPP : BMF_8BPP;
cjSizeImage = 0;
}
/* Allocate a surface */
@ -112,6 +113,7 @@ GreCreateBitmapEx(
iFormat,
fjBitmap,
cjWidthBytes,
cjSizeImage,
pvBits);
if (!psurf)
{
@ -207,6 +209,7 @@ NtGdiCreateBitmap(
iFormat,
0,
0,
0,
NULL);
if (!psurf)
{

View file

@ -1090,7 +1090,7 @@ NtGdiGetDIBitsInternal(
_SEH2_TRY
{
/* Copy the data back */
cjMaxInfo = min(cjMaxInfo, DIB_BitmapInfoSize(pbmi, (WORD)iUsage));
cjMaxInfo = min(cjMaxInfo, (UINT)DIB_BitmapInfoSize(pbmi, (WORD)iUsage));
ProbeForWrite(pbmiUser, cjMaxInfo, 1);
RtlCopyMemory(pbmiUser, pbmi, cjMaxInfo);
}
@ -1228,7 +1228,7 @@ NtGdiStretchDIBitsInternal(
RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
hbmTmp = GreCreateBitmapEx(pbmi->bmiHeader.biWidth,
pbmi->bmiHeader.biHeight,
abs(pbmi->bmiHeader.biHeight),
0,
BitmapFormat(pbmi->bmiHeader.biBitCount,
pbmi->bmiHeader.biCompression),
@ -1652,7 +1652,7 @@ DIB_CreateDIBSection(
// Get storage location for DIB bits. Only use biSizeImage if it's valid and
// we're dealing with a compressed bitmap. Otherwise, use width * height.
totalSize = bi->biSizeImage && bi->biCompression != BI_RGB && bi->biCompression != BI_BITFIELDS
totalSize = (bi->biSizeImage && (bi->biCompression != BI_RGB) && (bi->biCompression != BI_BITFIELDS))
? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
if (section)
@ -1674,7 +1674,7 @@ DIB_CreateDIBSection(
}
mapOffset = offset - (offset % Sbi.AllocationGranularity);
mapSize = bi->biSizeImage + (offset - mapOffset);
mapSize = totalSize + (offset - mapOffset);
SectionOffset.LowPart = mapOffset;
SectionOffset.HighPart = 0;
@ -1724,7 +1724,7 @@ DIB_CreateDIBSection(
BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
((bi->biHeight < 0) ? BMF_TOPDOWN : 0),
bi->biSizeImage,
totalSize,
bm.bmBits,
0);
if (!res)

View file

@ -3662,7 +3662,6 @@ GreExtTextOutW(
ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY));
MouseSafetyOnDrawEnd(dc->ppdev);
BackgroundLeft = DestRect.right;
}
DestRect.left = ((TextLeft + 32) >> 6) + realglyph->left;
@ -3675,72 +3674,76 @@ GreExtTextOutW(
MaskRect.right = realglyph->bitmap.width;
MaskRect.bottom = realglyph->bitmap.rows;
/*
* We should create the bitmap out of the loop at the biggest possible
* glyph size. Then use memset with 0 to clear it and sourcerect to
* limit the work of the transbitblt.
*/
/* Check if the bitmap has any pixels */
if ((bitSize.cx != 0) && (bitSize.cy != 0))
{
/*
* We should create the bitmap out of the loop at the biggest possible
* glyph size. Then use memset with 0 to clear it and sourcerect to
* limit the work of the transbitblt.
*/
HSourceGlyph = EngCreateBitmap(bitSize, realglyph->bitmap.pitch,
BMF_8BPP, BMF_TOPDOWN,
realglyph->bitmap.buffer);
if ( !HSourceGlyph )
{
DPRINT1("WARNING: EngLockSurface() failed!\n");
// FT_Done_Glyph(realglyph);
IntUnLockFreeType;
DC_vFinishBlit(dc, NULL);
goto fail2;
}
SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph);
if ( !SourceGlyphSurf )
{
HSourceGlyph = EngCreateBitmap(bitSize, realglyph->bitmap.pitch,
BMF_8BPP, BMF_TOPDOWN,
realglyph->bitmap.buffer);
if ( !HSourceGlyph )
{
DPRINT1("WARNING: EngCreateBitmap() failed!\n");
// FT_Done_Glyph(realglyph);
IntUnLockFreeType;
DC_vFinishBlit(dc, NULL);
goto fail2;
}
SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph);
if ( !SourceGlyphSurf )
{
EngDeleteSurface((HSURF)HSourceGlyph);
DPRINT1("WARNING: EngLockSurface() failed!\n");
IntUnLockFreeType;
DC_vFinishBlit(dc, NULL);
goto fail2;
}
/*
* Use the font data as a mask to paint onto the DCs surface using a
* brush.
*/
if (lprc && (fuOptions & ETO_CLIPPED) &&
DestRect.right >= lprc->right + dc->ptlDCOrig.x)
{
// We do the check '>=' instead of '>' to possibly save an iteration
// through this loop, since it's breaking after the drawing is done,
// and x is always incremented.
DestRect.right = lprc->right + dc->ptlDCOrig.x;
DoBreak = TRUE;
}
if (lprc && (fuOptions & ETO_CLIPPED) &&
DestRect.bottom >= lprc->bottom + dc->ptlDCOrig.y)
{
DestRect.bottom = lprc->bottom + dc->ptlDCOrig.y;
}
MouseSafetyOnDrawStart(dc->ppdev, DestRect.left, DestRect.top, DestRect.right, DestRect.bottom);
if (!IntEngMaskBlt(
SurfObj,
SourceGlyphSurf,
&dc->co.ClipObj,
&exloRGB2Dst.xlo,
&exloDst2RGB.xlo,
&DestRect,
(PPOINTL)&MaskRect,
&dc->eboText.BrushObject,
&BrushOrigin))
{
DPRINT1("Failed to MaskBlt a glyph!\n");
}
MouseSafetyOnDrawEnd(dc->ppdev) ;
EngUnlockSurface(SourceGlyphSurf);
EngDeleteSurface((HSURF)HSourceGlyph);
DPRINT1("WARNING: EngLockSurface() failed!\n");
IntUnLockFreeType;
DC_vFinishBlit(dc, NULL);
goto fail2;
}
/*
* Use the font data as a mask to paint onto the DCs surface using a
* brush.
*/
if (lprc && (fuOptions & ETO_CLIPPED) &&
DestRect.right >= lprc->right + dc->ptlDCOrig.x)
{
// We do the check '>=' instead of '>' to possibly save an iteration
// through this loop, since it's breaking after the drawing is done,
// and x is always incremented.
DestRect.right = lprc->right + dc->ptlDCOrig.x;
DoBreak = TRUE;
}
if (lprc && (fuOptions & ETO_CLIPPED) &&
DestRect.bottom >= lprc->bottom + dc->ptlDCOrig.y)
{
DestRect.bottom = lprc->bottom + dc->ptlDCOrig.y;
}
MouseSafetyOnDrawStart(dc->ppdev, DestRect.left, DestRect.top, DestRect.right, DestRect.bottom);
if (!IntEngMaskBlt(
SurfObj,
SourceGlyphSurf,
&dc->co.ClipObj,
&exloRGB2Dst.xlo,
&exloDst2RGB.xlo,
&DestRect,
(PPOINTL)&MaskRect,
&dc->eboText.BrushObject,
&BrushOrigin))
{
DPRINT1("Failed to MaskBlt a glyph!\n");
}
MouseSafetyOnDrawEnd(dc->ppdev) ;
EngUnlockSurface(SourceGlyphSurf);
EngDeleteSurface((HSURF)HSourceGlyph);
if (DoBreak)
{
break;

View file

@ -26,6 +26,7 @@
#include <ndk/psfuncs.h>
#include <ndk/rtlfuncs.h>
#include <ntstrsafe.h>
#include <ntintsafe.h>
#include <ntddkbd.h>
/* Win32 headers */