Second CDatabase bug in MFC in Visual Studio 2012

I was writing recently about an MFC bug in CDatabase class in Visual Studio 2012. In the meanwhile I have stumbled upon an even greater bug (check this report on Connect for the details): when the OpenEx function fails (wrong credentials, service not reachable, machine is shot down etc.) it corrupts memory. What happen next is chance. I don’t know when a fix will be available, but until that happens there is a workaround for this. Just like for the previous bug, you have to derive CDatabase and override OpenEx method, copying the original implementation from the MFC sources and adding one more line to null the pointer to already released memory. So, I’ll extend my previous CDatabaseEx class to the following implementation:

4 Replies to “Second CDatabase bug in MFC in Visual Studio 2012”

  1. You need to modify the code as follows as well at line 47/48:

    if(!Connect(dwOptions)) {
    m_blobConnect.pbData = NULL;
    return FALSE;

    Otherwise, a failure to connect for reasons other than an exception being caught will also null out the data.

  2. If you call OpenEx() with lpszConnectString pointing to an empty string,
    the MFC will open a dialog to let the user choose a new connection.

    If that dialog is closed with “Abort” then there will still be a memory

    I got around this bug with this check:

    if( m_strConnect.GetLength() > 0 ) // yet another workaround…
    DATA_BLOB connectBlob;
    connectBlob.pbData = (BYTE *)(LPCTSTR)m_strConnect;
    connectBlob.cbData = (DWORD)(AtlStrLen(m_strConnect) + 1) * sizeof(TCHAR);
    if (CryptProtectData(&connectBlob, NULL, NULL, NULL, NULL, 0, &m_blobConnect))
    SecureZeroMemory((BYTE *)(LPCTSTR)m_strConnect, m_strConnect.GetLength() * sizeof(TCHAR));


  3. Unfortunately, if the connection string is not empty but incomplete, the above fix doesn’t work; if the user cancels the source selection dialog double free still occurs. To fix this, we must duplicate the original CDatabase::Connect() function, adding the following fix:
    if (m_strConnect.GetLength() == 0)
    DATA_BLOB connectBlob;
    if (CryptUnprotectData(&m_blobConnect, NULL, NULL, NULL, NULL, 0, &connectBlob))
    m_strConnect = (LPTSTR)connectBlob.pbData;
    m_blobConnect.pbData = NULL; // This is the fix

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.