Merge commit 9f85bc834b07 from llvm-project (by Nikita Popov):

[PPCMergeStringPool] Only replace constant once (#92996)

  In #88846 I changed this code to use RAUW to perform the replacement
  instead of manual updates -- but kept the outer loop, which means we try
  to perform RAUW once per user. However, some of the users might be freed
  by the RAUW operation, resulting in use-after-free.

  The case where this happens is constant users where the replacement
  might result in the destruction of the original constant.

  Fixes https://github.com/llvm/llvm-project/issues/92991.

This fixes a possible crash when building crypto/openssh/sshkey.c for
PowerPC targets.

Reported by:	cperciva
PR:		276104
MFC after:	3 days
This commit is contained in:
Dimitry Andric 2024-05-30 17:35:15 +02:00
parent ff7de3b4d3
commit f30188c468

View File

@ -290,13 +290,6 @@ bool PPCMergeStringPool::mergeModuleStringPool(Module &M) {
return true;
}
static bool userHasOperand(User *TheUser, GlobalVariable *GVOperand) {
for (Value *Op : TheUser->operands())
if (Op == GVOperand)
return true;
return false;
}
// For pooled strings we need to add the offset into the pool for each string.
// This is done by adding a Get Element Pointer (GEP) before each user. This
// function adds the GEP.
@ -307,29 +300,13 @@ void PPCMergeStringPool::replaceUsesWithGEP(GlobalVariable *GlobalToReplace,
Indices.push_back(ConstantInt::get(Type::getInt32Ty(*Context), 0));
Indices.push_back(ConstantInt::get(Type::getInt32Ty(*Context), ElementIndex));
// Need to save a temporary copy of each user list because we remove uses
// as we replace them.
SmallVector<User *> Users;
for (User *CurrentUser : GlobalToReplace->users())
Users.push_back(CurrentUser);
for (User *CurrentUser : Users) {
// The user was not found so it must have been replaced earlier.
if (!userHasOperand(CurrentUser, GlobalToReplace))
continue;
// We cannot replace operands in globals so we ignore those.
if (isa<GlobalValue>(CurrentUser))
continue;
Constant *ConstGEP = ConstantExpr::getInBoundsGetElementPtr(
PooledStructType, GPool, Indices);
LLVM_DEBUG(dbgs() << "Replacing this global:\n");
LLVM_DEBUG(GlobalToReplace->dump());
LLVM_DEBUG(dbgs() << "with this:\n");
LLVM_DEBUG(ConstGEP->dump());
GlobalToReplace->replaceAllUsesWith(ConstGEP);
}
Constant *ConstGEP =
ConstantExpr::getInBoundsGetElementPtr(PooledStructType, GPool, Indices);
LLVM_DEBUG(dbgs() << "Replacing this global:\n");
LLVM_DEBUG(GlobalToReplace->dump());
LLVM_DEBUG(dbgs() << "with this:\n");
LLVM_DEBUG(ConstGEP->dump());
GlobalToReplace->replaceAllUsesWith(ConstGEP);
}
} // namespace