[Lldb-commits] [lldb] [lldb][NativePDB] Check record types before deserializing (PR #215847)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Aug 12 10:03:09 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Nerixyz (Nerixyz)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/215847.diff
2 Files Affected:
- (modified) lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp (+10-1)
- (added) lldb/test/Shell/SymbolFile/NativePDB/invalid-field-list-reference.yaml (+233)
``````````diff
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 at 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 at 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
+...
``````````
</details>
https://github.com/llvm/llvm-project/pull/215847
More information about the lldb-commits
mailing list