]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/debughlp.cpp
[ 1509599 ] 'Split pickers page in widgets sample' with more icons and rebaking.
[wxWidgets.git] / src / msw / debughlp.cpp
index 6e91403895ce18f2e80d0da6624b7a03e0de0b1b..726900c638933d227f54e2c189aed9517d5dfb15 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
@@ -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;
     }
@@ -305,46 +313,53 @@ wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
             break;
 
         case SYMBOL_TAG_DATA:
-            wxDbgHelpDLL::DataKind kind;
-            if ( !DoGetTypeInfo(pSym, TI_GET_DATAKIND, &kind) ||
-                    kind != DATA_MEMBER )
+            if ( !pVariable )
             {
-                // maybe it's a static member? we're not interested in them...
-                break;
+                s = _T("NULL");
             }
+            else // valid location
+            {
+                wxDbgHelpDLL::DataKind kind;
+                if ( !DoGetTypeInfo(pSym, TI_GET_DATAKIND, &kind) ||
+                        kind != DATA_MEMBER )
+                {
+                    // maybe it's a static member? we're not interested in them...
+                    break;
+                }
 
-            // get the offset of the child member, relative to its parent
-            DWORD ofs = 0;
-            if ( !DoGetTypeInfo(pSym, TI_GET_OFFSET, &ofs) )
-                break;
+                // get the offset of the child member, relative to its parent
+                DWORD ofs = 0;
+                if ( !DoGetTypeInfo(pSym, TI_GET_OFFSET, &ofs) )
+                    break;
 
-            pVariable = (void *)((DWORD_PTR)pVariable + ofs);
+                pVariable = (void *)((DWORD_PTR)pVariable + ofs);
 
 
-            // now pass to the type representing the type of this member
-            SYMBOL_INFO sym = *pSym;
-            if ( !DoGetTypeInfo(pSym, TI_GET_TYPEID, &sym.TypeIndex) )
-                break;
+                // now pass to the type representing the type of this member
+                SYMBOL_INFO sym = *pSym;
+                if ( !DoGetTypeInfo(pSym, TI_GET_TYPEID, &sym.TypeIndex) )
+                    break;
 
-            ULONG64 size;
-            DoGetTypeInfo(&sym, TI_GET_LENGTH, &size);
+                ULONG64 size;
+                DoGetTypeInfo(&sym, TI_GET_LENGTH, &size);
 
-            switch ( DereferenceSymbol(&sym, &pVariable) )
-            {
-                case SYMBOL_TAG_BASE_TYPE:
-                    {
-                        BasicType bt = GetBasicType(&sym);
-                        if ( bt )
+                switch ( DereferenceSymbol(&sym, &pVariable) )
+                {
+                    case SYMBOL_TAG_BASE_TYPE:
                         {
-                            s = DumpBaseType(bt, size, pVariable);
+                            BasicType bt = GetBasicType(&sym);
+                            if ( bt )
+                            {
+                                s = DumpBaseType(bt, size, pVariable);
+                            }
                         }
-                    }
-                    break;
+                        break;
 
-                case SYMBOL_TAG_UDT:
-                case SYMBOL_TAG_BASE_CLASS:
-                    s = DumpUDT(&sym, pVariable, level);
-                    break;
+                    case SYMBOL_TAG_UDT:
+                    case SYMBOL_TAG_BASE_CLASS:
+                        s = DumpUDT(&sym, pVariable, level);
+                        break;
+                }
             }
 
             if ( !s.empty() )
@@ -366,6 +381,13 @@ 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);
 
@@ -376,7 +398,25 @@ wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level)
     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
@@ -458,7 +498,16 @@ wxDbgHelpDLL::DereferenceSymbol(PSYMBOL_INFO pSym, void **ppData)
         // remove one level of indirection except for the char strings: we want
         // to dump "char *" and not a single "char" for them
         if ( ppData && *ppData && GetBasicType(pSym) != BASICTYPE_CHAR )
-            *ppData = (void *)*((DWORD_PTR *)*ppData);
+        {
+            DWORD_PTR *pData = (DWORD_PTR *)*ppData;
+
+            if ( ::IsBadReadPtr(pData, sizeof(DWORD_PTR *)) )
+            {
+                break;
+            }
+
+            *ppData = (void *)*pData;
+        }
     }
 
     return tag;
@@ -493,7 +542,9 @@ wxDbgHelpDLL::DumpSymbol(PSYMBOL_INFO pSym, void *pVariable)
 // debugging helpers
 // ----------------------------------------------------------------------------
 
-#ifndef NDEBUG
+// this code is very useful when debugging debughlp.dll-related code but
+// probably not worth having compiled in normally, please do not remove it!
+#if 0 // ndef NDEBUG
 
 static wxString TagString(wxDbgHelpDLL::SymbolTag tag)
 {
@@ -670,7 +721,7 @@ extern "C" void DumpTI(ULONG ti)
     }
 
     OutputDebugString(wxString::Format(_T("tag=%s%s"),
-                      nested ? _T("nested ") : _T(""),
+                      nested ? _T("nested ") : wxEmptyString,
                       TagString(tag).c_str()));
     if ( tag == wxDbgHelpDLL::SYMBOL_TAG_UDT )
     {
@@ -708,7 +759,7 @@ extern "C" void DumpTI(ULONG ti)
         OutputDebugString(wxString::Format(_T(", next ti=0x%x"), ti));
     }
 
-    OutputDebugString("\r\n");
+    OutputDebugString(_T("\r\n"));
 }
 
 #endif // NDEBUG