diff --git a/NEWS b/NEWS index f93196d..64ecaf1 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,10 @@ GNU diffutils NEWS -*- outline -*- cp /proc/cmdline t; cmp -s /proc/cmdline t || echo files differ [bug present since "the beginning"] + diff -E no longer mishandles some input lines containing '\a', '\b', + '\f', '\r', '\v', or '\0'. + [bug present since 2.8] + diff -ly no longer mishandles non-ASCII input [bug#64461 introduced in 2.9] diff --git a/src/io.c b/src/io.c index c56c479..e879c18 100644 --- a/src/io.c +++ b/src/io.c @@ -292,7 +292,7 @@ find_and_hash_each_line (struct file_data *current) case IGNORE_TAB_EXPANSION_AND_TRAILING_SPACE: case IGNORE_TRAILING_SPACE: { - intmax_t column = 0; + intmax_t tab = 0, column = 0; for (unsigned char c; (c = *p++) != '\n'; ) { if (ig_white_space & IGNORE_TRAILING_SPACE @@ -318,19 +318,29 @@ find_and_hash_each_line (struct file_data *current) switch (c) { case '\b': - column = (column ? column : tabsize) - 1; + if (0 < column) + column--; + else if (0 < tab) + { + tab--; + column = tabsize - 1; + } break; case '\t': c = ' '; repetitions = tabsize - column % tabsize; + tab += column / tabsize + 1; column = 0; break; case '\r': - column = 0; + tab = column = 0; break; + case '\0': case '\a': case '\f': case '\v': + break; + default: column++; break; diff --git a/src/util.c b/src/util.c index c1c8660..69d3bc4 100644 --- a/src/util.c +++ b/src/util.c @@ -1212,14 +1212,38 @@ lines_differ (char const *s1, char const *s2) if (c1 != c2) break; } - if (c1 == '\n') - return false; - column++; - if (c1 == '\t' || column == tabsize) + switch (c1) { + case '\n': + return false; + + case '\r': + tab = column = 0; + break; + + case '\b': + if (0 < column) + column--; + else if (0 < tab) + { + tab--; + column = tabsize - 1; + } + break; + + case '\0': case '\a': case '\f': case '\v': + break; + + default: + column++; + if (column < tabsize) + break; + FALLTHROUGH; + case '\t': tab++; column = 0; + break; } } diff --git a/tests/Makefile.am b/tests/Makefile.am index 5eb725a..75d8f06 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -16,6 +16,7 @@ TESTS = \ invalid-re \ function-line-vs-leading-space \ ignore-matching-lines \ + ignore-tab-expansion \ label-vs-func \ large-subopt \ new-file \ diff --git a/tests/ignore-tab-expansion b/tests/ignore-tab-expansion new file mode 100755 index 0000000..194bf0c --- /dev/null +++ b/tests/ignore-tab-expansion @@ -0,0 +1,16 @@ +#!/bin/sh +# Test ignoring tab expansion. + +. "${srcdir=.}/init.sh"; path_prepend_ ../src + +fail=0 + +for p in '\b' '\r' '\t ' '\n'; do + printf "$p"'\b\tx\n' >a || framework_failure_ + printf "$p"'\b x\n' >b || framework_failure + + diff -E a b >out || fail=1 + compare /dev/null out || fail=1 +done + +Exit $fail