Search code examples
pythonregexescapingwindbgpykd

How to escape an asterisk in a Python related library?


I'm working with PYKD, a library, used for writing Python scripts for Windbg.

One of the functions, typedVar, seems not to work when handling type names who contain an asterisk:

(In a Windbg session):

.load pykd.pyd // Load PYKD library
!py            // enter an interactive Python session

>>> print typedVar('CMap<unsigned long,unsigned long,int,int>', 0x02d729dc).m_nCount
Int4B at 0x2d729e8 Value: 0x4 (4)
=> ok!
>>> print typedVar('CMap<int,int,ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > > >', 0x02ca2568).m_nCount
Int4B at 0x2ca2574 Value: 0x7 (7)
=> ok!

>>> print typedVar('CMap<int,int,void *,void *>', 0x0054ac10).m_nCount
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeException: CMap<int,int,void *,void *> : invalid type name
=> NOK (most probably because of the asterisk)

I believe this is caused by the asterisk, being interpreted as a wildcard, so I'd like to use an escape character, in order to use the asterisk as a "normal" character, but this seems not to be that simple:

Using a backslash:

>>> print typedVar('CMap<int,int,void \*,void \*>', 0x0054ac10).m_nCount
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeException: CMap<int,int,void \*,void \*> : invalid type name

Doubling the asterisk:

>>> print typedVar('CMap<int,int,void **,void **>', 0x0054ac10).m_nCount
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeException: CMap<int,int,void **,void **> : invalid type name

Does anybody know the escape character for regular expressions in Python (in case it's not a backslash or doubling the character)?

Thanks in advance

Oh, before I forget: the mentioned type is present in the application's symbols, as you can see here:

for tp in app.enumTypes("*CMap<*"):
  print tp
...
CMap<int,int,void *,void *>
...

Edit after first comment and reply

These are the commands I used (with the r and the u):

>>> print typedVar(r'CMap<int,int,void *,void *>', 0x0054ac10).m_nCount
>>> print typedVar(u'CMap<int,int,void *,void *>', 0x0054ac10).m_nCount
>>> print typedVar(rr'CMap<int,int,void *,void *>', 0x0054ac10).m_nCount
>>> print typedVar(r'''CMap<int,int,void *,void *>''', 0x0054ac10).m_nCount
>>> print typedVar(r''CMap<int,int,void *,void *>'', 0x0054ac10).m_nCount
>>> print typedVar(ru'CMap<int,int,void *,void *>', 0x0054ac10).m_nCount
>>> print typedVar(ru'CMap<int,int,void *,void *>', 0x0054ac10).m_nCount

Edit after further use of the newest PYKD library

Unfortunately there still is an issue, as you can see from following excerpt:

0:000> .load pykd.pyd
0:000> .chain
Extension DLL search Path:
    ...
Extension DLL chain:
    pykd.pyd: image 0.3.4.2, API 1.0.0, built Sat Nov 17 13:06:54 2018
        [path: C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\winext\pykd.pyd]
    ...
0:000> !py

  >>> dprintln("%d" % typedVar('Application!CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,unsigned int,unsigned int>', 0x064ad440).m_nCount)
  2
  => An asterisk in the type name can sometimes be handled
  >>> dprintln("%d" % typedVar('Application!CMap<unsigned int,unsigned int,_RTL_CRITICAL_SECTION *,_RTL_CRITICAL_SECTION *>', 0x064ad328).m_nCount)
  Traceback (most recent call last):
    File "<console>", line 1, in <module>
  AttributeError: typed var has no field 'm_nCount'
  => But sometimes there still are issues.
     The error message clearly shows that the typename is known.

What might be the issue here? Can I do anything to add more detailed debugging information?

Edit after new proposal from ussrhero

typeInfo seems to be empty:

>>> print(typeInfo('Application!CMap<unsigned int,unsigned int,_RTL_CRITICAL_SECTION *,_RTL_CRITICAL_SECTION *>'))
class/struct : CMap<unsigned int,unsigned int,_RTL_CRITICAL_SECTION *,_RTL_CRITICAL_SECTION *> Size: 0x0 (0)

Here another CMap related typeInfo for reference reasons:

>>> print(typeInfo('Application!CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,unsigned int,unsigned int>'))
class/struct : CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,unsigned int,unsigned int> Size: 0x1c (28)
   +0000 __VFN_table             : VTable*
   =0000000000 classCObject      : CRuntimeClass
   +0004 m_pHashTable            : CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,unsigned int,unsigned int>::CAssoc**
   +0008 m_nHashTableSize        : UInt4B
   +000c m_nCount                : Int4B
   +0010 m_pFreeList             : CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,unsigned int,unsigned int>::CAssoc*
   +0014 m_pBlocks               : CPlex*
   +0018 m_nBlockSize            : Int4B

Here a typeInfo of a non-existing class (also for reference reasons):

>>> print(typeInfo('Application!NonExisting_Class'))
Traceback (most recent call last):
  File "<console>", line 1, in <module>
SymbolException: 'NonExisting_Class' - symbol not found

=> So the class, giving the problem, is known, but can apparently not be handled.

Edit after last update from ussrhero:

dt and dx seem to mention everything is ok for the other CMap:

0:000> dt 0x064ad440 CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,unsigned int,unsigned int>
Application!CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,unsigned int,unsigned int>
   +0x000 __VFN_table : 0x01503444 
   +0x004 m_pHashTable     : 0x06ab9ad0  -> (null) 
   +0x008 m_nHashTableSize : 0x186ab
   +0x00c m_nCount         : 0n2
   +0x010 m_pFreeList      : 0x063c953c CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,unsigned int,unsigned int>::CAssoc
   +0x014 m_pBlocks        : 0x063c9518 CPlex
   +0x018 m_nBlockSize     : 0n10
0:000> dt 0x064ad440 CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,unsigned int,unsigned int> m_nCount
Application!CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,unsigned int,unsigned int>
   +0x00c m_nCount : 0n2
0:000> dx (CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,unsigned int,unsigned int>*) 0x064ad440
(CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,unsigned int,unsigned int>*) 0x064ad440                 : 0x64ad440 [Type: CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,unsigned int,unsigned int> *]
    [+0x004] m_pHashTable     : 0x6ab9ad0 [Type: CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,unsigned int,unsigned int>::CAssoc * *]
    [+0x008] m_nHashTableSize : 0x186ab [Type: unsigned int]
    [+0x00c] m_nCount         : 2 [Type: int]
    [+0x010] m_pFreeList      : 0x63c953c [Type: CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,unsigned int,unsigned int>::CAssoc *]
    [+0x014] m_pBlocks        : 0x63c9518 [Type: CPlex *]
    [+0x018] m_nBlockSize     : 10 [Type: int]

dt and dx seem to mention there is a problem for that particular CMap:

0:000> dt 0x064ad328 CMap<unsigned int,unsigned int,_RTL_CRITICAL_SECTION *,_RTL_CRITICAL_SECTION *>
Application!CMap<unsigned int,unsigned int,_RTL_CRITICAL_SECTION *,_RTL_CRITICAL_SECTION *>
0:000> dt 0x064ad328 CMap<unsigned int,unsigned int,_RTL_CRITICAL_SECTION *,_RTL_CRITICAL_SECTION *> m_nCount
Application!CMap<unsigned int,unsigned int,_RTL_CRITICAL_SECTION *,_RTL_CRITICAL_SECTION *>
0:000> dx (CMap<unsigned int,unsigned int,_RTL_CRITICAL_SECTION *,_RTL_CRITICAL_SECTION *>*) 0x064ad328
Error: Unable to find type 'CMap<unsigned int,unsigned int,_RTL_CRITICAL_SECTION *,_RTL_CRITICAL_SECTION *> *' for cast.

However, the symbols seem not to have a problem:

0:000> x /2 Application!CMap<*vftable*
...
0152e944          Application!CMap<unsigned int,unsigned int,_RTL_CRITICAL_SECTION *,_RTL_CRITICAL_SECTION *>::`vftable'
...
01503444          Application!CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,unsigned int,unsigned int>::`vftable'

Apparently we are dealing here with a Windbg issue. How can we find out if this is a known Windbg issue or a new one? Where are those issues collected? (For your info, I'm working with Windbg 10.0.16299.15 X86 for Windows 10, Version 1803 (OS Build 17134.345), but also Windbg Preview seems to have this bug.


Solution

  • It is a pykd bug: https://githomelab.ru/pykd/pykd/issues/33

    It will be fixed next release