diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2018-12-28 19:00:50 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2018-12-28 19:08:16 -0800 |
commit | f8780039532cebb4f4580af1ef7c7d9019080157 (patch) | |
tree | 2b4090b4561e190ffc6914c71248a80ffb2a102c | |
parent | 15668f2c54d095b872cd06d78adde5a525a583e8 (diff) | |
download | diffutils-f8780039532cebb4f4580af1ef7c7d9019080157.tar.gz |
diff: fix UMR with --strip-trailing-cr
Problem reported by Hongxu Chen (Bug#31935).
* src/io.c (prepare_text): Strip trailing CR before
doing the rest of the analysis.
* NEWS: Mention the fix.
Co-authored-by: Jim Meyering <jim@meyering.net>
-rw-r--r-- | NEWS | 7 | ||||
-rw-r--r-- | src/io.c | 39 |
2 files changed, 22 insertions, 24 deletions
@@ -2,6 +2,13 @@ GNU diffutils NEWS -*- outline -*- * Noteworthy changes in release ?.? (????-??-??) [?] +** Bug fixes + + diff --strip-trailing-cr with a single CR byte in one input file + would provoke an uninitialized memory read, e.g., + diff -a --strip-trailing-cr <(printf '\r') <(echo a) + [bug introduced in 2.8 with addition of the --strip-trailing-cr option] + * Noteworthy changes in release 3.6 (2017-05-21) [stable] @@ -481,42 +481,33 @@ prepare_text (struct file_data *current) { size_t buffered = current->buffered; char *p = FILE_BUFFER (current); - - if (buffered == 0 || p[buffered - 1] == '\n') - current->missing_newline = false; - else - { - p[buffered++] = '\n'; - current->missing_newline = true; - } - if (!p) return; - /* Don't use uninitialized storage when planting or using sentinels. */ - memset (p + buffered, 0, sizeof (word)); - if (strip_trailing_cr) { - char *dst; char *srclim = p + buffered; *srclim = '\r'; - dst = rawmemchr (p, '\r'); + char *dst = rawmemchr (p, '\r'); - if (dst != srclim) + for (char const *src = dst; src != srclim; src++) { - char const *src = dst; - do - { - *dst = *src++; - dst += ! (*dst == '\r' && *src == '\n'); - } - while (src < srclim); - - buffered -= src - dst; + src += *src == '\r' && src[1] == '\n'; + *dst++ = *src; } + + buffered -= srclim - dst; } + if (buffered != 0 && p[buffered - 1] != '\n') + { + p[buffered++] = '\n'; + current->missing_newline = true; + } + + /* Don't use uninitialized storage when planting or using sentinels. */ + memset (p + buffered, 0, sizeof (word)); + current->buffered = buffered; } |