From owner-svn-src-all@FreeBSD.ORG Sat Jul 3 21:06:48 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C0ABA1065672; Sat, 3 Jul 2010 21:06:48 +0000 (UTC) (envelope-from jilles@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id AEE358FC13; Sat, 3 Jul 2010 21:06:48 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o63L6mBp025641; Sat, 3 Jul 2010 21:06:48 GMT (envelope-from jilles@svn.freebsd.org) Received: (from jilles@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o63L6m8O025638; Sat, 3 Jul 2010 21:06:48 GMT (envelope-from jilles@svn.freebsd.org) Message-Id: <201007032106.o63L6m8O025638@svn.freebsd.org> From: Jilles Tjoelker Date: Sat, 3 Jul 2010 21:06:48 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r209675 - in stable/7: bin/sh tools/regression/bin/sh/expansion X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 03 Jul 2010 21:06:48 -0000 Author: jilles Date: Sat Jul 3 21:06:48 2010 New Revision: 209675 URL: http://svn.freebsd.org/changeset/base/209675 Log: MFC r207944: sh: Fix pathname expansion with quoted slashes like *\/. These are git commits 36f0fa8fcbc8c7b2b194addd29100fb40e73e4e9 and d6d06ff5c2ea0fa44becc5ef4340e5f2f15073e4 in dash. Because this is the first code I'm importing from dash to expand.c, add the Herbert Xu copyright notice which is in dash's expand.c. When pathname expanding *\/, the CTLESC representing the quoted state was erroneously taken as part of the * pathname component. This CTLESC was then seen by the pattern matching code as escaping the '\0' terminating the string. The code is slightly different because dash converts the CTLESC characters to backslashes and removes all the other CTL* characters to allow substituting glob(3). The effect of the bug was also slightly different from dash (where nothing matched at all). Because a CTLESC can escape a '\0' in some way, whether files were included despite the bug depended on memory that should not be read. In particular, on many machines /*\/ expanded to a strict subset of what /*/ expanded to. Example: echo /*"/null" This should print /dev/null, not /*/null. PR: bin/146378 Obtained from: dash Added: stable/7/tools/regression/bin/sh/expansion/ stable/7/tools/regression/bin/sh/expansion/pathname2.0 - copied unchanged from r207944, head/tools/regression/bin/sh/expansion/pathname2.0 Modified: stable/7/bin/sh/expand.c Directory Properties: stable/7/bin/sh/ (props changed) stable/7/tools/regression/bin/sh/ (props changed) Modified: stable/7/bin/sh/expand.c ============================================================================== --- stable/7/bin/sh/expand.c Sat Jul 3 21:02:11 2010 (r209674) +++ stable/7/bin/sh/expand.c Sat Jul 3 21:06:48 2010 (r209675) @@ -1,6 +1,8 @@ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. + * Copyright (c) 1997-2005 + * Herbert Xu . All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. @@ -1122,10 +1124,11 @@ expmeta(char *enddir, char *name) struct dirent *dp; int atend; int matchdot; + int esc; metaflag = 0; start = name; - for (p = name ; ; p++) { + for (p = name; esc = 0, *p; p += esc + 1) { if (*p == '*' || *p == '?') metaflag = 1; else if (*p == '[') { @@ -1150,12 +1153,14 @@ expmeta(char *enddir, char *name) break; else if (*p == CTLQUOTEMARK) continue; - else if (*p == CTLESC) - p++; - if (*p == '/') { - if (metaflag) - break; - start = p + 1; + else { + if (*p == CTLESC) + esc++; + if (p[esc] == '/') { + if (metaflag) + break; + start = p + esc + 1; + } } } if (metaflag == 0) { /* we've reached the end of the file name */ @@ -1201,7 +1206,8 @@ expmeta(char *enddir, char *name) atend = 1; } else { atend = 0; - *endname++ = '\0'; + *endname = '\0'; + endname += esc + 1; } matchdot = 0; p = start; @@ -1229,7 +1235,7 @@ expmeta(char *enddir, char *name) } closedir(dirp); if (! atend) - endname[-1] = '/'; + endname[-esc - 1] = esc ? CTLESC : '/'; } Copied: stable/7/tools/regression/bin/sh/expansion/pathname2.0 (from r207944, head/tools/regression/bin/sh/expansion/pathname2.0) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/7/tools/regression/bin/sh/expansion/pathname2.0 Sat Jul 3 21:06:48 2010 (r209675, copy of r207944, head/tools/regression/bin/sh/expansion/pathname2.0) @@ -0,0 +1,31 @@ +# $FreeBSD$ + +failures=0 + +check() { + testcase=$1 + expect=$2 + eval "set -- $testcase" + actual="$*" + if [ "$actual" != "$expect" ]; then + failures=$((failures+1)) + printf '%s\n' "For $testcase, expected $expect actual $actual" + fi +} + +set -e +T=$(mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXX) +trap 'rm -rf $T' 0 +cd -P $T + +mkdir testdir testdir2 'testdir/*' 'testdir/?' testdir/a testdir/b testdir2/b +mkdir testdir2/.c +touch testf 'testdir/*/1' 'testdir/?/1' testdir/a/1 testdir/b/1 testdir2/b/.a + +check '*\/' 'testdir/ testdir2/' +check '"testdir/"*"/1"' 'testdir/*/1 testdir/?/1 testdir/a/1 testdir/b/1' +check '"testdir/"*"/"*' 'testdir/*/1 testdir/?/1 testdir/a/1 testdir/b/1' +check '"testdir/"*\/*' 'testdir/*/1 testdir/?/1 testdir/a/1 testdir/b/1' +check '"testdir"*"/"*"/"*' 'testdir/*/1 testdir/?/1 testdir/a/1 testdir/b/1' + +exit $((failures != 0))