From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10353 invoked by alias); 21 Aug 2015 08:57:31 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 36262 Received: (qmail 29978 invoked from network); 21 Aug 2015 08:57:29 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.0 X-AuditID: cbfec7f4-f79c56d0000012ee-fc-55d6e7f3580b Date: Fri, 21 Aug 2015 09:57:21 +0100 From: Peter Stephenson To: Zsh hackers list Subject: Re: mkdir builtin and $'\0' Message-id: <20150821095721.5790de94@pwslap01u.europe.root.pri> In-reply-to: References: <20150818091904.GA5389@chaz.gmail.com> <20150818162040.GC5629@chaz.gmail.com> <20150818173726.02ef5782@pwslap01u.europe.root.pri> Organization: Samsung Cambridge Solution Centre X-Mailer: Claws Mail 3.7.9 (GTK+ 2.22.0; i386-redhat-linux-gnu) MIME-version: 1.0 Content-type: text/plain; charset=UTF-8 Content-transfer-encoding: quoted-printable X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrCLMWRmVeSWpSXmKPExsVy+t/xy7qfn18LNVhzUdfiYPNDJgdGj1UH PzAFMEZx2aSk5mSWpRbp2yVwZZy79Ymx4Jtsxc1l+xgbGH+KdTFycEgImEh0TSntYuQEMsUk Ltxbz9bFyMUhJLCUUWLWvjksEM4MJom3lx6yQzjbGCUmzb7FCNLCIqAqMXPGfWYQm03AUGLq ptlgcREBLYkdJ08ygdjCAioSLxs72EBsXgF7iXXtV9lBbE6BYIm/v6axQgy9wSixZcFjVpAE v4C+xNW/n5ggbrKXmHnlDCNEs6DEj8n3WEBsZgF1iUnzFjFD2NoST95dAOsVAorfuLubfQKj 0CwkLbOQtMxC0rKAkXkVo2hqaXJBcVJ6rqFecWJucWleul5yfu4mRkjYftnBuPiY1SFGAQ5G JR7eGZHXQoVYE8uKK3MPMUpwMCuJ8Ao+BgrxpiRWVqUW5ccXleakFh9ilOZgURLnnbvrfYiQ QHpiSWp2ampBahFMlomDU6qBcbZq75sF6ivbdkbKaCtZfk2Xvsu5P6xYoVCy2vih9vsrZ9nY GFddufJyjZT+57bC3nkLb8o5fi5S4Ltu9uHg1lVz5u2fLf9m/07fHzcZZcI/l9aszWUWVV/x kTmnJ6eRLW+Bk+DvzcX/TE/xaSyLyY78MylnjYphbVouW53Sv/1trnO0/b6EK7EUZyQaajEX FScCADyp1yVXAgAA On Fri, 21 Aug 2015 08:20:55 +0200 Mikael Magnusson wrote: > % mkdir /tmp/=E3=83=9B > % cd /tmp/=E3=83=9B > cd: no such file or directory: /tmp/=E3=83=9B > % cd /tmp > % cd =E3=83=9B > % pwd > /tmp/=E3=83=9B > % echo =E3=83=9B|xxd > 00000000: e383 9b0a >=20 > Do we have inconsistent metafication in this string somehow? Yes --- it appears by tracing system calls everything is unmetafied but null terminated up to lchdir(). The culprit for the case Stephane saw was the second of a pair of lchdir() calls, where there's a string that needs unmetafying, while you're hitting the first, which is raw. I think this fixes both cases. I think we weren't seeing this before because Stephane's case is actually quite unusual --- we failed to changed directory normally because it doesn't exist, and only then hit the second lchdir(). There are a couple of remaining lchdir() calls in glob.c. I haven't determined whether the arguments are already unmetafied or not. (Er, this is if people think we really need to fix up little-used builtins of this sort... mmm....) pws diff --git a/Src/builtin.c b/Src/builtin.c index 572a0dd..3d34aa7 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -1163,7 +1163,7 @@ cd_try_chdir(char *pfix, char *dest, int hard) * or a parent directory is renamed in the interim. */ if (lchdir(buf, NULL, hard) && - (pfix || *dest =3D=3D '/' || lchdir(dest, NULL, hard))) { + (pfix || *dest =3D=3D '/' || lchdir(unmeta(dest), NULL, hard))) { free(buf); return NULL; } diff --git a/Src/compat.c b/Src/compat.c index a0ce182..db46852 100644 --- a/Src/compat.c +++ b/Src/compat.c @@ -454,8 +454,13 @@ zgetcwd(void) return ret; } =20 -/* chdir with arbitrary long pathname. Returns 0 on success, -1 on normal= * - * failure and -2 when chdir failed and the current directory is lost. */ +/* + * chdir with arbitrary long pathname. Returns 0 on success, -1 on normal= * + * failure and -2 when chdir failed and the current directory is lost. + * + * This is to be treated as if at system level, so dir is unmetafied but + * terminated by a NULL. + */ =20 /**/ mod_export int @@ -465,7 +470,7 @@ zchdir(char *dir) int currdir =3D -2; =20 for (;;) { - if (!*dir || chdir(unmeta(dir)) =3D=3D 0) { + if (!*dir || chdir(dir) =3D=3D 0) { #ifdef HAVE_FCHDIR if (currdir >=3D 0) close(currdir); diff --git a/Src/utils.c b/Src/utils.c index 20e01a2..4c4dc55 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -6440,10 +6440,15 @@ init_dirsav(Dirsav d) d->dirfd =3D d->level =3D -1; } =20 -/* Change directory, without following symlinks. Returns 0 on success, -1= * - * on failure. Sets errno to ENOTDIR if any symlinks are encountered. If= * - * fchdir() fails, or the current directory is unreadable, we might end up= * - * in an unwanted directory in case of failure. = */ +/* + * Change directory, without following symlinks. Returns 0 on success, -1 + * on failure. Sets errno to ENOTDIR if any symlinks are encountered. If + * fchdir() fails, or the current directory is unreadable, we might end up + * in an unwanted directory in case of failure. + * + * path is an unmetafied but null-terminated string, as needed by system + * calls. + */ =20 /**/ mod_export int diff --git a/Test/D07multibyte.ztst b/Test/D07multibyte.ztst index 644d280..0e3e98d 100644 --- a/Test/D07multibyte.ztst +++ b/Test/D07multibyte.ztst @@ -496,3 +496,15 @@ >OK >OK >OK + + () { + emulate -L zsh + setopt errreturn + local cdpath=3D(.) + mkdir =E3=83=9B + cd =E3=83=9B + cd .. + cd ./=E3=83=9B + cd .. + } +0:cd with special characters