diff --git a/src/context.c b/src/context.c index 42f1eed..32053d1 100644 --- a/src/context.c +++ b/src/context.c @@ -403,10 +403,10 @@ find_hunk (struct change *start) lin thresh; /* Threshold distance is CONTEXT if the second change is ignorable, - 2 * CONTEXT + 1 otherwise. Watch out for integer overflow. */ - lin non_ignorable_threshold = - (LIN_MAX - 1) / 2 < context ? LIN_MAX : 2 * context + 1; + 2 * CONTEXT + 1 otherwise. Integer overflow can't happen, due + to CONTEXT_LIM. */ lin ignorable_threshold = context; + lin non_ignorable_threshold = 2 * context + 1; do { diff --git a/src/diff.c b/src/diff.c index 50d0365..c6ba5f6 100644 --- a/src/diff.c +++ b/src/diff.c @@ -304,11 +304,12 @@ main (int argc, char **argv) case '7': case '8': case '9': - if (! ISDIGIT (prev)) - ocontext = c - '0'; - else if (LIN_MAX / 10 < ocontext - || ((ocontext = 10 * ocontext + c - '0') < 0)) - ocontext = LIN_MAX; + ocontext = (! ISDIGIT (prev) + ? c - '0' + : (ocontext - (c - '0' <= CONTEXT_MAX % 10) + < CONTEXT_MAX / 10) + ? 10 * ocontext + (c - '0') + : CONTEXT_MAX); break; case 'a': @@ -337,8 +338,8 @@ main (int argc, char **argv) numval = strtoumax (optarg, &numend, 10); if (*numend) try_help ("invalid context length '%s'", optarg); - if (LIN_MAX < numval) - numval = LIN_MAX; + if (CONTEXT_MAX < numval) + numval = CONTEXT_MAX; } else numval = 3; diff --git a/src/sdiff.c b/src/sdiff.c index e7bc657..329fa52 100644 --- a/src/sdiff.c +++ b/src/sdiff.c @@ -1099,12 +1099,14 @@ interact (struct line_filter *diff, uintmax_t val; lin llen, rlen, lenmax; errno = 0; - llen = val = strtoumax (diff_help + 1, &numend, 10); - if (llen < 0 || llen != val || errno || *numend != ',') + val = strtoumax (diff_help + 1, &numend, 10); + if (LIN_MAX < val || errno || *numend != ',') fatal (diff_help); - rlen = val = strtoumax (numend + 1, &numend, 10); - if (rlen < 0 || rlen != val || errno || *numend) + llen = val; + val = strtoumax (numend + 1, &numend, 10); + if (LIN_MAX < val || errno || *numend) fatal (diff_help); + rlen = val; lenmax = MAX (llen, rlen); diff --git a/src/system.h b/src/system.h index f39fff0..1f81a72 100644 --- a/src/system.h +++ b/src/system.h @@ -135,6 +135,11 @@ typedef ptrdiff_t lin; verify (TYPE_SIGNED (lin)); verify (sizeof (ptrdiff_t) <= sizeof (lin)); verify (sizeof (lin) <= sizeof (long int)); + +/* Limit so that 2 * CONTEXT + 1 does not overflow. */ + +#define CONTEXT_MAX ((LIN_MAX - 1) / 2) + /* This section contains POSIX-compliant defaults for macros that are meant to be overridden by hand in config.h as needed. */