1# 2# CDDL HEADER START 3# 4# The contents of this file are subject to the terms of the 5# Common Development and Distribution License (the "License"). 6# You may not use this file except in compliance with the License. 7# 8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9# or http://www.opensolaris.org/os/licensing. 10# See the License for the specific language governing permissions 11# and limitations under the License. 12# 13# When distributing Covered Code, include this CDDL HEADER in each 14# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15# If applicable, add the following below this CDDL HEADER, with the 16# fields enclosed by brackets "[]" replaced with your own identifying 17# information: Portions Copyright [yyyy] [name of copyright owner] 18# 19# CDDL HEADER END 20# 21 22# 23# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24# 25 26# 27# Test whether CR #6766246 ("bug in pattern matching") has been fixed. 28# 29# Quote from CR #6766246: 30# ---- snip ---- 31# The bootstrap script of pkgsrc contains this code 32# checkarg_sane_absolute_path() { 33# case "$1" in 34# "") ;; # the default value will be used. 35# *[!-A-Za-z0-9_./]*) 36# die "ERROR: Invalid characters in path $1 (from $2)." ;; 37# /*) ;; 38# *) die "ERROR: The argument to $2 must be an absolute path." ;; 39# esac 40# } 41# It turns out, the leading "!" in the pattern is not interpreted 42# as negation, and the first "-" not as a literal. Instead the 43# character range "! to A" is constructed. Paths containing "%" 44# or "@" are accepted, but paths containing "-" are rejected. 45# Note that this interpretation makes the whole pattern 46# syntactically wrong, which isn't noticed either. 47# 48# Test case: 49# -- snip -- 50# !/bin/sh 51# case "$1" in 52# *[!-A-Za-z0-9_./]*) 53# echo invalid characters used in $1 54# ;; 55# *) 56# echo only valid characters used in $1 57# ;; 58# esac 59# -- snip -- 60# Expected Result: 61# strings containing a "-" should be accepted, strings containing 62# a "@" should be rejected 63# Actual Result: 64# strings containing a "-" are rejected, strings containing a 65# "@" are accepted 66# Workaround 67# The pattern "*[!A-Za-z0-9_./-]*" (i.e. shifting the dash to 68# the end) works as expected. 69# ---- snip ---- 70 71 72# test setup 73function err_exit 74{ 75 print -u2 -n "\t" 76 print -u2 -r ${Command}[$1]: "${@:2}" 77 (( Errors < 127 && Errors++ )) 78} 79alias err_exit='err_exit $LINENO' 80 81set -o nounset 82Command=${0##*/} 83integer Errors=0 84 85 86## test 1 (based on the bug report): 87 88function do_match 89{ 90 case "$1" in 91 *[!-A-Za-z0-9_./]*) 92 print "match" 93 ;; 94 *) 95 print "nomatch" 96 ;; 97 esac 98 return 0 99} 100 101typeset pat 102 103pat="foo-bar" ; [[ "$(do_match "${pat}")" == "nomatch" ]] || err_exit "${pat} matched." 104pat="foo+bar" ; [[ "$(do_match "${pat}")" == "match" ]] || err_exit "${pat} not matched." 105pat="foo/bar" ; [[ "$(do_match "${pat}")" == "nomatch" ]] || err_exit "${pat} matched." 106pat="foo_bar" ; [[ "$(do_match "${pat}")" == "nomatch" ]] || err_exit "${pat} matched." 107pat="foo@bar" ; [[ "$(do_match "${pat}")" == "match" ]] || err_exit "${pat} not matched." 108pat="foobar-" ; [[ "$(do_match "${pat}")" == "nomatch" ]] || err_exit "${pat} matched." 109pat="foobar+" ; [[ "$(do_match "${pat}")" == "match" ]] || err_exit "${pat} not matched." 110pat="foobar/" ; [[ "$(do_match "${pat}")" == "nomatch" ]] || err_exit "${pat} matched." 111pat="foobar_" ; [[ "$(do_match "${pat}")" == "nomatch" ]] || err_exit "${pat} matched." 112pat="foobar@" ; [[ "$(do_match "${pat}")" == "match" ]] || err_exit "${pat} not matched." 113pat="-foobar" ; [[ "$(do_match "${pat}")" == "nomatch" ]] || err_exit "${pat} matched." 114pat="+foobar" ; [[ "$(do_match "${pat}")" == "match" ]] || err_exit "${pat} not matched." 115pat="/foobar" ; [[ "$(do_match "${pat}")" == "nomatch" ]] || err_exit "${pat} matched." 116pat="_foobar" ; [[ "$(do_match "${pat}")" == "nomatch" ]] || err_exit "${pat} matched." 117pat="@foobar" ; [[ "$(do_match "${pat}")" == "match" ]] || err_exit "${pat} not matched." 118 119 120## test 2 (gsf's test chain): 121 122# Make sure LC_COLLATE has a value 123if [[ ! -v LC_COLLATE ]] ; then 124 if [[ -v LANG && ! -v LC_ALL ]]; then 125 LC_COLLATE="${LANG}" 126 fi 127fi 128 129if [[ -v LC_ALL ]] ; then 130 LC_COLLATE="${LC_ALL}" 131fi 132 133[[ -v LC_COLLATE ]] || LC_COLLATE=C 134 135set -- \ 136 'A' 0 1 1 0 1 1 1 0 0 1 0 0 \ 137 'Z' 0 1 1 0 1 1 1 0 0 1 0 0 \ 138 '/' 0 0 0 0 0 0 1 1 1 1 1 1 \ 139 '.' 0 0 0 0 0 0 1 1 1 1 1 1 \ 140 '_' 0 0 0 0 0 0 1 1 1 1 1 1 \ 141 '-' 1 1 1 1 1 1 0 0 0 0 0 0 \ 142 '%' 0 0 0 0 0 0 1 1 1 1 1 1 \ 143 '@' 0 0 0 0 0 0 1 1 1 1 1 1 \ 144 '!' 0 0 0 0 0 0 1 1 1 1 1 1 \ 145 '^' 0 0 0 0 0 0 1 1 1 1 1 1 \ 146 # retain this line # 147while (( $# >= 13 )) ; do 148 c=$1 149 shift 150 for p in \ 151 '[![.-.]]' \ 152 '[![.-.][:upper:]]' \ 153 '[![.-.]A-Z]' \ 154 '[!-]' \ 155 '[!-[:upper:]]' \ 156 '[!-A-Z]' \ 157 '[[.-.]]' \ 158 '[[.-.][:upper:]]' \ 159 '[[.-.]A-Z]' \ 160 '[-]' \ 161 '[-[:upper:]]' \ 162 '[-A-Z]' \ 163 # retain this line # 164 do e=$1 165 shift 166 [[ $c == $p ]] 167 g=$? 168 [[ $g == $e ]] || err_exit "[[ '$c' == $p ]] for LC_COLLATE=$l failed -- expected $e, got $g" 169 done 170done 171 172 173# tests done 174exit $((Errors)) 175