From af0bd6ad70bbbf5ad188d270430d91ff6fa863c7 Mon Sep 17 00:00:00 2001 From: Johnothan King Date: Sun, 14 Jun 2020 09:28:22 -0700 Subject: [PATCH] `read -S` now correctly handles nested double quotes Prior to this bugfix, the following set of commands would fail to print two double quotes: IFS=',' read -S a b c <<<'foo,"""title"" data",bar' echo $b This fix is from ksh93v- 2013-10-10-alpha, although it has been revised to use stakputc to put the required double quote into the buffer for consistency with the ksh93u+ codebase. src/cmd/ksh93/bltins/read.c: - When handling nested double quotes, put the required double quote in read's buffer with stakputc. src/cmd/ksh93/tests/builtins.sh: - Add the regression test for `read -S` from ksh93v-. src/cmd/ksh93/sh.1: - Fix a minor formatting error to highlight '-S' in the ksh(1) man page. --- NEWS | 4 ++++ src/cmd/ksh93/bltins/read.c | 10 +++++++++- src/cmd/ksh93/include/version.h | 2 +- src/cmd/ksh93/sh.1 | 3 ++- src/cmd/ksh93/tests/builtins.sh | 5 +++++ 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index fca178f43..bfedb1360 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,10 @@ For full details, see the git log at: https://github.com/ksh93/ksh Any uppercase BUG_* names are modernish shell bug IDs. +2020-06-14: +- 'read -S' is now able to correctly handle strings with double quotes + nested inside of double quotes. + 2020-06-13: - Fixed a timezone name determination bug on FreeBSD that caused the diff --git a/src/cmd/ksh93/bltins/read.c b/src/cmd/ksh93/bltins/read.c index 2971af6a0..0f9c83a04 100644 --- a/src/cmd/ksh93/bltins/read.c +++ b/src/cmd/ksh93/bltins/read.c @@ -566,13 +566,21 @@ int sh_readline(register Shell_t *shp,char **names, volatile int fd, int flags,s #endif /*SHOPT_MULTIBYTE */ case S_QUOTE: c = shp->ifstable[*cp++]; - inquote = !inquote; + if(inquote && c==S_QUOTE) + c = -1; + else + inquote = !inquote; if(val) { stakputs(val); use_stak = 1; *val = 0; } + if(c==-1) + { + stakputc('"'); + c = shp->ifstable[*cp++]; + } continue; case S_ESC: /* process escape character */ diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index 3a34904ff..b0f3b9a70 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -17,4 +17,4 @@ * David Korn * * * ***********************************************************************/ -#define SH_RELEASE "93u+m 2020-06-11" +#define SH_RELEASE "93u+m 2020-06-14" diff --git a/src/cmd/ksh93/sh.1 b/src/cmd/ksh93/sh.1 index 960be0df7..e1bbd9105 100644 --- a/src/cmd/ksh93/sh.1 +++ b/src/cmd/ksh93/sh.1 @@ -6679,7 +6679,8 @@ option causes the variable .I vname\^ to be read as a compound variable. Blanks will be ignored when finding the beginning open parenthesis. -The \-S +The +.B \-S option causes the line to be treated like a record in a .B .csv format file so that double quotes can be used to allow the delimiter diff --git a/src/cmd/ksh93/tests/builtins.sh b/src/cmd/ksh93/tests/builtins.sh index e270a11d1..a4f732def 100755 --- a/src/cmd/ksh93/tests/builtins.sh +++ b/src/cmd/ksh93/tests/builtins.sh @@ -692,5 +692,10 @@ EOF PATH=/dev/null whence -q export) || err_exit '`builtin -d` deletes special builtins' +# ====== +# `read -S` should handle double quotes correctly +IFS=',' read -S a b c <<<'foo,"""title"" data",bar' +[[ $b == '"title" data' ]] || err_exit '"" inside "" not handled correctly with read -S' + # ====== exit $((Errors<125?Errors:125))