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?re... ============================================================================== --- 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?r... ============================================================================== --- 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?r... ============================================================================== --- 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.c... ============================================================================== --- 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&... ============================================================================== --- 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 */