diff options
author | jilles <jilles@FreeBSD.org> | 2015-08-30 17:24:22 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2015-08-30 17:24:22 +0000 |
commit | 1fb3e6c2bbcb782830c7fbc531a699b852dd84e0 (patch) | |
tree | 0f3a0ac1582ca2ea6ce5982cda12d443823790d3 /bin/sh | |
parent | f96bce47a48837f8ca605ef4c44822a8fa8b15e2 (diff) | |
download | FreeBSD-src-1fb3e6c2bbcb782830c7fbc531a699b852dd84e0.zip FreeBSD-src-1fb3e6c2bbcb782830c7fbc531a699b852dd84e0.tar.gz |
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.
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 4575e96..4de1276 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 c1e7b64..46a0b41 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 0000000..0805498 --- /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 ." ] |