Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/bin/sh Adjust tilde expansion as will be documented in the f...



details:   https://anonhg.NetBSD.org/src/rev/240b9e68de36
branches:  trunk
changeset: 373848:240b9e68de36
user:      kre <kre%NetBSD.org@localhost>
date:      Mon Mar 06 05:54:34 2023 +0000

description:
Adjust tilde expansion as will be documented in the forthcoming
version of the POSIX standard (Issue 8).   I believe we were already
compliant with what is to be required, but POSIX is now encouraging
(and will likely require in a later version) that if a tilde expansion
produces a string which ends in a '/' and the '~' that was expanded
is immediately followed by a '/' in the input word, that one of those
two slashes be omitted.   The worst (current) example of this is
when HOME=/ and we expand ~/foo - previously producing //foo which is
(in POSIX) a path with implementation defined semantics, and so not
what we should be generating by accident.   Change that, so now if
the ~ prefix expansion ends in a '/' and there is a '/' following
immediately after, the resulting word contains only one of those
chars (in the example just given, we will now produce /foo instead).

POSIX is also making it clear that the expansion that results from
the tilde expansion is treated as quoted (not subject to pathname
expansion, or field splitting, or any var/arith/command substitutions)
and that if HOME="" the expansion of ~ must generate "" (not nothing).
Our implementation did all of that already (though older versions
used to treat an empty expansion of HOME the same as if HOME was
unset - that was fixed some time ago).

The actual modification made here is probably smaller than this log entry,
and without added comments, certainly is!

diffstat:

 bin/sh/expand.c |  28 ++++++++++++++++++++++++----
 1 files changed, 24 insertions(+), 4 deletions(-)

diffs (64 lines):

diff -r ddb17f01a376 -r 240b9e68de36 bin/sh/expand.c
--- a/bin/sh/expand.c   Mon Mar 06 01:28:54 2023 +0000
+++ b/bin/sh/expand.c   Mon Mar 06 05:54:34 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: expand.c,v 1.141 2021/11/22 05:17:43 kre Exp $ */
+/*     $NetBSD: expand.c,v 1.142 2023/03/06 05:54:34 kre Exp $ */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)expand.c   8.5 (Berkeley) 5/15/95";
 #else
-__RCSID("$NetBSD: expand.c,v 1.141 2021/11/22 05:17:43 kre Exp $");
+__RCSID("$NetBSD: expand.c,v 1.142 2023/03/06 05:54:34 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -388,7 +388,7 @@
 STATIC const char *
 exptilde(const char *p, int flag)
 {
-       char c;
+       char c, last;
        const char *startp = p;
        struct passwd *pw;
        const char *home;
@@ -457,15 +457,35 @@
         * Posix XCU 2.6.1: The value of $HOME (for ~) or the initial
         *              working directory from getpwnam() for ~user
         * Nothing there about "except if a null string".  So do what it wants.
+        * In later drafts (to become Issue 8), it is even required that in
+        * this case, (where HOME='') a bare ~ expands to "" (which must not
+        * be reduced to nothing).
         */
-       if (home == NULL /* || *home == '\0' */) {
+       last = '\0';            /* just in case *home == '\0' (already) */
+       if (home == NULL) {
                CTRACE(DBG_EXPAND, (": returning unused \"%s\"\n", startp));
                return startp;
        } while ((c = *home++) != '\0') {
                if ((quotes && NEEDESC(c)) || ISCTL(c))
                        STPUTC(CTLESC, expdest);
                STPUTC(c, expdest);
+               last = c;
        }
+
+       /*
+        * If HOME (or whatver) ended in a '/' (last == '/'), and
+        * the ~prefix was terminated by a '/', then only keep one
+        * of them - since we already took the one from HOME, just
+        * skip over the one that ended the tilde prefix.
+        *
+        * Current (Issue 8) drafts say this is permitted, and recommend
+        * it - a later version of the standard will probably require it.
+        * This is to prevent ~/foo generating //foo when HOME=/ (and
+        * other cases like it, but that's the important one).
+        */
+       if (last == '/' && *p == '/')
+               p++;
+
        CTRACE(DBG_EXPAND, (": added %d \"%.*s\" returning \"%s\"\n",
              expdest - stackblock() - offs, expdest - stackblock() - offs,
              stackblock() + offs, p));



Home | Main Index | Thread Index | Old Index