From: Elijah Newren Date: Tue, 21 Apr 2026 00:26:07 +0000 (+0000) Subject: merge-ort: propagate callback errors from traverse_trees_wrapper() X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=f7a69261db0f268de967919fa1b7a226571069a9;p=thirdparty%2Fgit.git merge-ort: propagate callback errors from traverse_trees_wrapper() traverse_trees_wrapper() saves entries from a first pass through traverse_trees() and then replays them through the real callback (collect_merge_info_callback). However, the replay loop silently discards the callback return value. This means any error reported by the callback during replay -- including a future check for malformed trees -- would be ignored, allowing the merge to proceed with corrupt state. Capture the return value, stop the loop on negative (error) returns, and propagate the error to the caller. Note that the callback returns a positive mask value on success, so we normalize non-negative returns to 0 for the caller. Signed-off-by: Elijah Newren Signed-off-by: Junio C Hamano --- diff --git a/merge-ort.c b/merge-ort.c index 00923ce3cd..4b8e32209d 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -1008,18 +1008,20 @@ static int traverse_trees_wrapper(struct index_state *istate, info->traverse_path = renames->callback_data_traverse_path; info->fn = old_fn; for (i = old_offset; i < renames->callback_data_nr; ++i) { - info->fn(n, - renames->callback_data[i].mask, - renames->callback_data[i].dirmask, - renames->callback_data[i].names, - info); + ret = info->fn(n, + renames->callback_data[i].mask, + renames->callback_data[i].dirmask, + renames->callback_data[i].names, + info); + if (ret < 0) + break; } renames->callback_data_nr = old_offset; free(renames->callback_data_traverse_path); renames->callback_data_traverse_path = old_callback_data_traverse_path; info->traverse_path = NULL; - return 0; + return ret < 0 ? ret : 0; } static void setup_path_info(struct merge_options *opt,