]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/debughlp.cpp
fix crash which happened if you called SetAttr(NULL) followed by SetAttr(attr) (...
[wxWidgets.git] / src / msw / debughlp.cpp
index 5f5e75037e6f59cb5422aae989f6f1254981a35a..d2ddec0146f5154cddce7f12bc3d14a6a9361730 100644 (file)
 
 #include "wx/msw/debughlp.h"
 
-#if wxUSE_DBGHELP
+#if wxUSE_DBGHELP && wxUSE_DYNLIB_CLASS
+
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
+
+// to prevent recursion which could result from corrupted data we limit
+// ourselves to that many levels of embedded fields inside structs
+static const unsigned MAX_DUMP_DEPTH = 20;
 
 // ----------------------------------------------------------------------------
 // globals
@@ -137,7 +145,7 @@ const wxString& wxDbgHelpDLL::GetErrorMessage()
 void wxDbgHelpDLL::LogError(const wxChar *func)
 {
     ::OutputDebugString(wxString::Format(_T("dbghelp: %s() failed: %s\r\n"),
-                        func, wxSysErrorMsg(::GetLastError())));
+                        func, wxSysErrorMsg(::GetLastError())).wx_str());
 }
 
 // ----------------------------------------------------------------------------
@@ -286,7 +294,7 @@ wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
     wxString s;
 
     // avoid infinite recursion
-    if ( level > 100 )
+    if ( level > MAX_DUMP_DEPTH )
     {
         return s;
     }
@@ -373,20 +381,45 @@ wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
 wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
 {
     wxString s;
+
+    // we have to limit the depth of UDT dumping as otherwise we get in
+    // infinite loops trying to dump linked lists... 10 levels seems quite
+    // reasonable, full information is in minidump file anyhow
+    if ( level > 10 )
+        return s;
+
     s.reserve(512);
     s = GetSymbolName(pSym);
 
-#if !wxUSE_STL
+#if !wxUSE_STD_STRING
     // special handling for ubiquitous wxString: although the code below works
     // for it as well, it shows the wxStringBase class and takes 4 lines
     // instead of only one as this branch
     if ( s == _T("wxString") )
     {
         wxString *ps = (wxString *)pVariable;
-        s << _T("(\"") << *ps << _T(")\"");
+
+        // we can't just dump wxString directly as it could be corrupted or
+        // invalid and it could also be locked for writing (i.e. if we're
+        // between GetWriteBuf() and UngetWriteBuf() calls) and assert when we
+        // try to access it contents using public methods, so instead use our
+        // knowledge of its internals
+        const wxChar *p = NULL;
+        if ( !::IsBadReadPtr(ps, sizeof(wxString)) )
+        {
+            p = ps->data();
+            wxStringData *data = (wxStringData *)p - 1;
+            if ( ::IsBadReadPtr(data, sizeof(wxStringData)) ||
+                    ::IsBadReadPtr(p, sizeof(wxChar *)*data->nAllocLength) )
+            {
+                p = NULL; // don't touch this pointer with 10 feet pole
+            }
+        }
+
+        s << _T("(\"") << (p ? p : _T("???")) << _T(")\"");
     }
     else // any other UDT
-#endif // !wxUSE_STL
+#endif // !wxUSE_STD_STRING
     {
         // Determine how many children this type has.
         DWORD dwChildrenCount = 0;