llnode icon indicating copy to clipboard operation
llnode copied to clipboard

basic_string out_of_range while parsing node crash

Open stevenschlansker opened this issue 7 years ago • 3 comments

We had a node crash, and while attempting to analyze its core file with llnode 1.7.1 lldb 360.1.70:

libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: basic_string
zsh: abort      lldb node -c ./core.node.7.1531852031
Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000

Application Specific Information:
HandleCommand(command = "v8 findjsobjects")
abort() called
terminating with uncaught exception of type std::out_of_range: basic_string

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	0x00007fffa0771f06 __pthread_kill + 10
1   libsystem_pthread.dylib       	0x00007fff926874ec pthread_kill + 90
2   libsystem_c.dylib             	0x00007fff992486df abort + 129
3   libc++abi.dylib               	0x00007fffa0d7eb31 abort_message + 257
4   libc++abi.dylib               	0x00007fffa0da4def default_terminate_handler() + 243
5   libobjc.A.dylib               	0x00007fff9d4de4a6 _objc_terminate() + 124
6   libc++abi.dylib               	0x00007fffa0da1ffe std::__terminate(void (*)()) + 8
7   libc++abi.dylib               	0x00007fffa0da1a6a __cxa_throw + 121
8   libc++.1.dylib                	0x00007fff94c200c1 std::__1::__basic_string_common<true>::__throw_out_of_range() const + 71
9   libc++.1.dylib                	0x00007fff94c2056c std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long, unsigned long, std::__1::allocator<char> const&) + 68
10  llnode.dylib                  	0x0000000110c8c9c4 llnode::v8::SlicedString::ToString(llnode::v8::Error&) + 628
11  llnode.dylib                  	0x0000000110c876ab llnode::v8::String::ToString(llnode::v8::Error&) + 559
12  llnode.dylib                  	0x0000000110c8a81c llnode::v8::HeapObject::ToString(llnode::v8::Error&) + 208
13  llnode.dylib                  	0x0000000110c89105 llnode::v8::Value::ToString(llnode::v8::Error&) + 243
14  llnode.dylib                  	0x0000000110c9a8c7 llnode::FindJSObjectsVisitor::MapCacheEntry::Load(llnode::v8::Map, llnode::v8::HeapObject, llnode::v8::LLV8*, llnode::v8::Error&) + 1025
15  llnode.dylib                  	0x0000000110c9a2a9 llnode::FindJSObjectsVisitor::Visit(unsigned long long, unsigned long long) + 651
16  llnode.dylib                  	0x0000000110c9b86c llnode::LLScan::ScanMemoryRanges(llnode::FindJSObjectsVisitor&) + 282
17  llnode.dylib                  	0x0000000110c9570c llnode::LLScan::ScanHeapForObjects(lldb::SBTarget, lldb::SBCommandReturnObject&) + 352
18  llnode.dylib                  	0x0000000110c95512 llnode::FindObjectsCmd::DoExecute(lldb::SBDebugger, char**, lldb::SBCommandReturnObject&) + 138
19  com.apple.LLDB.framework      	0x000000010caeab37 CommandPluginInterfaceImplementation::DoExecute(lldb_private::Args&, lldb_private::CommandReturnObject&) + 183
20  com.apple.LLDB.framework      	0x000000010efe3c4b lldb_private::CommandObjectParsed::Execute(char const*, lldb_private::CommandReturnObject&) + 407
21  com.apple.LLDB.framework      	0x000000010efd8c0c lldb_private::CommandInterpreter::HandleCommand(char const*, lldb_private::LazyBool, lldb_private::CommandReturnObject&, lldb_private::ExecutionContext*, bool, bool) + 2314
22  com.apple.LLDB.framework      	0x000000010efdb55a lldb_private::CommandInterpreter::IOHandlerInputComplete(lldb_private::IOHandler&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) + 206
23  com.apple.LLDB.framework      	0x000000010eff517f lldb_private::IOHandlerEditline::Run() + 283
24  com.apple.LLDB.framework      	0x000000010eee3d89 lldb_private::Debugger::ExecuteIOHandlers() + 63
25  com.apple.LLDB.framework      	0x000000010efdbe65 lldb_private::CommandInterpreter::RunCommandInterpreter(bool, bool, lldb_private::CommandInterpreterRunOptions&) + 117
26  com.apple.LLDB.framework      	0x000000010cae6c86 lldb::SBDebugger::RunCommandInterpreter(bool, bool) + 68
27  lldb                          	0x000000010cab6e44 Driver::MainLoop() + 2228
28  lldb                          	0x000000010cab73b1 main + 268
29  libdyld.dylib                 	0x00007fff9f3105ad start + 1

The failure is 100% reproducible with the core file I have (2.1GB, though, so I can't easily share it)

stevenschlansker avatar Jul 17 '18 21:07 stevenschlansker

Looks like an incorrect parsing of a sliced string, what's the version of Node.js that produced the core dump?

It probably won't be actionable if we cannot reproduce the string that results in the crash.

joyeecheung avatar Jul 18 '18 00:07 joyeecheung

core is from node 8.9.3

I totally understand llnode may not be able to parse out all strings -- the process crashed, it's quite possible some of the heap is corrupt. But seeing as this is a debugging utility maybe it can be more robust -- print out a warning that the string could not be rendered and replace it with invalid string #1 length 123405 for example, instead of allowing an uncaught exception to terminate lldb.

stevenschlansker avatar Jul 19 '18 17:07 stevenschlansker

@stevenschlansker

But seeing as this is a debugging utility maybe it can be more robust -- print out a warning that the string could not be rendered and replace it with invalid string #1 length 123405 for example, instead of allowing an uncaught exception to terminate lldb.

I agree, this is more of an oversight in the code base (we don't usually do enough checks in the inspectors and just assume the values are legit). I opened https://github.com/nodejs/llnode/pull/217

joyeecheung avatar Jul 20 '18 07:07 joyeecheung