Skip to content

release/19.x: [RemoveDIs] Fix spliceDebugInfo splice-to-end edge case (#105671) #106691

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

llvmbot
Copy link
Member

@llvmbot llvmbot commented Aug 30, 2024

Backport 43661a1

Requested by: @OCHyams

Fix llvm#105571 which demonstrates an end() iterator dereference when
performing a non-empty splice to end() from a region that ends at
Src::end().

Rather than calling Instruction::adoptDbgRecords from Dest, create a marker
(which takes an iterator) and absorbDebugValues onto that. The "absorb" variant
doesn't clean up the source marker, which in this case we know is a trailing
marker, so we have to do that manually.

(cherry picked from commit 43661a1)
@llvmbot llvmbot added this to the LLVM 19.X Release milestone Aug 30, 2024
@llvmbot
Copy link
Member Author

llvmbot commented Aug 30, 2024

@jmorse What do you think about merging this PR to the release branch?

@llvmbot
Copy link
Member Author

llvmbot commented Aug 30, 2024

@llvm/pr-subscribers-llvm-ir

Author: None (llvmbot)

Changes

Backport 43661a1

Requested by: @OCHyams


Full diff: https://github.com./llvm/llvm-project/pull/106691.diff

2 Files Affected:

  • (modified) llvm/lib/IR/BasicBlock.cpp (+10-2)
  • (modified) llvm/unittests/IR/BasicBlockDbgInfoTest.cpp (+54)
diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp
index bf19934da047c4..103ec0da4763fd 100644
--- a/llvm/lib/IR/BasicBlock.cpp
+++ b/llvm/lib/IR/BasicBlock.cpp
@@ -971,8 +971,16 @@ void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src,
   if (ReadFromTail && Src->getMarker(Last)) {
     DbgMarker *FromLast = Src->getMarker(Last);
     if (LastIsEnd) {
-      Dest->adoptDbgRecords(Src, Last, true);
-      // adoptDbgRecords will release any trailers.
+      if (Dest == end()) {
+        // Abosrb the trailing markers from Src.
+        assert(FromLast == Src->getTrailingDbgRecords());
+        createMarker(Dest)->absorbDebugValues(*FromLast, true);
+        FromLast->eraseFromParent();
+        Src->deleteTrailingDbgRecords();
+      } else {
+        // adoptDbgRecords will release any trailers.
+        Dest->adoptDbgRecords(Src, Last, true);
+      }
       assert(!Src->getTrailingDbgRecords());
     } else {
       // FIXME: can we use adoptDbgRecords here to reduce allocations?
diff --git a/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp b/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp
index 91a0745a0cc76e..e6f8df2762e81e 100644
--- a/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp
+++ b/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp
@@ -1525,4 +1525,58 @@ TEST(BasicBlockDbgInfoTest, DbgMoveToEnd) {
   EXPECT_FALSE(Ret->hasDbgRecords());
 }
 
+TEST(BasicBlockDbgInfoTest, CloneTrailingRecordsToEmptyBlock) {
+  LLVMContext C;
+  std::unique_ptr<Module> M = parseIR(C, R"(
+    define i16 @foo(i16 %a) !dbg !6 {
+    entry:
+      %b = add i16 %a, 0
+        #dbg_value(i16 %b, !9, !DIExpression(), !11)
+      ret i16 0, !dbg !11
+    }
+
+    !llvm.dbg.cu = !{!0}
+    !llvm.module.flags = !{!5}
+
+    !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+    !1 = !DIFile(filename: "t.ll", directory: "/")
+    !2 = !{}
+    !5 = !{i32 2, !"Debug Info Version", i32 3}
+    !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
+    !7 = !DISubroutineType(types: !2)
+    !8 = !{!9}
+    !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
+    !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
+    !11 = !DILocation(line: 1, column: 1, scope: !6)
+)");
+  ASSERT_TRUE(M);
+
+  Function *F = M->getFunction("foo");
+  BasicBlock &BB = F->getEntryBlock();
+  // Start with no trailing records.
+  ASSERT_FALSE(BB.getTrailingDbgRecords());
+
+  BasicBlock::iterator Ret = std::prev(BB.end());
+  BasicBlock::iterator B = std::prev(Ret);
+
+  // Delete terminator which has debug records: we now get trailing records.
+  Ret->eraseFromParent();
+  EXPECT_TRUE(BB.getTrailingDbgRecords());
+
+  BasicBlock *NewBB = BasicBlock::Create(C, "NewBB", F);
+  NewBB->splice(NewBB->end(), &BB, B, BB.end());
+
+  // The trailing records should've been absorbed into NewBB.
+  EXPECT_FALSE(BB.getTrailingDbgRecords());
+  EXPECT_TRUE(NewBB->getTrailingDbgRecords());
+  if (NewBB->getTrailingDbgRecords()) {
+    EXPECT_EQ(
+        llvm::range_size(NewBB->getTrailingDbgRecords()->getDbgRecordRange()),
+        1u);
+  }
+
+  // Drop the trailing records now, to prevent a cleanup assertion.
+  NewBB->deleteTrailingDbgRecords();
+}
+
 } // End anonymous namespace.

@OCHyams
Copy link
Contributor

OCHyams commented Aug 30, 2024

Edge-case BasicBlock::end() iterator dereference, depends on #106690

@jmorse
Copy link
Member

jmorse commented Aug 30, 2024

@jmorse What do you think about merging this PR to the release branch?

I feel this is safe to go into the release branch; I don't think it should block the 19.0.0 release though, better to have it in a point release. This fault has been present for roughly five months and has only just been uncovered, so IMHO it's not a pressing issue.

@dklimkin
Copy link
Member

We are seeing ASAN errors past 43661a1214353ea1773a711f403f8d1118e9ca0f:

AddressSanitizer: 120 byte(s) leaked in 2 allocation(s).

Indirect leak of 96 byte(s) in 1 object(s) allocated from:
    #0 0x55661863b59d in operator new(unsigned long) llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:86:3
    #1 0x7fe8882b642e in llvm::DbgVariableRecord::createUnresolvedDbgVariableRecord(llvm::DbgVariableRecord::LocationType, llvm::Metadata*, llvm::MDNode*, llvm::MDNode*, llvm::MDNode*, llvm::Metadata*, llvm::MDNode*, llvm::MDNode*) llvm-project/llvm/lib/IR/DebugProgramInstruction.cpp:174:10
    #2 0x7fe88c37fdc3 in llvm::LLParser::parseDebugRecord(llvm::DbgRecord*&, llvm::LLParser::PerFunctionState&) llvm-project/llvm/lib/AsmParser/LLParser.cpp:6832:8
    #3 0x7fe88c37ef4c in llvm::LLParser::parseBasicBlock(llvm::LLParser::PerFunctionState&) llvm-project/llvm/lib/AsmParser/LLParser.cpp:6673:11
    #4 0x7fe88c344e2b in llvm::LLParser::parseFunctionBody(llvm::Function&, unsigned int, llvm::ArrayRef<unsigned int>) llvm-project/llvm/lib/AsmParser/LLParser.cpp:6618:9
    #5 0x7fe88c33cbe3 in llvm::LLParser::parseDefine() llvm-project/llvm/lib/AsmParser/LLParser.cpp:762:10
    #6 0x7fe88c335623 in llvm::LLParser::parseTopLevelEntities() llvm-project/llvm/lib/AsmParser/LLParser.cpp:566:11
    #7 0x7fe88c334e42 in llvm::LLParser::Run(bool, llvm::function_ref<std::__u::optional<std::__u::basic_string<char, std::__u::char_traits<char>, std::__u::allocator<char>>> (llvm::StringRef, llvm::StringRef)>) llvm-project/llvm/lib/AsmParser/LLParser.cpp:94:10
    #8 0x7fe88c3c757e in parseAssemblyInto(llvm::MemoryBufferRef, llvm::Module*, llvm::ModuleSummaryIndex*, llvm::SMDiagnostic&, llvm::SlotMapping*, bool, llvm::function_ref<std::__u::optional<std::__u::basic_string<char, std::__u::char_traits<char>, std::__u::allocator<char>>> (llvm::StringRef, llvm::StringRef)>) llvm-project/llvm/lib/AsmParser/Parser.cpp:35:8
    #9 0x7fe88c3c914b in parseAssemblyInto llvm-project/llvm/lib/AsmParser/Parser.cpp:42:10
    #10 0x7fe88c3c914b in parseAssembly llvm-project/llvm/lib/AsmParser/Parser.cpp:53:7
    #11 0x7fe88c3c914b in llvm::parseAssemblyString(llvm::StringRef, llvm::SMDiagnostic&, llvm::LLVMContext&, llvm::SlotMapping*) llvm-project/llvm/lib/AsmParser/Parser.cpp:141:10
    #12 0x7fe89ea5fd0d in parseIR llvm-project/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp:30:33
    
Indirect leak of 24 byte(s) in 1 object(s) allocated from:
    #0 0x55661863b59d in operator new(unsigned long) llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:86:3
    #1 0x7fe888182813 in llvm::BasicBlock::createMarker(llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction, false, false, void, true, llvm::BasicBlock>, false, false>) llvm-project/llvm/lib/IR/BasicBlock.cpp:71:8
    #2 0x7fe88818af8c in llvm::BasicBlock::spliceDebugInfoImpl(llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction, false, false, void, true, llvm::BasicBlock>, false, false>, llvm::BasicBlock*, llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction, false, false, void, true, llvm::BasicBlock>, false, false>, llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction, false, false, void, true, llvm::BasicBlock>, false, false>) llvm-project/llvm/lib/IR/BasicBlock.cpp:981:9
    #3 0x7fe88818a544 in llvm::BasicBlock::spliceDebugInfo(llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction, false, false, void, true, llvm::BasicBlock>, false, false>, llvm::BasicBlock*, llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction, false, false, void, true, llvm::BasicBlock>, false, false>, llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction, false, false, void, true, llvm::BasicBlock>, false, false>) llvm-project/llvm/lib/IR/BasicBlock.cpp:873:3
    #4 0x7fe888188da2 in llvm::BasicBlock::splice(llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction, false, false, void, true, llvm::BasicBlock>, false, false>, llvm::BasicBlock*, llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction, false, false, void, true, llvm::BasicBlock>, false, false>, llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction, false, false, void, true, llvm::BasicBlock>, false, false>) llvm-project/llvm/lib/IR/BasicBlock.cpp:1051:5

@OCHyams
Copy link
Contributor

OCHyams commented Aug 30, 2024

Thanks for the report, I'll look at that now

OCHyams added a commit to OCHyams/llvm-project that referenced this pull request Aug 30, 2024
dklimkin pushed a commit that referenced this pull request Aug 30, 2024
Fixes issue found here
#106691 (comment)

The issue wasn't in the code change itself, just the unittest; the
trailing marker wasn't properly cleaned up.
OCHyams added a commit to OCHyams/llvm-project that referenced this pull request Sep 2, 2024
@OCHyams
Copy link
Contributor

OCHyams commented Sep 2, 2024

Re-opened backport request with the fix too - #106952

@OCHyams OCHyams closed this Sep 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Development

Successfully merging this pull request may close these issues.

4 participants