Skip to content

Commit 67ae86d

Browse files
authored
[clang] Fix crash passing function pointer without prototype. (#90255)
Fixes use-after-free iterating over the uses of the function. Closes #88917
1 parent 8cb19eb commit 67ae86d

File tree

2 files changed

+26
-7
lines changed

2 files changed

+26
-7
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5740,15 +5740,17 @@ CodeGenModule::getLLVMLinkageVarDefinition(const VarDecl *VD) {
57405740
static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
57415741
llvm::Function *newFn) {
57425742
// Fast path.
5743-
if (old->use_empty()) return;
5743+
if (old->use_empty())
5744+
return;
57445745

57455746
llvm::Type *newRetTy = newFn->getReturnType();
5746-
SmallVector<llvm::Value*, 4> newArgs;
5747+
SmallVector<llvm::Value *, 4> newArgs;
5748+
5749+
SmallVector<llvm::CallBase *> callSitesToBeRemovedFromParent;
57475750

57485751
for (llvm::Value::use_iterator ui = old->use_begin(), ue = old->use_end();
5749-
ui != ue; ) {
5750-
llvm::Value::use_iterator use = ui++; // Increment before the use is erased.
5751-
llvm::User *user = use->getUser();
5752+
ui != ue; ui++) {
5753+
llvm::User *user = ui->getUser();
57525754

57535755
// Recognize and replace uses of bitcasts. Most calls to
57545756
// unprototyped functions will use bitcasts.
@@ -5760,8 +5762,9 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
57605762

57615763
// Recognize calls to the function.
57625764
llvm::CallBase *callSite = dyn_cast<llvm::CallBase>(user);
5763-
if (!callSite) continue;
5764-
if (!callSite->isCallee(&*use))
5765+
if (!callSite)
5766+
continue;
5767+
if (!callSite->isCallee(&*ui))
57655768
continue;
57665769

57675770
// If the return types don't match exactly, then we can't
@@ -5830,6 +5833,10 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
58305833
if (callSite->getDebugLoc())
58315834
newCall->setDebugLoc(callSite->getDebugLoc());
58325835

5836+
callSitesToBeRemovedFromParent.push_back(callSite);
5837+
}
5838+
5839+
for (auto *callSite : callSitesToBeRemovedFromParent) {
58335840
callSite->eraseFromParent();
58345841
}
58355842
}

clang/test/CodeGen/functions.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,15 @@ static void test9_helper(void) {}
6161
void test9(void) {
6262
(void) test9_helper;
6363
}
64+
65+
// PR88917: don't crash
66+
int b();
67+
68+
int main() {
69+
return b(b);
70+
// CHECK: call i32 @b(ptr noundef @b)
71+
}
72+
int b(int (*f)()){
73+
return 0;
74+
}
75+
// CHECK-LABEL: define{{.*}} i32 @b(ptr noundef %f)

0 commit comments

Comments
 (0)