aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CodeGenModule.cpp
diff options
context:
space:
mode:
authorlolloz98 <lorenzocarpaneto@yahoo.it>2024-05-21 19:51:21 +0100
committerGitHub <noreply@github.com>2024-05-21 11:51:21 -0700
commit67ae86d700b899979db39883f4063257513498d5 (patch)
tree915ce4d261f0d8e005aaccfb9e432fe20eb7de97 /clang/lib/CodeGen/CodeGenModule.cpp
parent8cb19ebd219668ef8efa9ffb4a72e39b18dd91d4 (diff)
downloadllvm-67ae86d700b899979db39883f4063257513498d5.zip
llvm-67ae86d700b899979db39883f4063257513498d5.tar.gz
llvm-67ae86d700b899979db39883f4063257513498d5.tar.bz2
[clang] Fix crash passing function pointer without prototype. (#90255)
Fixes use-after-free iterating over the uses of the function. Closes #88917
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp21
1 files changed, 14 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 227813a..60ef28a 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -5740,15 +5740,17 @@ CodeGenModule::getLLVMLinkageVarDefinition(const VarDecl *VD) {
static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
llvm::Function *newFn) {
// Fast path.
- if (old->use_empty()) return;
+ if (old->use_empty())
+ return;
llvm::Type *newRetTy = newFn->getReturnType();
- SmallVector<llvm::Value*, 4> newArgs;
+ SmallVector<llvm::Value *, 4> newArgs;
+
+ SmallVector<llvm::CallBase *> callSitesToBeRemovedFromParent;
for (llvm::Value::use_iterator ui = old->use_begin(), ue = old->use_end();
- ui != ue; ) {
- llvm::Value::use_iterator use = ui++; // Increment before the use is erased.
- llvm::User *user = use->getUser();
+ ui != ue; ui++) {
+ llvm::User *user = ui->getUser();
// Recognize and replace uses of bitcasts. Most calls to
// unprototyped functions will use bitcasts.
@@ -5760,8 +5762,9 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
// Recognize calls to the function.
llvm::CallBase *callSite = dyn_cast<llvm::CallBase>(user);
- if (!callSite) continue;
- if (!callSite->isCallee(&*use))
+ if (!callSite)
+ continue;
+ if (!callSite->isCallee(&*ui))
continue;
// If the return types don't match exactly, then we can't
@@ -5830,6 +5833,10 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
if (callSite->getDebugLoc())
newCall->setDebugLoc(callSite->getDebugLoc());
+ callSitesToBeRemovedFromParent.push_back(callSite);
+ }
+
+ for (auto *callSite : callSitesToBeRemovedFromParent) {
callSite->eraseFromParent();
}
}