summaryrefslogtreecommitdiff
path: root/usr/src/lib/libshell/common
diff options
context:
space:
mode:
authorCasper H.S. Dik <Casper.Dik@Sun.COM>2009-02-25 22:02:17 +0100
committerCasper H.S. Dik <Casper.Dik@Sun.COM>2009-02-25 22:02:17 +0100
commit9a6f360e750e0b14fc9b9bf8347e0ebad3959e3f (patch)
tree546322f102ab545a1f74e81db4da0e3d1c1b8ebf /usr/src/lib/libshell/common
parentcb1fa6c94ff0f7012e6629be31b7c18de21dde79 (diff)
downloadillumos-joyent-9a6f360e750e0b14fc9b9bf8347e0ebad3959e3f.tar.gz
6807179 ksh93 does unneccesary|libc::getpwnam()|lookups for ~(modifier)pattern patterns
Contributed by Roland Mainz <roland.mainz@nrubsig.org>
Diffstat (limited to 'usr/src/lib/libshell/common')
-rw-r--r--usr/src/lib/libshell/common/sh/macro.c2
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6807179_shellpattern_uses_getpwnam.sh89
2 files changed, 90 insertions, 1 deletions
diff --git a/usr/src/lib/libshell/common/sh/macro.c b/usr/src/lib/libshell/common/sh/macro.c
index 7b1ab77b48..cb938764d6 100644
--- a/usr/src/lib/libshell/common/sh/macro.c
+++ b/usr/src/lib/libshell/common/sh/macro.c
@@ -439,7 +439,7 @@ static void copyto(register Mac_t *mp,int endch, int newquote)
mp->sp = NIL(Sfio_t*);
mp->quote = newquote;
first = cp = fcseek(0);
- if(!mp->quote && *cp=='~')
+ if(!mp->quote && *cp=='~' && cp[1]!=LPAREN)
tilde = stktell(stkp);
/* handle // operator specially */
if(mp->pattern==2 && *cp=='/')
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6807179_shellpattern_uses_getpwnam.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6807179_shellpattern_uses_getpwnam.sh
new file mode 100644
index 0000000000..3e65edbfae
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6807179_shellpattern_uses_getpwnam.sh
@@ -0,0 +1,89 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test checks whether ksh93 does unneccesaty |libc::getpwnam()|
+# calls for "~(modifer)pattern"-style shell patterns
+#
+# This was reported as CR #6807179 ("ksh93 does unneccesary |libc::getpwnam()| lookups for ~(modifier) pattern patterns"):
+# ------------ snip ------------
+# ksh93 does unneccesary |libc::getpwnam()| lookups for
+# ~(modifer)pattern patterns, e.g. [[ $foo == ~(E)hello.*world ]].
+# The problem is that the shell ~(modifer)pattern is an extended
+# pattern syntax which allows to specify a "modifer" to change
+# the behaviour for "pattern". However the '~' at the beginning
+# of this string is causing a tilde expansion (or better: It's
+# filling an internal buffer as preparation for tilde expansion
+# and this code calls |libc::getpwnam()|) which shouldn't be
+# done in this case.
+# [1]=For example the "modifer" allows to specifcy "perl",
+# "fgrep", "grep", "egrep", "POSIX shell", "korn shell" and
+# other types of pattern matching systems (or select stuff
+# like archors, case-insensitive matching etc. etc.).
+# ------------ snip ------------
+#
+
+# test setup
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+typeset tmpfile
+
+tmpfile="$(mktemp "/tmp/sun_solaris_cr_6807179_shellpattern_uses_getpwnam.${PPID}.$$.XXXXXX")" || err_exit "Cannot create temporary file."
+rm -f "${tmpfile}"
+
+
+# test 1: Check if the shell uses |libc::getpwnam()| for pattern "~(Elr)wo.*ld"
+truss -u :: -o "${tmpfile}" ${SHELL} -c '[[ ${hello} == ~(Elr)wo.*ld ]] ; true' || err_exit "truss returned failure=$?"
+[[ "$( < "${tmpfile}")" != *getpwnam* ]] || err_exit "truss log reports the use of getpwnam() for pattern ~(Elr)wo.*ld"
+rm "${tmpfile}" || err_exit "rm ${tmpfile} failed."
+
+
+# test 2: Check if the shell uses |libc::getpwnam()| for pattern "~(Si)wo*ld"
+truss -u :: -o "${tmpfile}" ${SHELL} -c '[[ ${hello} == ~(Si)wo*ld ]] ; true' || err_exit "truss returned failure=$?"
+[[ "$( < "${tmpfile}")" != *getpwnam* ]] || err_exit "truss log reports the use of getpwnam() for pattern ~(Si)wo*ld"
+rm "${tmpfile}" || err_exit "rm ${tmpfile} failed."
+
+
+# test 3: Same as test 1 but uses ~root/ as pattern which will force the use of |libc::getpwnam()|
+getent passwd root >/dev/null || err_exit "getent passwd root failed" # safeguard to make sure we get a warning if user root is missing
+
+truss -u :: -o "${tmpfile}" ${SHELL} -c '[[ ${hello} == ~root/ ]] ; true' || err_exit "truss returned failure=$?"
+[[ "$( < "${tmpfile}" )" == *getpwnam* ]] || err_exit "truss log reports the use of getpwnam() for pattern ~root/"
+rm "${tmpfile}" || err_exit "rm ${tmpfile} failed."
+
+
+# tests done
+exit $((Errors))