https://github.com/Nerixyz created https://github.com/llvm/llvm-project/pull/215847
When running the `lldb/test/Shell/Expr/TestIRMemoryMapWindows.test` on my machine, I saw an assertion failure when walking an `LF_FIELDLIST`. Specifically this assertion: https://github.com/llvm/llvm-project/blob/8fda9eee8956d4ac5a393689ccbde16a0d3a72b3/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp#L243 The exact assertion isn't that important, although I think `MemberKind` isn't reset correctly in `TypeRecordMapping::visitMemberEnd`. The point is that we were visiting data that didn't belong to an `LF_FIELDLIST` when building the parent map, because we didn't check the record type before deserializing with `TypeDeserializer::deserializeAs<FieldListRecord>`. I added a check for this. There are more cases where we call `deserializeAs` but didn't check the symbol type in the function. However, in these cases, the callers already check the type. I still added safety checks for them. Furthermore, we still have some `lldbassert`s in the file. I'll remove them in a followup PR. >From dca3881811cb1bc98d977af1820c59bfce1e2aa1 Mon Sep 17 00:00:00 2001 From: Nerixyz <[email protected]> Date: Wed, 12 Aug 2026 18:47:13 +0200 Subject: [PATCH] [lldb][NativePDB] Check record types before deserializing --- .../NativePDB/SymbolFileNativePDB.cpp | 11 +- .../invalid-field-list-reference.yaml | 233 ++++++++++++++++++ 2 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 lldb/test/Shell/SymbolFile/NativePDB/invalid-field-list-reference.yaml diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index ec6e89b10e776..2ea0907b49897 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1125,6 +1125,9 @@ SymbolFileNativePDB::CreateConstantSymbol(PdbGlobalSymId var_id, TpiStream &tpi = m_index->tpi(); ConstantSym constant(cvs.kind()); + if (cvs.kind() != S_CONSTANT) + return nullptr; + if (auto err = SymbolDeserializer::deserializeAs<ConstantSym>(cvs, constant)) { LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err), @@ -1681,6 +1684,8 @@ void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id, CompilandIndexItem *cii = m_index->compilands().GetCompiland(id.modi); CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(id.offset); CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii); + if (sym.kind() != S_INLINESITE) + return; InlineSiteSym inline_site(static_cast<SymbolRecordKind>(sym.kind())); if (auto err = @@ -2368,7 +2373,8 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id, if (is_constant) { CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(var_id.offset); - assert(sym.kind() == S_CONSTANT); + if (sym.kind() != S_CONSTANT) + return nullptr; ConstantSym constant(sym.kind()); if (auto err = SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant)) { @@ -2838,6 +2844,9 @@ void SymbolFileNativePDB::BuildParentMap() { }; CVType field_list_cvt = m_index->tpi().getType(tag.asTag().FieldList); + if (field_list_cvt.kind() != LF_FIELDLIST) + continue; // Invalid reference to a field list. + ProcessTpiStream process(*m_index, *ti, tag, m_parent_types); FieldListRecord field_list; if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>( diff --git a/lldb/test/Shell/SymbolFile/NativePDB/invalid-field-list-reference.yaml b/lldb/test/Shell/SymbolFile/NativePDB/invalid-field-list-reference.yaml new file mode 100644 index 0000000000000..26dc10cdad79a --- /dev/null +++ b/lldb/test/Shell/SymbolFile/NativePDB/invalid-field-list-reference.yaml @@ -0,0 +1,233 @@ +# Check that invalid references to field lists are handled gracefully. + +# RUN: llvm-pdbutil yaml2pdb %s --pdb=%t +# RUN: lldb-test symbols %t --find=type --name=Inner | FileCheck %s --check-prefix=INNER +# RUN: lldb-test symbols %t --find=type --name=Outer | FileCheck %s --check-prefix=OUTER + +# INNER: Found 1 types: +# INNER-NEXT: Type{{.*}} , name = "Inner", size = 4, compiler_type = {{.*}} struct Inner { +# INNER-NEXT: int i; +# INNER-NEXT: } + +# We should find the struct, but can't complete it. +# OUTER: Found 1 types: +# OUTER-NEXT: Type{{.*}} , name = "Outer", size = 4, compiler_type = {{.*}} struct Outer + +# OUTER-NOT: } +# OUTER-NOT: int + +# This was compiled with clang-cl from + +# > cat main.cpp +# struct Outer { +# struct Inner { +# int i = 1; +# }; +# int o = 1; +# }; +# +# int main() { +# Outer o; +# Outer::Inner i; +# return o.o + i.i; +# } +# > clang-cl main.cpp /GS- /GR- /Z7 /link /nodefaultlib /entry:main + +# The output was trimmed to only include necessary parts. +# Changes to references are marked with "CHANGED:". + +--- +StringTable: + - 'F:\Dev\dummy\invalid-fwd-refs\main.cpp' +PdbStream: + Features: [ VC140 ] +DbiStream: + VerHeader: V70 + Age: 1 + BuildNumber: 36363 + PdbDllVersion: 0 + PdbDllRbld: 0 + Flags: 0 + MachineType: Amd64 + Modules: + - Module: 'C:\Users\johannes\AppData\Local\Temp\main-1eb5ab.obj' + ObjFile: 'C:\Users\johannes\AppData\Local\Temp\main-1eb5ab.obj' + SourceFiles: + - 'F:\Dev\dummy\invalid-fwd-refs\main.cpp' + Modi: + Signature: 4 + Records: + - Kind: S_OBJNAME + ObjNameSym: + Signature: 0 + ObjectName: 'C:\Users\johannes\AppData\Local\Temp\main-1eb5ab.obj' + - Kind: S_COMPILE3 + Compile3Sym: + Flags: [ ] + Machine: X64 + FrontendMajor: 22 + FrontendMinor: 1 + FrontendBuild: 4 + FrontendQFE: 0 + BackendMajor: 22014 + BackendMinor: 0 + BackendBuild: 0 + BackendQFE: 0 + Version: '' + - Kind: S_BUILDINFO + BuildInfoSym: + BuildId: 4107 + SectionHeaders: + - Name: .text + VirtualSize: 97 + VirtualAddress: 4096 + SizeOfRawData: 512 + PointerToRawData: 1024 + Characteristics: 1610612768 + - Name: .rdata + VirtualSize: 116 + VirtualAddress: 8192 + SizeOfRawData: 512 + PointerToRawData: 1536 + Characteristics: 1073741888 + - Name: .pdata + VirtualSize: 36 + VirtualAddress: 12288 + SizeOfRawData: 512 + PointerToRawData: 2048 + Characteristics: 1073741888 +TpiStream: + Version: VC80 + Records: + # 4096 + - Kind: LF_ARGLIST + ArgList: + ArgIndices: [ ] + # 4097 + - Kind: LF_PROCEDURE + Procedure: + ReturnType: 116 + CallConv: NearC + Options: [ None ] + ParameterCount: 0 + # CHANGED: Was 4096, now 8958 (doesn't exist). + # Triggers an assertion failure when reading the record as an LF_FIELDLIST. + ArgumentList: 8958 + # 4098 + - Kind: LF_STRUCTURE + Class: + MemberCount: 0 + Options: [ None, ForwardReference, HasUniqueName ] + FieldList: 0 + Name: Outer + UniqueName: '.?AUOuter@@' + DerivationList: 0 + VTableShape: 0 + Size: 0 + # 4099 + - Kind: LF_STRUCTURE + Class: + MemberCount: 0 + Options: [ None, Nested, ForwardReference, HasUniqueName ] + FieldList: 0 + Name: 'Outer::Inner' + UniqueName: '.?AUInner@Outer@@' + DerivationList: 0 + VTableShape: 0 + Size: 0 + # 4100 + - Kind: LF_FIELDLIST + FieldList: + - Kind: LF_MEMBER + DataMember: + Attrs: 3 + Type: 116 + FieldOffset: 0 + Name: o + - Kind: LF_NESTTYPE + NestedType: + Type: 4099 + Name: Inner + # 4101 + - Kind: LF_STRUCTURE + Class: + MemberCount: 2 + Options: [ None, HasConstructorOrDestructor, ContainsNestedClass, HasUniqueName ] + # CHANGED: Was 4100 (LF_FIELDLIST), now 4097 (LF_PROCEDURE) + FieldList: 4097 + Name: Outer + UniqueName: '.?AUOuter@@' + DerivationList: 0 + VTableShape: 0 + Size: 4 + # 4102 + - Kind: LF_FIELDLIST + FieldList: + - Kind: LF_MEMBER + DataMember: + Attrs: 3 + Type: 116 + FieldOffset: 0 + Name: i + # 4103 + - Kind: LF_STRUCTURE + Class: + MemberCount: 1 + Options: [ None, HasConstructorOrDestructor, Nested, HasUniqueName ] + FieldList: 4102 + Name: 'Outer::Inner' + UniqueName: '.?AUInner@Outer@@' + DerivationList: 0 + VTableShape: 0 + Size: 4 + # 4104 + - Kind: LF_POINTER + Pointer: + ReferentType: 4098 + Attrs: 66572 + # 4105 + - Kind: LF_MFUNCTION + MemberFunction: + ReturnType: 3 + ClassType: 4098 + ThisType: 4104 + CallConv: NearC + Options: [ None, Constructor ] + ParameterCount: 0 + ArgumentList: 4096 + ThisPointerAdjustment: 0 + # 4106 + - Kind: LF_POINTER + Pointer: + ReferentType: 4098 + Attrs: 65548 + # 4107 + - Kind: LF_POINTER + Pointer: + ReferentType: 4099 + Attrs: 66572 + # 4108 + - Kind: LF_MFUNCTION + MemberFunction: + ReturnType: 3 + ClassType: 4099 + ThisType: 4107 + CallConv: NearC + Options: [ None, Constructor ] + ParameterCount: 0 + ArgumentList: 4096 + ThisPointerAdjustment: 0 + # 4109 + - Kind: LF_POINTER + Pointer: + ReferentType: 4099 + Attrs: 65548 +PublicsStream: + Records: + - Kind: S_PUB32 + PublicSym32: + Flags: [ Function ] + Offset: 0 + Segment: 1 + Name: main +... _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
