From 7bb9626d5ab901e5c1a8e9acbbb1684c982401b4 Mon Sep 17 00:00:00 2001 From: Tulio Magno Quites Machado Filho Date: Fri, 10 Jul 2026 15:45:02 -0300 Subject: [PATCH] [LLVM][Verifier] Fix buffer overflow when verifying gc.statepoint (#208278) When a negative base index is passed, the verification detects the out-of-bounds value and start printing information that helps to identify what caused the error. In order to print all the information, it tries to dereference the Base pointer at GCRelocateInst::getBasePtr(), causing the buffer overflow. Add a bounds check to getBasePTR() and getDerivedPtr() in order to avoid this. Improve the test in order to validate negative values passed as indexes. They're based on the reproducer from issue #199191. Fixes #199191 --- llvm/lib/IR/AsmWriter.cpp | 10 ++++++++-- llvm/lib/IR/IntrinsicInst.cpp | 19 ++++++++++++++++--- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index e90630a8cae5..6752d6aa344d 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -4372,9 +4372,15 @@ void AssemblyWriter::printInstructionLine(const Instruction &I) { /// intrinsic indicating base and derived pointer names. void AssemblyWriter::printGCRelocateComment(const GCRelocateInst &Relocate) { Out << " ; ("; - writeOperand(Relocate.getBasePtr(), false); + if (Value *BasePtr = Relocate.getBasePtr()) + writeOperand(BasePtr, false); + else + Out << "invalid"; Out << ", "; - writeOperand(Relocate.getDerivedPtr(), false); + if (Value *DerivedPtr = Relocate.getDerivedPtr()) + writeOperand(DerivedPtr, false); + else + Out << "invalid"; Out << ")"; } diff --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp index 3e9f3257956a..eb964d566f29 100644 --- a/llvm/lib/IR/IntrinsicInst.cpp +++ b/llvm/lib/IR/IntrinsicInst.cpp @@ -867,10 +867,16 @@ Value *GCRelocateInst::getBasePtr() const { auto Statepoint = getStatepoint(); if (isa(Statepoint)) return UndefValue::get(Statepoint->getType()); - + // Handle too few (bundle) arguments to avoid crashes when printing invalid + // IR, e.g. in the verifier. auto *GCInst = cast(Statepoint); - if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live)) + if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live)) { + if (getBasePtrIndex() > Opt->Inputs.size()) + return nullptr; return *(Opt->Inputs.begin() + getBasePtrIndex()); + } + if (getBasePtrIndex() > GCInst->arg_size()) + return nullptr; return *(GCInst->arg_begin() + getBasePtrIndex()); } @@ -879,9 +885,16 @@ Value *GCRelocateInst::getDerivedPtr() const { if (isa(Statepoint)) return UndefValue::get(Statepoint->getType()); + // Handle too few (bundle) arguments to avoid crashes when printing invalid + // IR, e.g. in the verifier. auto *GCInst = cast(Statepoint); - if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live)) + if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live)) { + if (getDerivedPtrIndex() > Opt->Inputs.size()) + return nullptr; return *(Opt->Inputs.begin() + getDerivedPtrIndex()); + } + if (getDerivedPtrIndex() > GCInst->arg_size()) + return nullptr; return *(GCInst->arg_begin() + getDerivedPtrIndex()); } -- 2.50.1