Skip to content

Commit f9cfa0c

Browse files
committed
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 <mmontalbo@gmail.com>
1 parent f0478d4 commit f9cfa0c

1 file changed

Lines changed: 12 additions & 4 deletions

File tree

xdiff/xemit.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,20 @@ static long saturating_add(long a, long b)
4646
xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg)
4747
{
4848
xdchange_t *xch, *xchp, *lxch;
49-
long max_common = saturating_add(saturating_add(xecfg->ctxlen,
50-
xecfg->ctxlen),
51-
xecfg->interhunkctxlen);
52-
long max_ignorable = xecfg->ctxlen;
49+
long max_common;
50+
long max_ignorable;
5351
long ignored = 0; /* number of ignored blank lines */
5452

53+
if (xecfg->ctxlen < 0)
54+
BUG("negative context length: %ld", xecfg->ctxlen);
55+
if (xecfg->interhunkctxlen < 0)
56+
BUG("negative inter-hunk context length: %ld", xecfg->interhunkctxlen);
57+
58+
max_common = saturating_add(saturating_add(xecfg->ctxlen,
59+
xecfg->ctxlen),
60+
xecfg->interhunkctxlen);
61+
max_ignorable = xecfg->ctxlen;
62+
5563
/* remove ignorable changes that are too far before other changes */
5664
for (xchp = *xscr; xchp && xchp->ignore; xchp = xchp->next) {
5765
xch = xchp->next;

0 commit comments

Comments
 (0)