Author: jilles
Date: Sun Aug 30 17:24:22 2015
New Revision: 287308
URL: https://svnweb.freebsd.org/changeset/base/287308

Log:
  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.

Added:
  head/bin/sh/tests/builtins/read9.0   (contents, props changed)
Modified:
  head/bin/sh/miscbltin.c
  head/bin/sh/tests/builtins/Makefile

Modified: head/bin/sh/miscbltin.c
==============================================================================
--- head/bin/sh/miscbltin.c     Sun Aug 30 16:10:12 2015        (r287307)
+++ head/bin/sh/miscbltin.c     Sun Aug 30 17:24:22 2015        (r287308)
@@ -100,6 +100,7 @@ readcmd(int argc __unused, char **argv _
        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 _
        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 _
                        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 _
                        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 _
                        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 _
                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 _
                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 "" */

Modified: head/bin/sh/tests/builtins/Makefile
==============================================================================
--- head/bin/sh/tests/builtins/Makefile Sun Aug 30 16:10:12 2015        
(r287307)
+++ head/bin/sh/tests/builtins/Makefile Sun Aug 30 17:24:22 2015        
(r287308)
@@ -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

Added: head/bin/sh/tests/builtins/read9.0
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/bin/sh/tests/builtins/read9.0  Sun Aug 30 17:24:22 2015        
(r287308)
@@ -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 ." ]
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to