From 4517e4ca104ca93b51b4acf4d2c62e9325bbb623 Mon Sep 17 00:00:00 2001 From: Michael Montalbo Date: Tue, 12 May 2026 18:10:22 +0000 Subject: [PATCH] xdiff: guard against negative context lengths The xdemitconf_t fields ctxlen and interhunkctxlen are typed as long (signed), but negative values are not meaningful for context line counts. Unlike the diff_options fields changed in the previous two commits, these cannot be converted to unsigned because the xdiff arithmetic relies on signed subtraction: s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0); If ctxlen were unsigned long, the signed operand would be implicitly converted to unsigned, and the subtraction would wrap to a large positive value when i1 < ctxlen, defeating the XDL_MAX clamp. The signed type is required for correct context-window calculations. The previous two commits reject negative values at the parse layer for --inter-hunk-context and -U/--unified, so negative values should no longer reach xdiff in normal use. Add BUG() guards at the top of xdl_get_hunk() as defense in depth to catch programming errors in current or future callers that bypass option parsing. xdl_get_hunk() is called by both xdl_emit_diff() and xdl_call_hunk_func(), so a single guard covers all xdiff consumers. Signed-off-by: Michael Montalbo Signed-off-by: Junio C Hamano --- xdiff/xemit.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/xdiff/xemit.c b/xdiff/xemit.c index 04f7e9193b..7cd9cf0a44 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -46,12 +46,20 @@ static long saturating_add(long a, long b) xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg) { xdchange_t *xch, *xchp, *lxch; - long max_common = saturating_add(saturating_add(xecfg->ctxlen, - xecfg->ctxlen), - xecfg->interhunkctxlen); - long max_ignorable = xecfg->ctxlen; + long max_common; + long max_ignorable; long ignored = 0; /* number of ignored blank lines */ + if (xecfg->ctxlen < 0) + BUG("negative context length: %ld", xecfg->ctxlen); + if (xecfg->interhunkctxlen < 0) + BUG("negative inter-hunk context length: %ld", xecfg->interhunkctxlen); + + max_common = saturating_add(saturating_add(xecfg->ctxlen, + xecfg->ctxlen), + xecfg->interhunkctxlen); + max_ignorable = xecfg->ctxlen; + /* remove ignorable changes that are too far before other changes */ for (xchp = *xscr; xchp && xchp->ignore; xchp = xchp->next) { xch = xchp->next;