Author: tkreuzer
Date: Sun Mar 8 17:25:44 2015
New Revision: 66611
URL:
http://svn.reactos.org/svn/reactos?rev=66611&view=rev
Log:
[WIN32K]
- 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
Modified:
trunk/reactos/win32ss/gdi/eng/bitblt.c
trunk/reactos/win32ss/gdi/eng/surface.c
trunk/reactos/win32ss/gdi/eng/surface.h
trunk/reactos/win32ss/gdi/ntgdi/bitblt.c
trunk/reactos/win32ss/gdi/ntgdi/bitmaps.c
trunk/reactos/win32ss/gdi/ntgdi/dibobj.c
trunk/reactos/win32ss/gdi/ntgdi/freetype.c
trunk/reactos/win32ss/pch.h
Modified: trunk/reactos/win32ss/gdi/eng/bitblt.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/eng/bitblt.c?r…
==============================================================================
--- trunk/reactos/win32ss/gdi/eng/bitblt.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/eng/bitblt.c [iso-8859-1] Sun Mar 8 17:25:44 2015
@@ -1078,6 +1078,7 @@
psoDest->iBitmapFormat,
0,
0,
+ 0,
NULL);
if (psurfTemp == NULL)
{
Modified: trunk/reactos/win32ss/gdi/eng/surface.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/eng/surface.c?…
==============================================================================
--- trunk/reactos/win32ss/gdi/eng/surface.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/eng/surface.c [iso-8859-1] Sun Mar 8 17:25:44 2015
@@ -120,6 +120,7 @@
_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 @@
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 @@
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 @@
}
/* 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 @@
iFormat,
fl,
lWidth,
+ 0,
pvBits);
if (!psurf)
{
@@ -327,6 +359,7 @@
iFormat,
0,
0,
+ 0,
NULL);
if (!psurf)
{
@@ -363,6 +396,7 @@
sizl.cx,
sizl.cy,
iFormat,
+ 0,
0,
0,
NULL);
Modified: trunk/reactos/win32ss/gdi/eng/surface.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/eng/surface.h?…
==============================================================================
--- trunk/reactos/win32ss/gdi/eng/surface.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/eng/surface.h [iso-8859-1] Sun Mar 8 17:25:44 2015
@@ -123,6 +123,7 @@
_In_ ULONG iFormat,
_In_ ULONG fjBitmap,
_In_opt_ ULONG cjWidth,
+ _In_opt_ ULONG cjBits,
_In_opt_ PVOID pvBits);
FORCEINLINE
Modified: trunk/reactos/win32ss/gdi/ntgdi/bitblt.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/bitblt.c…
==============================================================================
--- trunk/reactos/win32ss/gdi/ntgdi/bitblt.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/ntgdi/bitblt.c [iso-8859-1] Sun Mar 8 17:25:44 2015
@@ -1453,6 +1453,7 @@
BMF_32BPP,
0,
0,
+ 0,
&ulRGBColor);
if (psurfDest)
{
Modified: trunk/reactos/win32ss/gdi/ntgdi/bitmaps.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/bitmaps.…
==============================================================================
--- trunk/reactos/win32ss/gdi/ntgdi/bitmaps.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/ntgdi/bitmaps.c [iso-8859-1] Sun Mar 8 17:25:44 2015
@@ -103,6 +103,7 @@
pvCompressedBits = pvBits;
pvBits = NULL;
iFormat = (iFormat == BMF_4RLE) ? BMF_4BPP : BMF_8BPP;
+ cjSizeImage = 0;
}
/* Allocate a surface */
@@ -112,6 +113,7 @@
iFormat,
fjBitmap,
cjWidthBytes,
+ cjSizeImage,
pvBits);
if (!psurf)
{
@@ -205,6 +207,7 @@
nWidth,
nHeight,
iFormat,
+ 0,
0,
0,
NULL);
Modified: trunk/reactos/win32ss/gdi/ntgdi/dibobj.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/dibobj.c…
==============================================================================
--- trunk/reactos/win32ss/gdi/ntgdi/dibobj.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/ntgdi/dibobj.c [iso-8859-1] Sun Mar 8 17:25:44 2015
@@ -1090,7 +1090,7 @@
_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 @@
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 @@
// 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 @@
}
mapOffset = offset - (offset % Sbi.AllocationGranularity);
- mapSize = bi->biSizeImage + (offset - mapOffset);
+ mapSize = totalSize + (offset - mapOffset);
SectionOffset.LowPart = mapOffset;
SectionOffset.HighPart = 0;
@@ -1724,7 +1724,7 @@
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)
Modified: trunk/reactos/win32ss/gdi/ntgdi/freetype.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/freetype…
==============================================================================
--- trunk/reactos/win32ss/gdi/ntgdi/freetype.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/ntgdi/freetype.c [iso-8859-1] Sun Mar 8 17:25:44 2015
@@ -3662,7 +3662,6 @@
ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY));
MouseSafetyOnDrawEnd(dc->ppdev);
BackgroundLeft = DestRect.right;
-
}
DestRect.left = ((TextLeft + 32) >> 6) + realglyph->left;
@@ -3675,71 +3674,75 @@
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.
- */
-
- 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 )
- {
+ /* 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: 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)
{
Modified: trunk/reactos/win32ss/pch.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/pch.h?rev=66611&am…
==============================================================================
--- trunk/reactos/win32ss/pch.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/pch.h [iso-8859-1] Sun Mar 8 17:25:44 2015
@@ -26,6 +26,7 @@
#include <ndk/psfuncs.h>
#include <ndk/rtlfuncs.h>
#include <ntstrsafe.h>
+#include <ntintsafe.h>
#include <ntddkbd.h>
/* Win32 headers */