aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2023-02-12 08:57:15 +0000
committerRon Yorston <rmy@pobox.com>2023-02-12 08:57:15 +0000
commit0f2feac4b7e518e838b80d7b8ceac8f9699ae997 (patch)
tree8f65b2d8487c72d1b0ca034b4c50585939915953
parentd9916c6344c806696554115baa764eea09ca5f08 (diff)
downloadbusybox-w32-0f2feac4b7e518e838b80d7b8ceac8f9699ae997.tar.gz
busybox-w32-0f2feac4b7e518e838b80d7b8ceac8f9699ae997.tar.bz2
busybox-w32-0f2feac4b7e518e838b80d7b8ceac8f9699ae997.zip
ash: improve CRLF handling in read
Commit deae0c7bf3 (Skip carriage return in read builtin command) caused all CRs to be removed from input to the read builtin. Only remove CRs that are part of a CRLF pair. Adds 64-80 bytes. (GitHub issue #285)
-rw-r--r--shell/shell_common.c24
-rwxr-xr-xtestsuite/sh.tests16
2 files changed, 40 insertions, 0 deletions
diff --git a/shell/shell_common.c b/shell/shell_common.c
index c0dd32fb4..eb2c4fbf5 100644
--- a/shell/shell_common.c
+++ b/shell/shell_common.c
@@ -273,11 +273,35 @@ shell_builtin_read(struct builtin_read_params *params)
273 273
274 c = buffer[bufpos]; 274 c = buffer[bufpos];
275#if ENABLE_PLATFORM_MINGW32 275#if ENABLE_PLATFORM_MINGW32
276# if !ENABLE_ASH_IGNORE_CR
276 if (c == '\r') 277 if (c == '\r')
277 continue; 278 continue;
279# else
280 if (c == '\n') {
281 if (backslash == 2 || (bufpos > 0 && buffer[bufpos - 1] == '\r')) {
282 /* We saw either:
283 * - BS CR LF: remove CR, fall through to ignore escaped LF
284 * and exit BS context.
285 * - CR LF not in BS context: replace CR with LF */
286 buffer[--bufpos] = c;
287 ++nchars;
288 }
289 } else if (backslash == 2) {
290 /* We saw BS CR ??, keep escaped CR, exit BS context,
291 * process ?? */
292 backslash = 0;
293 }
294# endif
278#endif 295#endif
279 if (!(read_flags & BUILTIN_READ_RAW)) { 296 if (!(read_flags & BUILTIN_READ_RAW)) {
280 if (backslash) { 297 if (backslash) {
298#if ENABLE_ASH_IGNORE_CR
299 if (c == '\r') {
300 /* We have BS CR, keep CR for now, might see LF next */
301 backslash = 2;
302 goto put;
303 }
304#endif
281 backslash = 0; 305 backslash = 0;
282 if (c != '\n') 306 if (c != '\n')
283 goto put; 307 goto put;
diff --git a/testsuite/sh.tests b/testsuite/sh.tests
index 6fc3ca104..749d2dde2 100755
--- a/testsuite/sh.tests
+++ b/testsuite/sh.tests
@@ -97,4 +97,20 @@ testing "sh preserve lone CRs during field splitting" \
97 "sh input" \ 97 "sh input" \
98 "Hello\r world\n" "echo \$(printf \"Hello\\\\r\\\\r\\\\nworld\\\\r\\\\n\")" "" 98 "Hello\r world\n" "echo \$(printf \"Hello\\\\r\\\\r\\\\nworld\\\\r\\\\n\")" ""
99 99
100testing "sh read with CRLF" \
101 "printf '1 2\\r\\n' | { read var; printf \"\${var}\\\\n\"; }" \
102 "1 2\n" "" ""
103
104testing "sh read with CR" \
105 "printf '1\\r2\\r\\n' | { read var; printf \"\${var}\\\\n\"; }" \
106 "1\r2\n" "" ""
107
108testing "sh read with \\CRLF" \
109 "printf '1\\\\\r\\n2\\r\\n' | { read var; printf \"\${var}\\\\n\"; }" \
110 "12\n" "" ""
111
112testing "sh read with \\CR" \
113 "printf '1\\\\\r2\\r\\n' | { read var; printf \"\${var}\\\\n\"; }" \
114 "1\r2\n" "" ""
115
100exit $FAILCOUNT 116exit $FAILCOUNT