diff, sdiff: minor integer overflow fixes

* src/context.c (find_hunk):
Simplify, now that 2 * context + 1 cannot overflow.
* src/diff.c (main):
* src/sdiff.c (interact):
Don't rely on undefined behavior on signed integer overflow.
* src/diff.c (main): Don't let contexts exceed CONTEXT_MAX.
* src/system.h (CONTEXT_MAX): New macro.
This commit is contained in:
Paul Eggert 2014-02-24 21:56:21 -08:00
parent c26334b7df
commit ed8975e7de
4 changed files with 22 additions and 14 deletions

View File

@ -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
{

View File

@ -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;

View File

@ -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);

View File

@ -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. */