[Lldb-commits] [lldb] [lldb][NativePDB] Handle invalid type references gracefully (PR #202371)
via lldb-commits
lldb-commits at lists.llvm.org
Mon Jun 8 08:48:46 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Nerixyz (Nerixyz)
<details>
<summary>Changes</summary>
Incrementally linked PDBs can contain semantically incorrect references to types from the symbol streams and the IPI stream.
I can't reproduce it reliably, but as mentioned in #<!-- -->200452, at some point the references become incorrect.
We should not crash if we receive such PDBs as input. Here I noticed two issues:
1. `CVTagRecord` requires the passed type to be a type record (union/struct/class). We should check that this is the case with `IsTagRecord`.
2. After casting the return of `GetOrCreateClangType`, check that it's the expected type (not null).
I added a test for both cases.
---
Full diff: https://github.com/llvm/llvm-project/pull/202371.diff
2 Files Affected:
- (modified) lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp (+8-1)
- (added) lldb/test/Shell/SymbolFile/NativePDB/invalid-type-refs.yaml (+221)
``````````diff
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp
index e1cdfca57e79e..673bd2826b455 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp
@@ -1027,13 +1027,18 @@ clang::FunctionDecl *PdbAstBuilderClang::CreateFunctionDecl(
TypeIndex class_index = func_record.getClassType();
CVType parent_cvt = index.tpi().getType(class_index);
+ if (!IsTagRecord(parent_cvt))
+ return nullptr;
TagRecord tag_record = CVTagRecord::create(parent_cvt).asTag();
// If it's a forward reference, try to get the real TypeIndex.
if (tag_record.isForwardRef()) {
llvm::Expected<TypeIndex> eti =
index.tpi().findFullDeclForForwardRef(class_index);
if (eti) {
- tag_record = CVTagRecord::create(index.tpi().getType(*eti)).asTag();
+ CVType resolved_tag_record = index.tpi().getType(*eti);
+ if (!IsTagRecord(resolved_tag_record))
+ return nullptr;
+ tag_record = CVTagRecord::create(resolved_tag_record).asTag();
} else {
LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), eti.takeError(),
"failed to find full decl for forward ref: {0}");
@@ -1229,6 +1234,8 @@ PdbAstBuilderClang::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) {
const clang::FunctionProtoType *func_type =
llvm::dyn_cast<clang::FunctionProtoType>(qt);
+ if (!func_type)
+ return nullptr;
CompilerType func_ct = ToCompilerType(qt);
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/invalid-type-refs.yaml b/lldb/test/Shell/SymbolFile/NativePDB/invalid-type-refs.yaml
new file mode 100644
index 0000000000000..341abd32eb838
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/NativePDB/invalid-type-refs.yaml
@@ -0,0 +1,221 @@
+# Check that semantically incorrect type references are handled without errors/crashes.
+
+# RUN: llvm-pdbutil yaml2pdb %s --pdb=%t
+# RUN: lldb-test symbols %t | FileCheck %s
+
+# CHECK: CompileUnit
+# CHECK-NEXT: Function{{.*}}, demangled = main
+# CHECK-NEXT: Block{{.*}}, ranges = [0x00000fff-0x0000101b)
+# CHECK-NEXT: Function{{.*}}, demangled = AStruct::a_method
+# CHECK-NEXT: Block{{.*}}, ranges = [0x0000101f-0x0000102b)
+
+# This was compiled with clang-cl from
+
+# > clang-cl main.cpp /GS- /GR- /Z7 /link /nodefaultlib /entry:main
+# > cat main.cpp
+# struct AStruct {
+# int a_method() { return 42; }
+# };
+# int main() {
+# AStruct a;
+# return a.a_method();
+# }
+
+# The output was trimmed to only include necessary parts.
+# Changes to references are marked with "CHANGED:".
+
+---
+PdbStream:
+ Features: [ VC140 ]
+DbiStream:
+ MachineType: Amd64
+ Modules:
+ - Module: 'C:\Users\johannes\AppData\Local\Temp\main-b7a866.obj'
+ SourceFiles:
+ - 'F:\Dev\dummy\invalid-refs\main.cpp'
+ Modi:
+ Records:
+ - Kind: S_OBJNAME
+ ObjNameSym:
+ Signature: 0
+ ObjectName: 'C:\Users\johannes\AppData\Local\Temp\main-b7a866.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: 'clang version 22.1.4 (https://github.com/llvm/llvm-project 35990504507d79e0b9deb809c8ee5e1b34ceef20)'
+ - Kind: S_GPROC32
+ ProcSym:
+ PtrEnd: 300
+ CodeSize: 28
+ DbgStart: 0
+ DbgEnd: 0
+ # CHANGED: Should be 4097 (LF_PROCEDURE). Changed to 4099 (LF_POINTER).
+ FunctionType: 4099
+ Segment: 1
+ Flags: [ IsNoInline, HasOptimizedDebugInfo ]
+ DisplayName: main
+ - Kind: S_FRAMEPROC
+ FrameProcSym:
+ TotalFrameBytes: 40
+ PaddingFrameBytes: 0
+ OffsetToPadding: 0
+ BytesOfCalleeSavedRegisters: 0
+ OffsetOfExceptionHandler: 0
+ SectionIdOfExceptionHandler: 0
+ Flags: [ SafeBuffers ]
+ - Kind: S_LOCAL
+ LocalSym:
+ Type: 4102
+ Flags: [ ]
+ VarName: a
+ - Kind: S_DEFRANGE_FRAMEPOINTER_REL
+ DefRangeFramePointerRelSym:
+ Offset: 35
+ Range:
+ OffsetStart: 12
+ ISectStart: 1
+ Range: 16
+ Gaps: []
+ - Kind: S_END
+ ScopeEndSym: {}
+ - Kind: S_BUILDINFO
+ BuildInfoSym:
+ BuildId: 4105
+ - Kind: S_GPROC32
+ ProcSym:
+ PtrEnd: 436
+ CodeSize: 12
+ DbgStart: 0
+ DbgEnd: 0
+ FunctionType: 4100
+ Offset: 32
+ Segment: 1
+ Flags: [ IsNoInline, HasOptimizedDebugInfo ]
+ DisplayName: 'AStruct::a_method'
+ - Kind: S_FRAMEPROC
+ FrameProcSym:
+ TotalFrameBytes: 8
+ PaddingFrameBytes: 0
+ OffsetToPadding: 0
+ BytesOfCalleeSavedRegisters: 0
+ OffsetOfExceptionHandler: 0
+ SectionIdOfExceptionHandler: 0
+ Flags: [ SafeBuffers ]
+ - Kind: S_LOCAL
+ LocalSym:
+ Type: 4103
+ Flags: [ IsParameter ]
+ VarName: this
+ - Kind: S_DEFRANGE_FRAMEPOINTER_REL
+ DefRangeFramePointerRelSym:
+ Offset: 0
+ Range:
+ OffsetStart: 37
+ ISectStart: 1
+ Range: 7
+ Gaps: []
+ - Kind: S_END
+ ScopeEndSym: {}
+ SectionHeaders:
+ - Name: .text
+ VirtualSize: 44
+ VirtualAddress: 4096
+ SizeOfRawData: 512
+ PointerToRawData: 1024
+ Characteristics: 1610612768
+ - Name: .rdata
+ VirtualSize: 104
+ VirtualAddress: 8192
+ SizeOfRawData: 512
+ PointerToRawData: 1536
+ Characteristics: 1073741888
+ - Name: .pdata
+ VirtualSize: 24
+ VirtualAddress: 12288
+ SizeOfRawData: 512
+ PointerToRawData: 2048
+ Characteristics: 1073741888
+TpiStream:
+ Records:
+ # 4096
+ - Kind: LF_ARGLIST
+ ArgList:
+ ArgIndices: [ ]
+ # 4097
+ - Kind: LF_PROCEDURE
+ Procedure:
+ ReturnType: 116
+ CallConv: NearC
+ Options: [ None ]
+ ParameterCount: 0
+ ArgumentList: 4096
+ # 4098
+ - Kind: LF_STRUCTURE
+ Class:
+ MemberCount: 0
+ Options: [ None, ForwardReference, HasUniqueName ]
+ FieldList: 0
+ Name: AStruct
+ UniqueName: '.?AUAStruct@@'
+ DerivationList: 0
+ VTableShape: 0
+ Size: 0
+ # 4099
+ - Kind: LF_POINTER
+ Pointer:
+ ReferentType: 4098
+ Attrs: 66572
+ # 4100
+ - Kind: LF_MFUNCTION
+ MemberFunction:
+ ReturnType: 116
+ # CHANGED: Should be 4098 (LF_STRUCTURE). Changed to 4097 (LF_PROCEDURE).
+ ClassType: 4097
+ ThisType: 4099
+ CallConv: NearC
+ Options: [ None ]
+ ParameterCount: 0
+ ArgumentList: 4096
+ ThisPointerAdjustment: 0
+ # 4101
+ - Kind: LF_FIELDLIST
+ FieldList:
+ - Kind: LF_ONEMETHOD
+ OneMethod:
+ Type: 4100
+ Attrs: 3
+ VFTableOffset: -1
+ Name: a_method
+ # 4102
+ - Kind: LF_STRUCTURE
+ Class:
+ MemberCount: 1
+ Options: [ None, HasUniqueName ]
+ FieldList: 4101
+ Name: AStruct
+ UniqueName: '.?AUAStruct@@'
+ DerivationList: 0
+ VTableShape: 0
+ Size: 1
+ # 4103
+ - Kind: LF_POINTER
+ Pointer:
+ ReferentType: 4098
+ Attrs: 65548
+PublicsStream:
+ Records:
+ - Kind: S_PUB32
+ PublicSym32:
+ Flags: [ Function ]
+ Segment: 1
+ Name: main
+...
``````````
</details>
https://github.com/llvm/llvm-project/pull/202371
More information about the lldb-commits
mailing list