[CodeView] Call llvm::codeview::visitMemberRecordStream with the deserialized CVType...
authorZequan Wu <zequanwu@google.com>
Thu, 30 Jun 2022 00:09:40 +0000 (17:09 -0700)
committerZequan Wu <zequanwu@google.com>
Thu, 30 Jun 2022 00:18:56 +0000 (17:18 -0700)
llvm::codeview::visitMemberRecordStream expects to receive an array ref that's FieldListRecord's Data not a CVType's data which has 4 more bytes preceeding. The first 2 bytes indicate the size of the FieldListRecord, and following 2 bytes is always 0x1203. Inside llvm::codeview::visitMemberRecordStream, it iterates to the data to check if first two bytes matching some type record kinds. If the size coincidentally matches one type kind, it will start parsing from there and causing crash.

lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp

index daca398..6dcce73 100644 (file)
@@ -401,10 +401,13 @@ void PdbAstBuilder::BuildParentMap() {
       }
     };
 
-    CVType field_list = m_index.tpi().getType(tag.asTag().FieldList);
+    CVType field_list_cvt = m_index.tpi().getType(tag.asTag().FieldList);
     ProcessTpiStream process(m_index, *ti, tag, m_parent_types);
-    llvm::Error error = visitMemberRecordStream(field_list.data(), process);
-    if (error)
+    FieldListRecord field_list;
+    if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(
+            field_list_cvt, field_list))
+      llvm::consumeError(std::move(error));
+    if (llvm::Error error = visitMemberRecordStream(field_list.Data, process))
       llvm::consumeError(std::move(error));
   }
 
@@ -757,22 +760,26 @@ bool PdbAstBuilder::CompleteTagDecl(clang::TagDecl &tag) {
   CVType field_list_cvt = m_index.tpi().getType(field_list_ti);
   if (field_list_cvt.kind() != LF_FIELDLIST)
     return false;
+  FieldListRecord field_list;
+  if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(
+          field_list_cvt, field_list))
+    llvm::consumeError(std::move(error));
 
   // Visit all members of this class, then perform any finalization necessary
   // to complete the class.
   CompilerType ct = ToCompilerType(tag_qt);
   UdtRecordCompleter completer(best_ti, ct, tag, *this, m_index,
                                m_cxx_record_map);
-  auto error =
-      llvm::codeview::visitMemberRecordStream(field_list_cvt.data(), completer);
+  llvm::Error error =
+      llvm::codeview::visitMemberRecordStream(field_list.Data, completer);
   completer.complete();
 
   status.resolved = true;
-  if (!error)
-    return true;
-
-  llvm::consumeError(std::move(error));
-  return false;
+  if (error) {
+    llvm::consumeError(std::move(error));
+    return false;
+  }
+  return true;
 }
 
 clang::QualType PdbAstBuilder::CreateSimpleType(TypeIndex ti) {
@@ -1118,10 +1125,14 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id,
       }
     }
     if (!tag_record.FieldList.isSimple()) {
-      CVType field_list = m_index.tpi().getType(tag_record.FieldList);
+      CVType field_list_cvt = m_index.tpi().getType(tag_record.FieldList);
+      FieldListRecord field_list;
+      if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(
+              field_list_cvt, field_list))
+        llvm::consumeError(std::move(error));
       CreateMethodDecl process(m_index, m_clang, func_ti, function_decl,
                                parent_opaque_ty, func_name, func_ct);
-      if (llvm::Error err = visitMemberRecordStream(field_list.data(), process))
+      if (llvm::Error err = visitMemberRecordStream(field_list.Data, process))
         llvm::consumeError(std::move(err));
     }
 
index 10e8cbd..ee1de24 100644 (file)
@@ -733,9 +733,14 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo(
         }
         if (IsTagRecord(class_cvt)) {
           TagRecord tag_record = CVTagRecord::create(class_cvt).asTag();
-          CVType field_list = index.tpi().getType(tag_record.FieldList);
+          CVType field_list_cvt = index.tpi().getType(tag_record.FieldList);
+          FieldListRecord field_list;
+          if (llvm::Error error =
+                  TypeDeserializer::deserializeAs<FieldListRecord>(
+                      field_list_cvt, field_list))
+            llvm::consumeError(std::move(error));
           FindMembersSize find_members_size(members_info, index.tpi());
-          if (llvm::Error err = visitMemberRecordStream(field_list.data(),
+          if (llvm::Error err = visitMemberRecordStream(field_list.Data,
                                                         find_members_size)) {
             llvm::consumeError(std::move(err));
             break;
index 645a996..ec37d27 100644 (file)
@@ -67,10 +67,13 @@ NativeEnumEnumEnumerators::NativeEnumEnumEnumerators(
 
   ContinuationIndex = ClassParent.getEnumRecord().FieldList;
   while (ContinuationIndex) {
-    CVType FieldList = Types.getType(*ContinuationIndex);
-    assert(FieldList.kind() == LF_FIELDLIST);
+    CVType FieldListCVT = Types.getType(*ContinuationIndex);
+    assert(FieldListCVT.kind() == LF_FIELDLIST);
     ContinuationIndex.reset();
-    cantFail(visitMemberRecordStream(FieldList.data(), *this));
+    FieldListRecord FieldList;
+    cantFail(TypeDeserializer::deserializeAs<FieldListRecord>(FieldListCVT,
+                                                              FieldList));
+    cantFail(visitMemberRecordStream(FieldList.Data, *this));
   }
 }
 
index 49b24e2..e4e2b2a 100644 (file)
@@ -490,7 +490,10 @@ private:
 
 Error LeafRecordImpl<FieldListRecord>::fromCodeViewRecord(CVType Type) {
   MemberRecordConversionVisitor V(Members);
-  return visitMemberRecordStream(Type.content(), V);
+  FieldListRecord FieldList;
+  cantFail(TypeDeserializer::deserializeAs<FieldListRecord>(Type,
+                                                            FieldList));
+  return visitMemberRecordStream(FieldList.Data, V);
 }
 
 CVType LeafRecordImpl<FieldListRecord>::toCodeViewRecord(