diff options
author | Jilles Tjoelker <jilles@FreeBSD.org> | 2015-08-30 17:24:22 +0000 |
---|---|---|
committer | Jilles Tjoelker <jilles@FreeBSD.org> | 2015-08-30 17:24:22 +0000 |
commit | f0688a48d2dea18ba34187e36b4b87d37726c6b2 (patch) | |
tree | 0f3a0ac1582ca2ea6ce5982cda12d443823790d3 /bin/sh | |
parent | a7fc139721129fd392d17215a623132eb86d8b69 (diff) | |
download | src-f0688a48d2dea18ba34187e36b4b87d37726c6b2.tar.gz src-f0688a48d2dea18ba34187e36b4b87d37726c6b2.zip |
sh: Fix read with escaped IFS characters at the end.
Characters escaped with a backslash must be treated as if they were not in
IFS. This includes stripping trailing IFS characters.
Notes
Notes:
svn path=/head/; revision=287308
Diffstat (limited to 'bin/sh')
-rw-r--r-- | bin/sh/miscbltin.c | 29 | ||||
-rw-r--r-- | bin/sh/tests/builtins/Makefile | 1 | ||||
-rw-r--r-- | bin/sh/tests/builtins/read9.0 | 10 |
3 files changed, 28 insertions, 12 deletions
diff --git a/bin/sh/miscbltin.c b/bin/sh/miscbltin.c index 4575e966295d..4de12760b54e 100644 --- a/bin/sh/miscbltin.c +++ b/bin/sh/miscbltin.c @@ -100,6 +100,7 @@ readcmd(int argc __unused, char **argv __unused) int i; int is_ifs; int saveall = 0; + ptrdiff_t lastnonifs, lastnonifsws; struct timeval tv; char *tvptr; fd_set ifds; @@ -169,6 +170,7 @@ readcmd(int argc __unused, char **argv __unused) startword = 2; backslash = 0; STARTSTACKSTR(p); + lastnonifs = lastnonifsws = -1; for (;;) { nread = read(STDIN_FILENO, &c, 1); if (nread == -1) { @@ -193,6 +195,7 @@ readcmd(int argc __unused, char **argv __unused) backslash = 0; if (c != '\n') { startword = 0; + lastnonifs = lastnonifsws = p - stackblock(); USTPUTC(c, p); } continue; @@ -218,8 +221,10 @@ readcmd(int argc __unused, char **argv __unused) if (is_ifs == 2 && startword == 1) { /* Only one non-whitespace IFS per word */ startword = 2; - if (saveall) + if (saveall) { + lastnonifsws = p - stackblock(); USTPUTC(c, p); + } continue; } } @@ -230,6 +235,7 @@ readcmd(int argc __unused, char **argv __unused) if (saveall) /* Not just a spare terminator */ saveall++; + lastnonifs = lastnonifsws = p - stackblock(); USTPUTC(c, p); continue; } @@ -240,6 +246,8 @@ readcmd(int argc __unused, char **argv __unused) if (ap[1] == NULL) { /* Last variable needs all IFS chars */ saveall++; + if (is_ifs == 2) + lastnonifsws = p - stackblock(); USTPUTC(c, p); continue; } @@ -248,20 +256,17 @@ readcmd(int argc __unused, char **argv __unused) setvar(*ap, stackblock(), 0); ap++; STARTSTACKSTR(p); + lastnonifs = lastnonifsws = -1; } STACKSTRNUL(p); - /* Remove trailing IFS chars */ - for (; stackblock() <= --p; *p = 0) { - if (!strchr(ifs, *p)) - break; - if (strchr(" \t\n", *p)) - /* Always remove whitespace */ - continue; - if (saveall > 1) - /* Don't remove non-whitespace unless it was naked */ - break; - } + /* + * Remove trailing IFS chars: always remove whitespace, don't remove + * non-whitespace unless it was naked + */ + if (saveall <= 1) + lastnonifsws = lastnonifs; + stackblock()[lastnonifsws + 1] = '\0'; setvar(*ap, stackblock(), 0); /* Set any remaining args to "" */ diff --git a/bin/sh/tests/builtins/Makefile b/bin/sh/tests/builtins/Makefile index c1e7b6416e4f..46a0b4159a1a 100644 --- a/bin/sh/tests/builtins/Makefile +++ b/bin/sh/tests/builtins/Makefile @@ -123,6 +123,7 @@ FILES+= read5.0 FILES+= read6.0 FILES+= read7.0 FILES+= read8.0 +FILES+= read9.0 FILES+= return1.0 FILES+= return2.1 FILES+= return3.1 diff --git a/bin/sh/tests/builtins/read9.0 b/bin/sh/tests/builtins/read9.0 new file mode 100644 index 000000000000..080549889839 --- /dev/null +++ b/bin/sh/tests/builtins/read9.0 @@ -0,0 +1,10 @@ +# $FreeBSD$ + +empty='' +read a b c <<EOF +\ \ A B\ \ B C\ \ $empty +EOF +read d e <<EOF +D\ $empty +EOF +[ "$a.$b.$c.$d.$e" = " A.B B.C .D ." ] |