From e10c934d5a756c1a4c7b547ebd02c403ddfde7b8 Mon Sep 17 00:00:00 2001 From: GRAB Racem Date: Sat, 10 Oct 2026 01:36:11 +0200 Subject: [PATCH] fix(ghidra): keep the cross-format branch callee multi-block The cross-format oracle requires a callee whose recovered control flow has more than one basic block, and rea_cross_branch provided it through a symmetric if/else of tail calls. Clang 21 folds that shape into a conditional negate plus one tail branch, a single basic block, so the lane rejected a correct Ghidra analysis of the fixture. Give the branch a loop whose trip count depends on a volatile global: no compiler can eliminate the backedge, and the callee stays multi-block at every optimization level on every toolchain. --- tests/conformance/ghidra/cross-format.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/conformance/ghidra/cross-format.c b/tests/conformance/ghidra/cross-format.c index f718b9b54..22efa6159 100644 --- a/tests/conformance/ghidra/cross-format.c +++ b/tests/conformance/ghidra/cross-format.c @@ -8,10 +8,15 @@ __attribute__((noinline, used)) int rea_cross_leaf(int value) { } __attribute__((noinline, used)) int rea_cross_branch(int value) { - if (value > 10) { - return rea_cross_leaf(value); + /* A volatile-dependent loop keeps this callee multi-block at every + optimization level: newer clang folds a symmetric if/else of tail calls + into a conditional negate, and cross-format verification requires a + recovered multi-block callee. */ + int adjusted = value > 10 ? value + 1 : -value; + while (adjusted > 100) { + adjusted -= rea_cross_global; } - return rea_cross_leaf(-value); + return rea_cross_leaf(adjusted); } __attribute__((noinline, used)) int rea_cross_indirect(