Search code examples
c++mfcdumppykd

how to recognise "wrong" pointers


I'm working with heap_stat, a script, based on PYKD library (the script performs Ptrptr() on !heap -h 0 results and continues from there).

This heap_stat script sometimes contains wrong results, as you can see from following excerpt:

heap_stat source code:

if (type_name.endswith("CStringArray") or
    ... :
    if type_name.endswith("CStringArray"):
        collection_Size = typedVar('CStringArray', ptr).m_nSize
    elif 
    ...
    try:
        dprintln(("0x" + pointer_format + "\t%s\t Size:[%d]") % (ptr, type_name, collection_Size))

Results excerpts:

...
0x000002660b40d890      mfc140u!CStringArray     Size:[9],
...
0x000002660ae8c6d0      mfc140u!CStringArray     Size:[8589934592]
...

Verifying this in Visual Studio yields following results:

-    (CStringArray*)0x000002660b40d890    0x000002660b40d890 {size = 9, pointer : 0x000002660b40d890}
    [size]      9    __int64
    [capacity]  9    __int64
    [grow by]   0    __int64
+    [0]    L""    mfc140u.dll!ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >
+    [1]    L""    mfc140u.dll!ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >
+    [2]    L""    mfc140u.dll!ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >
+    [3]    L""    mfc140u.dll!ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >
+    [4]    L""    mfc140u.dll!ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >
+    [5]    L""    mfc140u.dll!ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >
+    [6]    L""    mfc140u.dll!ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >
+    [7]    L""    mfc140u.dll!ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >
+    [8]    L""    mfc140u.dll!ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >

=> Correct

-    (CStringArray*)0x000002660ae8c6d0    0x000002660ae8c6d0 {size = 8589934592, pointer : 0x000002660ae8c6d0}
    [size]      8589934592    __int64
    [capacity]  8589934594    __int64
    [grow by]   8589934594    __int64
+    [Raw View]    0x000002660ae8c6d0 {m_pData=0x88000000bb1d05ba ??? m_nSize=8589934592 m_nMaxSize=8589934594 ...}

=> Wrong: this seems to be a leftover of an object which is not valid anymore.

My question: is there any feature in PYKD to filter out those wrong objects? Is there even a way to recognise those while debugging in Visual Studio? And not to forget: what are those leftovers? I don't think there's much delete array_with_strings where array_with_strings is a CStringArray in my source code.


Solution

  • In response to IInspectable's comment: that was a real coincidence, having exactly that number. But it put me thinking: are there any limitations to that number, and in fact, it's very simple:

    The size of a CStringArray (or any other MFC collection for that matter) is an int, which means that it is bounded by INT_MAX (being 2^21-1).

    So, I've adapted my heap_stat script, filtering out all MFC objects, having a size, larger than 2^21-1.