Crash Dump Analysis Patterns (Part 6a)
This is a specialization of Invalid Pointer pattern called NULL Pointer and it is the most easily recognized pattern with a straightforward fix most of the time according to my experience. Checking the pointer value to be non-NULL might not work if the pointer value is random (Wild Pointer pattern) but at least it eliminates this class of problems. NULL pointers can be NULL data pointers or NULL code pointers. The latter happens when we have a pointer to some function and we try to call it. Consider this example:
0:002> r
eax=00000000 ebx=00000000 ecx=93630000 edx=00000000 esi=00000000 edi=00000000
eip=00000000 esp=0222ffbc ebp=0222ffec iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246
00000000 ?? ???
0:002> kv
ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
0222ffb8 7d4dfe21 00000000 00000000 00000000 0×0
0222ffec 00000000 00000000 00000000 00000000 kernel32!BaseThreadStart+0×34
Clearly we have a NULL code pointer here and if we disassemble backwards the return address 7d4dfe21 or BaseThreadStart+0×34 we would suspect that BaseThreadStart function tried to call a thread start procedure:
0:002> ub 7d4dfe21
kernel32!BaseThreadStart+0x10:
7d4dfdfd mov eax,dword ptr fs:[00000018h]
7d4dfe03 cmp dword ptr [eax+10h],1E00h
7d4dfe0a jne kernel32!BaseThreadStart+0x2e (7d4dfe1b)
7d4dfe0c cmp byte ptr [kernel32!BaseRunningInServerProcess (7d560008)],0
7d4dfe13 jne kernel32!BaseThreadStart+0x2e (7d4dfe1b)
7d4dfe15 call dword ptr [kernel32!_imp__CsrNewThread (7d4d0310)]
7d4dfe1b push dword ptr [ebp+0Ch]
7d4dfe1e call dword ptr [ebp+8]
0:002> dp ebp+8 l1
0222fff4 00000000
To confirm this suspicion we can write a code that calls CreateThread function similar to this one:
typedef DWORD (WINAPI *THREADPROC)(PVOID);
DWORD WINAPI ThreadProc(PVOID pvParam)
{
// Does some work
return 0;
}
void foo()
{
//..
THREADPROC thProc = ThreadProc;
//..
// thProc becomes NULL because of a bug
//..
HANDLE Thread = CreateThread(NULL, 0, thProc, 0, 0, NULL);
CloseHandle(hThread);
}
- Dmitry Vostokov @ DumpAnalysis.org -
February 4th, 2009 at 6:11 pm
[…] 2009 (0×7D9) - The Year of Debugging 2010 (0×7DA) - The Year of Dump Analysis It was reported that after an upgrade to the new version of a productivity software package one unrelated GUI application started to crash frequently. One crash dump was collected and the following stack trace pointed to a NULL code pointer: […]
April 14th, 2009 at 6:51 pm
[…] Analysis NULL Data Pointer is a special version of the more general Invalid Pointer pattern like NULL Code Pointer. The effective address is below 0xFFFF and it is usually a register with 0 value and the small […]
May 13th, 2009 at 2:50 pm
[…] looking at a stack trace of one crashed process we noticed an invalid code pointer. It is not a NULL code pointer but has the same stack trace […]
July 6th, 2009 at 4:57 pm
[…] resulted effective address is a NULL code pointer (EAX=3, major code and ESI is […]
March 22nd, 2010 at 8:54 pm
[…] Today we introduce an icon for NULL Pointer (code) pattern: […]
October 20th, 2018 at 5:38 pm
Some runtime implementations replace NULL code pointers with some default functions which provide additional diagnostics, for example, in the case of C++ pure virtual call:
0:008> kc
#
00 ucrtbase!abort
01 VCRUNTIME140!_purecall
WARNING: Stack unwind information not available. Following frames may be wrong.
02 ClientTelemetry!Microsoft::Applications::Telemetry::LogManager::checkup
03 ClientTelemetry!Microsoft::Applications::Telemetry::EventProperty::type_name
04 ClientTelemetry!Microsoft::Applications::Telemetry::EventProperty::type_name
05 ClientTelemetry!Microsoft::Applications::Telemetry::EventProperty::type_name
06 ClientTelemetry!Microsoft::Applications::Telemetry::EventProperty::type_name
07 wininet!InternetIndicateStatus
08 wininet!CFsm::RunWorkItem
09 wininet!CSocket::ReceiveCompletion
0a wininet!CWxSocket::IoCompletionCallback
0b KERNELBASE!BasepTpIoCallback
0c ntdll!TppIopExecuteCallback
0d ntdll!TppWorkerThread
0e kernel32!BaseThreadInitThunk
0f ntdll!__RtlUserThreadStart
10 ntdll!_RtlUserThreadStart