diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2014-10-27 19:53:08 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2014-10-27 19:53:44 -0700 |
commit | 1fa6140faacb29e44f2d666c74529ed27b0abb5a (patch) | |
tree | dcda5e1e92c94b6c5ec76365a1b540069ab64ca7 | |
parent | df3af29627a92495a740da13cb8bb0d4fcc1bf84 (diff) | |
download | diffutils-1fa6140faacb29e44f2d666c74529ed27b0abb5a.tar.gz |
diff: fix integer overflow problem with --tabsize
Reported by Tobias Stoeckmann in: http://bugs.gnu.org/18857
* src/diff.c (main): Don't overflow if INTMAX_MAX / 2 < tabsize.
* tests/bignum: New file, to test for this bug.
* tests/Makefile.am (TESTS): Add it.
-rw-r--r-- | src/diff.c | 15 | ||||
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rwxr-xr-x | tests/bignum | 14 |
3 files changed, 25 insertions, 5 deletions
@@ -595,7 +595,8 @@ main (int argc, char **argv) case TABSIZE_OPTION: numval = strtoumax (optarg, &numend, 10); - if (! (0 < numval && numval <= SIZE_MAX) || *numend) + if (! (0 < numval && numval <= SIZE_MAX - GUTTER_WIDTH_MINIMUM) + || *numend) try_help ("invalid tabsize '%s'", optarg); if (tabsize != numval) { @@ -682,10 +683,14 @@ main (int argc, char **argv) a half line plus a gutter is an integral number of tabs, so that tabs in the right column line up. */ - intmax_t t = expand_tabs ? 1 : tabsize; - intmax_t w = width; - intmax_t off = (w + t + GUTTER_WIDTH_MINIMUM) / (2 * t) * t; - sdiff_half_width = MAX (0, MIN (off - GUTTER_WIDTH_MINIMUM, w - off)), + size_t t = expand_tabs ? 1 : tabsize; + size_t w = width; + size_t t_plus_g = t + GUTTER_WIDTH_MINIMUM; + size_t unaligned_off = (w >> 1) + (t_plus_g >> 1) + (w & t_plus_g & 1); + size_t off = unaligned_off - unaligned_off % t; + sdiff_half_width = (off <= GUTTER_WIDTH_MINIMUM || w <= off + ? 0 + : MIN (off - GUTTER_WIDTH_MINIMUM, w - off)); sdiff_column2_offset = sdiff_half_width ? off : w; } diff --git a/tests/Makefile.am b/tests/Makefile.am index 005d9f0..438fbdf 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -2,6 +2,7 @@ TESTS = \ basic \ + bignum \ binary \ colliding-file-names \ excess-slash \ diff --git a/tests/bignum b/tests/bignum new file mode 100755 index 0000000..a0c95f6 --- /dev/null +++ b/tests/bignum @@ -0,0 +1,14 @@ +#!/bin/sh +# big numbers + +. "${srcdir=.}/init.sh"; path_prepend_ ../src + +fail=0 + +for tabsize in 2147483648 9223372036854775808; do + diff --tabsize=$tabsize /dev/null /dev/null + status=$? + test $status -eq 0 || test $status -eq 2 || fail=1 +done + +Exit $fail |