Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS Tech Support » Purify Flags Uninitialized memory read in ExtCreateRegion Collapse All
Subject Author Date
Kevin Eshbach Apr 27, 2009 - 9:44 AM

Our product uses Prof-UIS for the docking, floating, etc. windows and I have been running our application under Purify to see if anything bad is happening and Purify flagged an uninitialized memory read in ExtCreateRegion.  I’ve attached a call stack with the problem.  I looked at the code and everything seems to be fine.  Can you confirm my findings that Purify is returning a bogus message?  If no problem is present would it be possible to tweak the code in the future so Purify won’t flag it again?


 


[W] UMR: Uninitialized memory read in ExtCreateRegion {1 occurrence}

        Reading 2784 bytes from 0x00211438 (2784 bytes at 0x00211438 uninitialized)

        Address 0x00211438 is argument #3 of ExtCreateRegion

        Address 0x00211438 is 448 bytes into a 3232 byte block at 0x00211278

        Address 0x00211438 points to a Global/LocalAlloc’d block

        Thread ID: 0x1f0

        Error location

             [c:\windows\system32\gDI32.DLL ip=0x67F11DCC]

            CExtBitmap::GenerateColorHRGN(bool,DWORD,DWORD)const [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extcmdicon.cpp:5903]

                            sizeof(RGNDATAHEADER)

                                + (sizeof(RECT) * nMaxParts),

                            pRgnData

             =>             );

                    if( hRgnResult != NULL )

                    {

                        ::CombineRgn(

            CExtBitmap::GenerateColorHRGN(bool,DWORD,DWORD)const [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extcmdicon.cpp:5751]

            CExtPaintManager::DockMarkerBase::CreateFromBitmaps(CRect,eDockMarkerType_t::CExtPaintManager,DWORD,CExtBitmap const&,CExtBitmap const&) [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extpaintmanager2.cpp:8972]

            CExtPaintManager::DockMarkerBase::CreateFromBitmapResources(CRect,eDockMarkerType_t::CExtPaintManager,DWORD,char const*,char const*,char const*,char const*,HINSTANCE__ *,HINSTANCE__ *) [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extpaintmanager2.cpp:8887]

            CExtPaintManager::DockMarkerBeta2::Create(bool,eDockMarkerType_t::CExtPaintManager,CRect) [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extpaintmanager2.cpp:9901]

            CExtPaintManager::DockMarkerBase::Create(bool,eDockMarkerType_t::CExtPaintManager,CRect) [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extpaintmanager2.cpp:9735]

            CExtPaintManager::DockMarker_CreateWnds(HWND__ *,eDockMarkerType_t::CExtPaintManager,CRect,CTypedPtrArray<CPtrArray,CExtDynDockMarkerWnd *>&,int,CExtDynDockMarkerWnd *) [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extpaintmanager2.cpp:10662]

            CExtDynDockMarkerWnd::CreateOuterMarkers(CFrameWnd *,bool,CExtPaintManager *) [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extcontrolbar.cpp:24146]

            CAgUiDynamicControlBar::_DraggingStart(CPoint const&,CPoint const&,CSize) [c:\dev\agimain\source\uif\utilities\aguipersutilities\aguidynamiccontrolbar.cpp:1236]

            CExtControlBar::OnLButtonDown(UINT,CPoint) [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extcontrolbar.cpp:10143]

            CWnd::OnWndMsg(UINT,UINT,long,long *) [f:\sp\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp:2167]

            CWnd::WindowProc(UINT,UINT,long) [f:\sp\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp:1741]

            CControlBar::WindowProc(UINT,UINT,long) [f:\sp\vctools\vc7libs\ship\atlmfc\src\mfc\barcore.cpp:504]

            CExtControlBar::WindowProc(UINT,UINT,long) [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extcontrolbar.cpp:8641]

        Allocation location

             [C:\WINDOWS\system32\KERNEL32.DLL ip=0x6C802140]

            CExtBitmap::GenerateColorHRGN(bool,DWORD,DWORD)const [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extcmdicon.cpp:5764]

            CExtBitmap::GenerateColorHRGN(bool,DWORD,DWORD)const [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extcmdicon.cpp:5751]

            CExtPaintManager::DockMarkerBase::CreateFromBitmaps(CRect,eDockMarkerType_t::CExtPaintManager,DWORD,CExtBitmap const&,CExtBitmap const&) [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extpaintmanager2.cpp:8972]

            CExtPaintManager::DockMarkerBase::CreateFromBitmapResources(CRect,eDockMarkerType_t::CExtPaintManager,DWORD,char const*,char const*,char const*,char const*,HINSTANCE__ *,HINSTANCE__ *) [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extpaintmanager2.cpp:8887]

            CExtPaintManager::DockMarkerBeta2::Create(bool,eDockMarkerType_t::CExtPaintManager,CRect) [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extpaintmanager2.cpp:9901]

            CExtPaintManager::DockMarkerBase::Create(bool,eDockMarkerType_t::CExtPaintManager,CRect) [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extpaintmanager2.cpp:9735]

            CExtPaintManager::DockMarker_CreateWnds(HWND__ *,eDockMarkerType_t::CExtPaintManager,CRect,CTypedPtrArray<CPtrArray,CExtDynDockMarkerWnd *>&,int,CExtDynDockMarkerWnd *) [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extpaintmanager2.cpp:10662]

            CExtDynDockMarkerWnd::CreateOuterMarkers(CFrameWnd *,bool,CExtPaintManager *) [d:\code\thirdparty\foss\prof-uis\agi\2.82\src\extcontrolbar.cpp:24146]

            CAgUiDynamicControlBar::_DraggingStart(CPoint const&,CPoint const&,CSize) [c:\dev\agimain\source\uif\utilities\aguipersutilities\aguidynamiccontrolbar.cpp:1236]


Technical Support Apr 28, 2009 - 2:40 AM

The CExtBitmap::GenerateColorHRGN() and CExtPaintManager::stat_HBITMAPtoHRGN() methods in Prof-UIS are generating the HRGN handles using the ::ExtCreateRegion() Win32 API which uses pre-allocated memory buffers containing the RGNDATAHEADER header data structure and chain of RECT data structures. The size of chain is computed dynamically and has some allocation align. As result, some chains at the rest of allocated memory block can be unused and really uninitialized. We believe the GDI should not try to access this rest of chain because the RGNDATAHEADER header contains information about correct number of used and initialized RECT data structures. The Purify and DevPartner systems does not always perform correct detection of uninitialized memory access in such cases. But we improved the CExtBitmap::GenerateColorHRGN() and CExtPaintManager::stat_HBITMAPtoHRGN() methods and made them filling the just allocated or re-allocated HGLOBAL memory with zero values. This should make these methods compatible with Purify and DevPartner systems.

 HRGN CExtBitmap::GenerateColorHRGN(
	bool bRTL,
	COLORREF clrTransparent,
	COLORREF clrTolerance // = RGB(0,0,0)
	) const
{
	if( IsEmpty() )
	{
		ASSERT( FALSE );
		return NULL;
	}
ULONG nBPP = GetBPP();
	if( nBPP != 32 )
	{
		CExtBitmap other = (*this);
		other.Make32(false);
		return other.GenerateColorHRGN( bRTL, clrTransparent, clrTolerance );
	}
CSize _sizeBitmap = GetSize();
ULONG nScanLineSize = stat_RcScanLineSize( _sizeBitmap.cx, nBPP ); LPBYTE p32bitColorSurface = stat_RcSurface( m_pImageBuffer ); 
	ASSERT( p32bitColorSurface != NULL );
static DWORD g_nReallocSize = ( g_PaintManager.m_bIsWinNT4 ? 1 : 200 ); DWORD nMaxParts = g_nReallocSize; HANDLE hGlobal = ::GlobalAlloc( GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (
sizeof(RECT) * nMaxParts ) );
RGNDATA * pRgnData = (RGNDATA *) ::GlobalLock( hGlobal );
	::memset( LPVOID(pRgnData), 0, sizeof(RGNDATAHEADER) + (
sizeof(RECT) * nMaxParts ) );
	pRgnData->rdh.dwSize	= sizeof(RGNDATAHEADER);
	pRgnData->rdh.iType		= RDH_RECTANGLES;
	pRgnData->rdh.nCount	= pRgnData->rdh.nRgnSize = 0;
	::SetRect( &pRgnData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0 );
BYTE nLowRed	= GetRValue( clrTransparent );
BYTE nLowGreen	= GetGValue( clrTransparent );
BYTE nLowBlue	= GetBValue( clrTransparent );
BYTE nHighRed	= BYTE( min( 0xff, ( nLowRed + GetRValue(clrTolerance) ) )
);
BYTE nHighGreen	= BYTE( min( 0xff, ( nLowGreen + GetGValue(clrTolerance) ) )
);
BYTE nHighBlue	= BYTE( min( 0xff, ( nLowBlue + GetBValue(clrTolerance) ) )
);
HRGN hRgnResult = NULL;
	for( INT _nY = 0; _nY < _sizeBitmap.cy; _nY++ )
	{
		INT nY = _sizeBitmap.cy - _nY - 1;
		for( INT nX = 0; nX < _sizeBitmap.cx; nX++ )
		{
			LPLONG ptrLinePart = (LPLONG)p32bitColorSurface + nX;
			INT nSavedX = nX;
			for( ; nX < _sizeBitmap.cx; ptrLinePart++, nX++ )
			{
				BYTE nColorPart = GetRValue( (*ptrLinePart) );
				if( nColorPart >= nLowRed && nColorPart <= nHighRed )
				{
					nColorPart = GetGValue(
(*ptrLinePart) );
					if( nColorPart >= nLowGreen &&
nColorPart <= nHighGreen )
					{
						nColorPart = GetBValue(
(*ptrLinePart) );
						if( nColorPart >= nLowBlue
&& nColorPart <= nHighBlue )
							break;
					} // if( nColorPart >= nLowGreen && nColorPart <= nHighGreen )
				} // if( nColorPart >= nLowRed && nColorPart <= nHighRed )
			} // for( ; nX < _sizeBitmap.cx; ptrLinePart++, nX++
)

			if( nX > nSavedX )
			{
				if( pRgnData->rdh.nCount >= nMaxParts )
				{
					::GlobalUnlock( hGlobal );
					DWORD dwPrevParts = nMaxParts;
					nMaxParts += g_nReallocSize;
					hGlobal = ::GlobalReAlloc( hGlobal,
sizeof(RGNDATAHEADER) + (sizeof(RECT) * nMaxParts), GMEM_MOVEABLE );
					pRgnData = (RGNDATA *) ::GlobalLock( hGlobal );
					::memset( LPVOID( LPBYTE(pRgnData) +
sizeof(RGNDATAHEADER) + ( sizeof(RECT) * dwPrevParts ) ), 0, sizeof(RECT) * ( nMaxParts - dwPrevParts ) );
				} // if( pRgnData->rdh.nCount >= nMaxParts )
				LPRECT pRect = (LPRECT)&pRgnData->Buffer;
				::SetRect( &pRect[pRgnData->rdh.nCount], nSavedX, nY, nX, nY + 1 );
				if( nSavedX < pRgnData->rdh.rcBound.left )
					pRgnData->rdh.rcBound.left =
nSavedX;
				if( nY < pRgnData->rdh.rcBound.top )
					pRgnData->rdh.rcBound.top = nY;
				if( nX > pRgnData->rdh.rcBound.right )
					pRgnData->rdh.rcBound.right = nX;
				if( (nY + 1) > pRgnData->rdh.rcBound.bottom
)
					pRgnData->rdh.rcBound.bottom = nY+1;
				pRgnData->rdh.nCount ++;
				if( pRgnData->rdh.nCount == DWORD(
g_PaintManager.m_bIsWinNT4 ? 1 : 2000 ) )
				{
					if( bRTL )
					{
						INT nPart, nLeft, nRight,
nCount = INT( pRgnData->rdh.nCount );
						LPRECT pRect =
(LPRECT)&pRgnData->Buffer;
						for( nPart = 0; nPart <
nCount; nPart ++, pRect ++ )
						{
							nLeft =
_sizeBitmap.cx - pRect->left;
							nRight =
_sizeBitmap.cx - pRect->right;
							pRect->right =
nLeft;
							pRect->left =
nRight;
						} // for( nPart = 0; nPart <
nCount; nPart ++, pRect ++ )
					} // if( bRTL )
					HRGN hRgnPart = ::ExtCreateRegion(
NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * nMaxParts), pRgnData );
					if( hRgnResult != NULL )
					{
						::CombineRgn( hRgnResult,
hRgnResult, hRgnPart, RGN_OR );
						::DeleteObject( hRgnPart );
					} // if( hRgnResult != NULL )
					else
						hRgnResult = hRgnPart;
					pRgnData->rdh.nCount = 0;
					::SetRect( &pRgnData->rdh.rcBound,
MAXLONG, MAXLONG, 0, 0 );
				} // if( pRgnData->rdh.nCount ==  (
g_PaintManager.m_bIsWinNT4 ? 1 : 2000 ) )
			} // if( nX > nSavedX )
		} // for( INT nX = 0; nX < _sizeBitmap.cx; nX++ )
		p32bitColorSurface += nScanLineSize;
	} // for( INT _nY = 0; _nY < _sizeBitmap.cy; _nY++ )
	if( bRTL )
	{
		INT nPart, nLeft, nRight, nCount = INT( pRgnData->rdh.nCount );
		LPRECT pRect = (LPRECT)&pRgnData->Buffer;
		for( nPart = 0; nPart < nCount; nPart ++, pRect ++ )
		{
			nLeft = _sizeBitmap.cx - pRect->left;
			nRight = _sizeBitmap.cx - pRect->right;
			pRect->right = nLeft;
			pRect->left = nRight;
		} // for( nPart = 0; nPart < nCount; nPart ++, pRect ++ )
	} // if( bRTL )
HRGN hRgnPart = ::ExtCreateRegion( NULL, sizeof(RGNDATAHEADER) +
(sizeof(RECT) * nMaxParts), pRgnData );
	if( hRgnResult != NULL )
	{
		::CombineRgn( hRgnResult, hRgnResult, hRgnPart, RGN_OR );
		::DeleteObject( hRgnPart );
	} // if( hRgnResult != NULL )
	else
		hRgnResult = hRgnPart;
	::GlobalFree( hGlobal );
	return hRgnResult;
}

HRGN CExtPaintManager::stat_HBITMAPtoHRGN(
	HBITMAP hBitmap,
	COLORREF clrTransparent,
	COLORREF clrTolerance // = RGB(0,0,0)
	)
{
	if( hBitmap == NULL )
	{
		ASSERT( FALSE );
		return NULL;
	} // if( hBitmap == NULL )
HDC hDstDC = ::CreateCompatibleDC( NULL );
	if( hDstDC == NULL )
	{
		ASSERT( FALSE );
		return NULL;
	} // if( hDstDC == NULL )
BITMAP _bmpInfoSrcBmp;
	::memset( &_bmpInfoSrcBmp, 0, sizeof(BITMAP) );
	::GetObject( hBitmap, sizeof(BITMAP), &_bmpInfoSrcBmp ); BITMAPINFOHEADER _bmpInfoHdr = {
	sizeof(BITMAPINFOHEADER),
	_bmpInfoSrcBmp.bmWidth,
	_bmpInfoSrcBmp.bmHeight,
	1,
	32,
	BI_RGB,
	0,
	0,
	0,
	0,
	0
};
LPVOID p32bitColorSurface = NULL;
HBITMAP hDstDIB = ::CreateDIBSection( hDstDC, (BITMAPINFO *)&_bmpInfoHdr, DIB_RGB_COLORS, &p32bitColorSurface, NULL, 0 );
	if( hDstDIB == NULL )
	{
		ASSERT( FALSE );
		::DeleteDC( hDstDC );
		return NULL;
	} // if( hDstDIB == NULL )
	ASSERT( p32bitColorSurface != NULL );
HBITMAP hOldDst = (HBITMAP) ::SelectObject( hDstDC, hDstDIB ); HDC hSrcDC = ::CreateCompatibleDC( hDstDC );
	if( hSrcDC == NULL )
	{
		ASSERT( FALSE );
		::DeleteObject( ::SelectObject( hDstDC, hOldDst ) );
		::DeleteDC( hDstDC );
		return NULL;
	} // if( hSrcDC == NULL )
BITMAP _bmpInfoDstDIB;
	::memset( &_bmpInfoDstDIB, 0, sizeof(BITMAP) );
	::GetObject( hDstDIB, sizeof(BITMAP), &_bmpInfoDstDIB );
	for( ; (_bmpInfoDstDIB.bmWidthBytes % 4) != 0; _bmpInfoDstDIB.bmWidthBytes ++ ); HBITMAP hOldSrc = (HBITMAP) ::SelectObject( hSrcDC, hBitmap );
	::BitBlt( hDstDC, 0, 0, _bmpInfoSrcBmp.bmWidth, _bmpInfoSrcBmp.bmHeight, hSrcDC, 0, 0, SRCCOPY ); static const DWORD g_nReallocSize = 200; DWORD nMaxParts = g_nReallocSize; HANDLE hGlobal = ::GlobalAlloc( GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (
sizeof(RECT) * nMaxParts ) );
RGNDATA * pRgnData = (RGNDATA *) ::GlobalLock( hGlobal );
	::memset( LPVOID(pRgnData), 0, sizeof(RGNDATAHEADER) + (
sizeof(RECT) * nMaxParts ) );
	pRgnData->rdh.dwSize	= sizeof(RGNDATAHEADER);
	pRgnData->rdh.iType		= RDH_RECTANGLES;
	pRgnData->rdh.nCount	= pRgnData->rdh.nRgnSize = 0;
	::SetRect( &pRgnData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0 );
BYTE nLowRed	= GetRValue( clrTransparent );
BYTE nLowGreen	= GetGValue( clrTransparent );
BYTE nLowBlue	= GetBValue( clrTransparent );
BYTE nHighRed	= BYTE( min( 0xff, ( nLowRed + GetRValue(clrTolerance) ) )
);
BYTE nHighGreen	= BYTE( min( 0xff, ( nLowGreen + GetGValue(clrTolerance) ) )
);
BYTE nHighBlue	= BYTE( min( 0xff, ( nLowBlue + GetBValue(clrTolerance) ) )
);
BYTE * pDstColorSurface = (BYTE *)_bmpInfoDstDIB.bmBits + (_bmpInfoDstDIB.bmHeight - 1) * _bmpInfoDstDIB.bmWidthBytes; HRGN hRgnResult = NULL;
	for( int nY = 0; nY < _bmpInfoSrcBmp.bmHeight; nY++ )
	{
		for( int nX = 0; nX < _bmpInfoSrcBmp.bmWidth; nX++ )
		{
			LPLONG ptrLinePart = (LPLONG)pDstColorSurface + nX;
			int nSavedX = nX;
			for( ; nX < _bmpInfoSrcBmp.bmWidth; ptrLinePart++,
nX++ )
			{
				BYTE nColorPart = GetRValue( (*ptrLinePart) );
				if( nColorPart >= nLowRed && nColorPart <= nHighRed )
				{
					nColorPart = GetGValue(
(*ptrLinePart) );
					if( nColorPart >= nLowGreen &&
nColorPart <= nHighGreen )
					{
						nColorPart = GetBValue(
(*ptrLinePart) );
						if( nColorPart >= nLowBlue
&& nColorPart <= nHighBlue )
							break;
					} // if( nColorPart >= nLowGreen && nColorPart <= nHighGreen )
				} // if( nColorPart >= nLowRed && nColorPart <= nHighRed )
			} // for( ; nX < _bmpInfoSrcBmp.bmWidth;
ptrLinePart++, nX++ )

			if( nX > nSavedX )
			{
				if( pRgnData->rdh.nCount >= nMaxParts )
				{
					::GlobalUnlock( hGlobal );
					DWORD dwPrevParts = nMaxParts;
					nMaxParts += g_nReallocSize;
					hGlobal = ::GlobalReAlloc( hGlobal,
sizeof(RGNDATAHEADER) + (sizeof(RECT) * nMaxParts), GMEM_MOVEABLE );
					pRgnData = (RGNDATA *) ::GlobalLock( hGlobal );
					::memset( LPVOID( LPBYTE(pRgnData) +
sizeof(RGNDATAHEADER) + ( sizeof(RECT) * dwPrevParts ) ), 0, sizeof(RECT) * ( nMaxParts - dwPrevParts ) );
				} // if( pRgnData->rdh.nCount >= nMaxParts )
				LPRECT pRect = (LPRECT)&pRgnData->Buffer;
				::SetRect( &pRect[pRgnData->rdh.nCount], nSavedX, nY, nX, nY + 1 );
				if( nSavedX < pRgnData->rdh.rcBound.left )
					pRgnData->rdh.rcBound.left =
nSavedX;
				if( nY < pRgnData->rdh.rcBound.top )
					pRgnData->rdh.rcBound.top = nY;
				if( nX > pRgnData->rdh.rcBound.right )
					pRgnData->rdh.rcBound.right = nX;
				if( (nY + 1) > pRgnData->rdh.rcBound.bottom
)
					pRgnData->rdh.rcBound.bottom = nY+1;
				pRgnData->rdh.nCount ++;
				if( pRgnData->rdh.nCount == 2000 )
				{
					HRGN hRgnPart = ::ExtCreateRegion(
NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * nMaxParts), pRgnData );
					if( hRgnResult != NULL )
					{
						::CombineRgn( hRgnResult,
hRgnResult, hRgnPart, RGN_OR );
						::DeleteObject( hRgnPart );
					} // if( hRgnResult != NULL )
					else
						hRgnResult = hRgnPart;
					pRgnData->rdh.nCount = 0;
					::SetRect( &pRgnData->rdh.rcBound,
MAXLONG, MAXLONG, 0, 0 );
				} // if( pRgnData->rdh.nCount == 2000 )
			} // if( nX > nSavedX )
		} // for( int nX = 0; nX < _bmpInfoSrcBmp.bmWidth; nX++ )
		pDstColorSurface -= _bmpInfoDstDIB.bmWidthBytes;
	} // for( int nY = 0; nY < _bmpInfoSrcBmp.bmHeight; nY++ ) HRGN hRgnPart =
		::ExtCreateRegion( NULL, sizeof(RGNDATAHEADER) +
(sizeof(RECT) * nMaxParts), pRgnData );
	if( hRgnResult != NULL )
	{
		::CombineRgn( hRgnResult, hRgnResult, hRgnPart, RGN_OR );
		::DeleteObject( hRgnPart );
	} // if( hRgnResult != NULL )
	else
		hRgnResult = hRgnPart;
	::GlobalFree( hGlobal );
	::SelectObject( hSrcDC, hOldSrc );
	::DeleteDC( hSrcDC );
	::DeleteObject( ::SelectObject( hDstDC, hOldDst ) );
	::DeleteDC( hDstDC );
	return hRgnResult;
}