Description
When debugging the following program in LLDB (both 106ae10 and Apple's lldb-1100.0.30.12
):
void foo() {}
struct X {
X() {
static_member;
foo();
}
static inline auto static_member = 0xBEEF;
};
int main() {
X x;
return 0;
}
At DWARFExpression::Evaluate()
in DWARFExpression.cpp (line 943)
:
const uint8_t op = opcodes.GetU8(&offset);
The initial value of the static member from the DWARF (0xBEEF
) is being misinterpreted as opcodes (0xEF
, 0xBE
, 0x00
, 0x00
) and thus the evaluation has unexpected results.
This problem seems to only arise when Variable::m_scope
is eValueTypeVariableGlobal
and Variable::m_static_member
is true
, but I didn't have time to dig deeper and verify this claim.
This issue leads to undefined behavior (as expected), e.g. when stopped into foo()
and static_member
has a value that translates "nicely" to opcodes, LLDB can find static_member
without qualification and incorrectly read some value.
For example (static_member == 50
):
(lldb) b foo
(lldb) r
(lldb) p static_member
(int) $0 = 2
(lldb) p X::static_member
(int) $1 = 50
However (static_member == 0xBEEF
):
(lldb) b foo
(lldb) r
(lldb) p static_member
error: Couldn't materialize: couldn't get the value of variable X::static_member: Stack empty after evaluation.
error: errored out in DoExecute, couldn't PrepareToExecuteJITExpression
(lldb) p/x X::static_member
(int) $1 = 0xbeef
Also, removing any reference to static_member
from the constructor (static_member == 50
):
(lldb) b foo
(lldb) r
(lldb) p static_member
error: <user expression 0>:1:1: use of undeclared identifier 'static_member'
static_member
^
(lldb) p X::static_member
=================================================================
==84957==ERROR: AddressSanitizer: use-after-poison on address 0x621000e84500 at pc 0x0001152b2202 bp 0x7ffee95daa70 sp 0x7ffee95daa68
WRITE of size 8 at 0x621000e84500 thread T0
#0 0x1152b2201 in llvm::itanium_demangle::Node::Node(llvm::itanium_demangle::Node::Kind, llvm::itanium_demangle::Node::Cache, llvm::itanium_demangle::Node::Cache, llvm::itanium_demangle::Node::Cache) ItaniumDemangle.h:146
#1 0x1152bf959 in llvm::itanium_demangle::NameType::NameType(llvm::itanium_demangle::StringView) ItaniumDemangle.h:388
#2 0x1152bf6f1 in llvm::itanium_demangle::NameType::NameType(llvm::itanium_demangle::StringView) ItaniumDemangle.h:388
#3 0x115306503 in llvm::itanium_demangle::NameType* (anonymous namespace)::NodeAllocator::makeNode<llvm::itanium_demangle::NameType, llvm::itanium_demangle::StringView&>(llvm::itanium_demangle::StringView&) CPlusPlusLanguage.cpp:280
#4 0x1152f97c6 in llvm::itanium_demangle::Node* llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::make<llvm::itanium_demangle::NameType, llvm::itanium_demangle::StringView&>(llvm::itanium_demangle::StringView&) ItaniumDemangle.h:2367
#5 0x115327568 in llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::parseSourceName(llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::NameState*) ItaniumDemangle.h:2727
#6 0x1152be8ae in llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::parseUnqualifiedName(llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::NameState*) ItaniumDemangle.h:2614
#7 0x1152b8241 in llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::parseNestedName(llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::NameState*) ItaniumDemangle.h:3185
#8 0x1152acdff in llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::parseName(llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::NameState*) ItaniumDemangle.h:2516
#9 0x1152a8422 in llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::parseEncoding() ItaniumDemangle.h:5097
#10 0x1152a616b in llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::parse() ItaniumDemangle.h:5505
#11 0x1152a3f97 in (anonymous namespace)::ManglingSubstitutor<(anonymous namespace)::TypeSubstitutor>::substituteImpl(llvm::StringRef) CPlusPlusLanguage.cpp:316
#12 0x1152993be in lldb_private::ConstString (anonymous namespace)::ManglingSubstitutor<(anonymous namespace)::TypeSubstitutor>::substitute<char const (&) [2], char const (&) [2]>(llvm::StringRef, char const (&) [2], char const (&) [2]) CPlusPlusLanguage.cpp:302
#13 0x1152980ba in lldb_private::CPlusPlusLanguage::FindAlternateFunctionManglings(lldb_private::ConstString, std::__1::set<lldb_private::ConstString, std::__1::less<lldb_private::ConstString>, std::__1::allocator<lldb_private::ConstString> >&) CPlusPlusLanguage.cpp:430
#14 0x11385998b in lldb_private::IRExecutionUnit::CollectCandidateCPlusPlusNames(std::__1::vector<lldb_private::IRExecutionUnit::SearchSpec, std::__1::allocator<lldb_private::IRExecutionUnit::SearchSpec> >&, std::__1::vector<lldb_private::IRExecutionUnit::SearchSpec, std::__1::allocator<lldb_private::IRExecutionUnit::SearchSpec> > const&, lldb_private::SymbolContext const&) IRExecutionUnit.cpp:730
#15 0x113860dc1 in lldb_private::IRExecutionUnit::FindSymbol(lldb_private::ConstString, bool&) IRExecutionUnit.cpp:956
#16 0x113864b28 in lldb_private::IRExecutionUnit::MemoryManager::GetSymbolAddressAndPresence(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool&) IRExecutionUnit.cpp:1044
#17 0x1138644c6 in lldb_private::IRExecutionUnit::MemoryManager::findSymbol(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) IRExecutionUnit.cpp:1022
#18 0x113865202 in non-virtual thunk to lldb_private::IRExecutionUnit::MemoryManager::findSymbol(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) IRExecutionUnit.cpp
#19 0x118875c3a in llvm::LinkingSymbolResolver::findSymbol(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) MCJIT.cpp:676
#20 0x11888033a in llvm::LegacyJITSymbolResolver::lookup(std::__1::set<llvm::StringRef, std::__1::less<llvm::StringRef>, std::__1::allocator<llvm::StringRef> > const&, llvm::unique_function<void (llvm::Expected<std::__1::map<llvm::StringRef, llvm::JITEvaluatedSymbol, std::__1::less<llvm::StringRef>, std::__1::allocator<std::__1::pair<llvm::StringRef const, llvm::JITEvaluatedSymbol> > > >)>) JITSymbol.cpp:87
#21 0x1188821e0 in llvm::RuntimeDyldImpl::resolveExternalSymbols() RuntimeDyld.cpp:1165
#22 0x118881889 in llvm::RuntimeDyldImpl::resolveRelocations() RuntimeDyld.cpp:131
#23 0x1188736ed in llvm::MCJIT::finalizeObject() MCJIT.cpp:240
#24 0x11384e307 in lldb_private::IRExecutionUnit::ReportAllocations(llvm::ExecutionEngine&) IRExecutionUnit.cpp:1191
#25 0x113846a89 in lldb_private::IRExecutionUnit::GetRunnableInfo(lldb_private::Status&, unsigned long long&, unsigned long long&) IRExecutionUnit.cpp:355
#26 0x118144122 in lldb_private::ClangExpressionParser::PrepareForExecution(unsigned long long&, unsigned long long&, std::__1::shared_ptr<lldb_private::IRExecutionUnit>&, lldb_private::ExecutionContext&, bool&, lldb_private::ExecutionPolicy) ClangExpressionParser.cpp:1337
#27 0x118287aa9 in lldb_private::ClangUserExpression::Parse(lldb_private::DiagnosticManager&, lldb_private::ExecutionContext&, lldb_private::ExecutionPolicy, bool, bool) ClangUserExpression.cpp:639
#28 0x11397394f in lldb_private::UserExpression::Evaluate(lldb_private::ExecutionContext&, lldb_private::EvaluateExpressionOptions const&, llvm::StringRef, llvm::StringRef, std::__1::shared_ptr<lldb_private::ValueObject>&, lldb_private::Status&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*, lldb_private::ValueObject*) UserExpression.cpp:251
#29 0x114781719 in lldb_private::Target::EvaluateExpression(llvm::StringRef, lldb_private::ExecutionContextScope*, std::__1::shared_ptr<lldb_private::ValueObject>&, lldb_private::EvaluateExpressionOptions const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*, lldb_private::ValueObject*) Target.cpp:2369
#30 0x117898e81 in lldb_private::CommandObjectExpression::EvaluateExpression(llvm::StringRef, lldb_private::Stream*, lldb_private::Stream*, lldb_private::CommandReturnObject*) CommandObjectExpression.cpp:419
#31 0x11789dc37 in lldb_private::CommandObjectExpression::DoExecute(llvm::StringRef, lldb_private::CommandReturnObject&) CommandObjectExpression.cpp:649
#32 0x113cec858 in lldb_private::CommandObjectRaw::Execute(char const*, lldb_private::CommandReturnObject&) CommandObject.cpp:1012
#33 0x113c343d6 in lldb_private::CommandInterpreter::HandleCommand(char const*, lldb_private::LazyBool, lldb_private::CommandReturnObject&, lldb_private::ExecutionContext*, bool, bool) CommandInterpreter.cpp:1915
#34 0x113c4939e in lldb_private::CommandInterpreter::IOHandlerInputComplete(lldb_private::IOHandler&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) CommandInterpreter.cpp:2913
#35 0x11320c7eb in lldb_private::IOHandlerEditline::Run() IOHandler.cpp:549
#36 0x11306af0b in lldb_private::Debugger::RunIOHandlers() Debugger.cpp:903
#37 0x113c4e5c1 in lldb_private::CommandInterpreter::RunCommandInterpreter(bool, bool, lldb_private::CommandInterpreterRunOptions&) CommandInterpreter.cpp:3099
#38 0x111a2496a in lldb::SBDebugger::RunCommandInterpreter(bool, bool) SBDebugger.cpp:1169
#39 0x106629f9e in Driver::MainLoop() Driver.cpp:675
#40 0x10662ee9b in main Driver.cpp:898
#41 0x7fff6640b7fc in start (libdyld.dylib:x86_64+0x1a7fc)
0x621000e84500 is located 0 bytes inside of 4096-byte region [0x621000e84500,0x621000e85500)
allocated by thread T0 here:
#0 0x1067b4793 in wrap_malloc (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x61793)
#1 0x117122071 in llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul, 128ul>::StartNewSlab() MemAlloc.h:26
#2 0x117121fdc in llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul, 128ul>::Allocate(unsigned long, llvm::Align) Allocator.h:188
#3 0x114c67381 in llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 4096ul, 4096ul, 128ul>::Allocate(unsigned long, unsigned long) Allocator.h:202
#4 0x1153063ed in llvm::itanium_demangle::NameType* (anonymous namespace)::NodeAllocator::makeNode<llvm::itanium_demangle::NameType, llvm::itanium_demangle::StringView&>(llvm::itanium_demangle::StringView&) CPlusPlusLanguage.cpp:279
#5 0x1152f97c6 in llvm::itanium_demangle::Node* llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::make<llvm::itanium_demangle::NameType, llvm::itanium_demangle::StringView&>(llvm::itanium_demangle::StringView&) ItaniumDemangle.h:2367
#6 0x115327568 in llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::parseSourceName(llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::NameState*) ItaniumDemangle.h:2727
#7 0x1152be8ae in llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::parseUnqualifiedName(llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::NameState*) ItaniumDemangle.h:2614
#8 0x1152b8241 in llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::parseNestedName(llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::NameState*) ItaniumDemangle.h:3185
#9 0x1152acdff in llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::parseName(llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::NameState*) ItaniumDemangle.h:2516
#10 0x1152a8422 in llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::parseEncoding() ItaniumDemangle.h:5097
#11 0x1152a616b in llvm::itanium_demangle::AbstractManglingParser<(anonymous namespace)::TypeSubstitutor, (anonymous namespace)::NodeAllocator>::parse() ItaniumDemangle.h:5505
#12 0x1152a3f97 in (anonymous namespace)::ManglingSubstitutor<(anonymous namespace)::TypeSubstitutor>::substituteImpl(llvm::StringRef) CPlusPlusLanguage.cpp:316
#13 0x1152993be in lldb_private::ConstString (anonymous namespace)::ManglingSubstitutor<(anonymous namespace)::TypeSubstitutor>::substitute<char const (&) [2], char const (&) [2]>(llvm::StringRef, char const (&) [2], char const (&) [2]) CPlusPlusLanguage.cpp:302
#14 0x115297dec in lldb_private::CPlusPlusLanguage::FindAlternateFunctionManglings(lldb_private::ConstString, std::__1::set<lldb_private::ConstString, std::__1::less<lldb_private::ConstString>, std::__1::allocator<lldb_private::ConstString> >&) CPlusPlusLanguage.cpp:425
#15 0x11385998b in lldb_private::IRExecutionUnit::CollectCandidateCPlusPlusNames(std::__1::vector<lldb_private::IRExecutionUnit::SearchSpec, std::__1::allocator<lldb_private::IRExecutionUnit::SearchSpec> >&, std::__1::vector<lldb_private::IRExecutionUnit::SearchSpec, std::__1::allocator<lldb_private::IRExecutionUnit::SearchSpec> > const&, lldb_private::SymbolContext const&) IRExecutionUnit.cpp:730
#16 0x113860dc1 in lldb_private::IRExecutionUnit::FindSymbol(lldb_private::ConstString, bool&) IRExecutionUnit.cpp:956
#17 0x113864b28 in lldb_private::IRExecutionUnit::MemoryManager::GetSymbolAddressAndPresence(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool&) IRExecutionUnit.cpp:1044
#18 0x1138644c6 in lldb_private::IRExecutionUnit::MemoryManager::findSymbol(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) IRExecutionUnit.cpp:1022
#19 0x113865202 in non-virtual thunk to lldb_private::IRExecutionUnit::MemoryManager::findSymbol(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) IRExecutionUnit.cpp
#20 0x118875c3a in llvm::LinkingSymbolResolver::findSymbol(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) MCJIT.cpp:676
#21 0x11888033a in llvm::LegacyJITSymbolResolver::lookup(std::__1::set<llvm::StringRef, std::__1::less<llvm::StringRef>, std::__1::allocator<llvm::StringRef> > const&, llvm::unique_function<void (llvm::Expected<std::__1::map<llvm::StringRef, llvm::JITEvaluatedSymbol, std::__1::less<llvm::StringRef>, std::__1::allocator<std::__1::pair<llvm::StringRef const, llvm::JITEvaluatedSymbol> > > >)>) JITSymbol.cpp:87
#22 0x1188821e0 in llvm::RuntimeDyldImpl::resolveExternalSymbols() RuntimeDyld.cpp:1165
#23 0x118881889 in llvm::RuntimeDyldImpl::resolveRelocations() RuntimeDyld.cpp:131
#24 0x1188736ed in llvm::MCJIT::finalizeObject() MCJIT.cpp:240
#25 0x11384e307 in lldb_private::IRExecutionUnit::ReportAllocations(llvm::ExecutionEngine&) IRExecutionUnit.cpp:1191
#26 0x113846a89 in lldb_private::IRExecutionUnit::GetRunnableInfo(lldb_private::Status&, unsigned long long&, unsigned long long&) IRExecutionUnit.cpp:355
#27 0x118144122 in lldb_private::ClangExpressionParser::PrepareForExecution(unsigned long long&, unsigned long long&, std::__1::shared_ptr<lldb_private::IRExecutionUnit>&, lldb_private::ExecutionContext&, bool&, lldb_private::ExecutionPolicy) ClangExpressionParser.cpp:1337
#28 0x118287aa9 in lldb_private::ClangUserExpression::Parse(lldb_private::DiagnosticManager&, lldb_private::ExecutionContext&, lldb_private::ExecutionPolicy, bool, bool) ClangUserExpression.cpp:639
#29 0x11397394f in lldb_private::UserExpression::Evaluate(lldb_private::ExecutionContext&, lldb_private::EvaluateExpressionOptions const&, llvm::StringRef, llvm::StringRef, std::__1::shared_ptr<lldb_private::ValueObject>&, lldb_private::Status&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*, lldb_private::ValueObject*) UserExpression.cpp:251
SUMMARY: AddressSanitizer: use-after-poison ItaniumDemangle.h:146 in llvm::itanium_demangle::Node::Node(llvm::itanium_demangle::Node::Kind, llvm::itanium_demangle::Node::Cache, llvm::itanium_demangle::Node::Cache, llvm::itanium_demangle::Node::Cache)
Shadow bytes around the buggy address:
0x1c42001d0850: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x1c42001d0860: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c42001d0870: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c42001d0880: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c42001d0890: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x1c42001d08a0:[f7]f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
0x1c42001d08b0: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
0x1c42001d08c0: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
0x1c42001d08d0: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
0x1c42001d08e0: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
0x1c42001d08f0: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==84957==ABORTING
Backtrace:
#0 DWARFExpression::Evaluate(ExecutionContext*, RegisterContext*, std::__1::shared_ptr<Module>, DataExtractor const&, DWARFUnit const*, lldb::RegisterKind, Value const*, Value const*, Value&, Status*)
#1 DWARFExpression::Evaluate(ExecutionContext*, RegisterContext*, unsigned long long, Value const*, Value const*, Value&, Status*) const
#2 ValueObjectVariable::UpdateValue()
#3 ValueObject::UpdateValueIfNeeded(bool)
#4 ValueObject::GetData(DataExtractor&, Status&)
DWARF entry for static_member
:
0x00000046: DW_TAG_member
DW_AT_name ("static_member")
DW_AT_type (0x0000000000000060 "int")
DW_AT_decl_file ("<redacted>/static_member.cpp")
DW_AT_decl_line (8)
DW_AT_external (true)
DW_AT_declaration (true)
DW_AT_const_value (48879) // 0xBEEF