From e7349844959391ad1cff39b1c256634de9130b60 Mon Sep 17 00:00:00 2001 From: Todd White Date: Sun, 28 Jun 2026 15:17:12 -0400 Subject: [PATCH] Fix imp_getBlock/imp_removeBlock for struct-return block IMPs When the IMP is not found in the regular trampoline set, both functions fall back to searching sret_trampolines but discarded the result of the second indexForIMP() call, leaving idx at -1. imp_getBlock therefore always returned NULL for a struct-return block IMP, and imp_removeBlock returned NO without releasing the block (a leak). Assign the second indexForIMP() result to idx. Extend Test/BlockImpTest.m to check imp_getBlock and imp_removeBlock on the struct-return IMP it already creates. --- Test/BlockImpTest.m | 5 +++++ block_to_imp.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Test/BlockImpTest.m b/Test/BlockImpTest.m index aa07499c..f16bc4e2 100644 --- a/Test/BlockImpTest.m +++ b/Test/BlockImpTest.m @@ -50,8 +50,11 @@ int main(void) struct big b = {1, 2, 3, 4, 5}; return b; }; + blk = Block_copy((blk)); imp = imp_implementationWithBlock(blk); assert(imp && "Can't make sret IMP"); + // imp_getBlock / imp_removeBlock must also work for struct-return blocks. + assert(imp_getBlock(imp) == blk); type = block_copyIMPTypeEncoding_np(blk); assert(NULL != type); class_addMethod((objc_getMetaClass("Foo")), @selector(sret), imp, type); @@ -62,5 +65,7 @@ int main(void) assert(s.c == 3); assert(s.d == 4); assert(s.e == 5); + imp_removeBlock(imp); + assert(imp_getBlock(imp) != blk); return 0; } diff --git a/block_to_imp.c b/block_to_imp.c index 7bba1467..94dea880 100644 --- a/block_to_imp.c +++ b/block_to_imp.c @@ -373,7 +373,7 @@ id imp_getBlock(IMP anImp) if (idx == -1) { set = sret_trampolines; - indexForIMP(anImp, &set); + idx = indexForIMP(anImp, &set); } if (idx == -1) { @@ -390,7 +390,7 @@ BOOL imp_removeBlock(IMP anImp) if (idx == -1) { set = sret_trampolines; - indexForIMP(anImp, &set); + idx = indexForIMP(anImp, &set); } if (idx == -1) {