Subject: Re: bin/22846
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org, jmmv@menta.net>
From: Christian Biere <christianbiere@gmx.de>
List: netbsd-bugs
Date: 10/11/2006 06:10:02
The following reply was made to PR bin/22846; it has been noted by GNATS.

From: Christian Biere <christianbiere@gmx.de>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: bin/22846
Date: Wed, 11 Oct 2006 08:08:05 +0200

 Christian Biere wrote:
 > There's a way to convince ksh to expand filenames with brackets:
 > 
 > $ touch '[foo]'
 > $ touch '[bar]'
 > $ ls \[\[]f<tab>
 
 The reason this works is that x_file_glob() strips all backslashes,
 thus glob() will see [[]f whis is a literal '[f' as desired.
 
 The following partial patch fixes cases like the above but not
 those which require multiple tab completions:
 
  $ touch '[foo].bak'
  $ ls [f<tab>	# expands too \[foo\]
  $ ls \[foo\].<tab> # does not expand
 
 Obviously, due to the internal stripped backslashes [foo].<tab>
 won't expand because there is no matching file. However, even
 if the backslashes are kept, yylex() does record these as
 literal characters instead of marking the following character
 as quoted.
 
 The partial patch simply adds a check to see whether there
 is an unquoted '[' is followed by an unquoted ']'. If not,
 the '[' does not initiate a glob pattern.
 
 --- bin/ksh/edit.c	2006-10-08 05:29:36.000000000 +0200
 +++ bin/ksh/edit.c	2006-10-11 07:49:55.000000000 +0200
 @@ -880,7 +880,7 @@
  	for (s = toglob; *s; s++) {
  		if (*s == '\\' && s[1])
  			s++;
 -		else if (*s == '*' || *s == '[' || *s == '?' || *s == '$'
 +		else if (*s == '*' || *s == '?' || *s == '$'
  			 || (s[1] == '(' /*)*/ && strchr("*+?@!", *s)))
  			break;
  		else if (ISDIRSEP(*s))
 --- bin/ksh/eval.c	2006-05-23 16:45:10.000000000 +0200
 +++ bin/ksh/eval.c	2006-10-11 06:48:51.000000000 +0200
 @@ -605,6 +605,21 @@
  			if (!quote)
  				switch (c) {
  				  case '[':
 +					{
 +						const char *p = sp;
 +						bool_t special = FALSE;
 +						while (*p != EOS) {
 +							if (p[0] == CHAR &&
 +								p[1] == ']') {
 +								special = TRUE;
 +								break;
 +							}
 +								
 +							p += 2;
 +						}
 +						if (!special)
 +							break;
 +					}
  				  case NOT:
  				  case '-':
  				  case ']':