Secondo bug di CDatabase in MFC in Visual Studio 2012

 C Programming >> Programmazione C >  >> Tags >> MFC
Secondo bug di CDatabase in MFC in Visual Studio 2012

Stavo scrivendo di recente di un bug MFC nella classe CDatabase in Visual Studio 2012. Nel frattempo mi sono imbattuto in un bug ancora più grande (controlla questo report su Connect per i dettagli):quando la funzione OpenEx fallisce (credenziali errate, servizio non raggiungibile , la macchina viene spenta, ecc.) danneggia la memoria. Quello che succede dopo è il caso. Non so quando sarà disponibile una correzione, ma fino a quando ciò non accadrà c'è una soluzione alternativa per questo. Proprio come per il bug precedente, devi derivare CDatabase e sovrascrivere il metodo OpenEx, copiando l'implementazione originale dai sorgenti MFC e aggiungendo un'altra riga per annullare il puntatore alla memoria già rilasciata. Quindi, estenderò la mia precedente classe CDatabaseEx alla seguente implementazione:

class CDatabaseEx : public CDatabase  
{  
public:  
   CString GetConnectEx()  
   {  
      CString strConnect = m_strConnect;  
  
      if (strConnect.GetLength() == 0)  
      {  
         DATA_BLOB connectBlob;  
         if (CryptUnprotectData(&m_blobConnect, NULL, NULL, NULL, NULL, 0, &connectBlob))  
         {  
            strConnect = (LPTSTR)connectBlob.pbData;  
            LocalFree(connectBlob.pbData);  
         }  
      }  
  
      return strConnect;  
   }

   virtual BOOL OpenEx(LPCTSTR lpszConnectString, DWORD dwOptions = 0)
   {
     ENSURE_VALID(this);
     ENSURE_ARG(lpszConnectString == NULL || AfxIsValidString(lpszConnectString));
     ENSURE_ARG(!(dwOptions & noOdbcDialog && dwOptions & forceOdbcDialog));

     // Exclusive access not supported.
     ASSERT(!(dwOptions & openExclusive));

     m_bUpdatable = !(dwOptions & openReadOnly);

     TRY
     {
        m_strConnect = lpszConnectString;

        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));
           m_strConnect.Empty();
        }

        // Allocate the HDBC and make connection
        AllocConnect(dwOptions);
        if(!Connect(dwOptions))
        {
           m_blobConnect.pbData = NULL;
           return FALSE;
        }

        // Verify support for required functionality and cache info
        VerifyConnect();
        GetConnectInfo();
     }
     CATCH_ALL(e)
     {
        // HERE IT IS, the workaround (hopefully temporary) for MFC bug with OpenEx corrupting memory
        // http://connect.microsoft.com/VisualStudio/feedback/details/760371/localfree-called-twice-in-cdatabase-mfc-11
        m_blobConnect.pbData = NULL;
        Free();
        THROW_LAST();
     }
     END_CATCH_ALL

     return TRUE;
   }
};