aboutsummaryrefslogtreecommitdiff
path: root/bin/sh
diff options
context:
space:
mode:
authorJilles Tjoelker <jilles@FreeBSD.org>2015-08-30 17:24:22 +0000
committerJilles Tjoelker <jilles@FreeBSD.org>2015-08-30 17:24:22 +0000
commitf0688a48d2dea18ba34187e36b4b87d37726c6b2 (patch)
tree0f3a0ac1582ca2ea6ce5982cda12d443823790d3 /bin/sh
parenta7fc139721129fd392d17215a623132eb86d8b69 (diff)
downloadsrc-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.c29
-rw-r--r--bin/sh/tests/builtins/Makefile1
-rw-r--r--bin/sh/tests/builtins/read9.010
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 ." ]