Configuration Information [Automatically generated, do not change]:
Machine: i386
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='i386' -DCONF_OSTYPE='linux-gnu' 
-DCONF_MACHTYPE='i386-pc-linux-gnu' -DCONF_VENDOR='pc' -DSHELL -DHAVE_CONFIG_H  
-D_FILE_OFFSET_BITS=64  -I. -I/usr/include 
-I/home/swt/doko/export/packages/bash/bash-2.04 
-I/home/swt/doko/export/packages/bash/bash-2.04/include 
-I/home/swt/doko/export/packages/bash/bash-2.04/lib -I/usr/include -g -O2
uname output: Linux nostromo 2.2.14 #1 Thu Jan 13 05:18:09 MST 2000 i686 unknown
Machine Type: i386-pc-linux-gnu

Bash Version: 2.04
Patch Level: 0
Release Status: beta5

Description:
Bash behaves incorrectly on

case "/tmp" in
  [/\\]*) exit 0;;
esac
exit 1

the problem is that fnmatch.c is buggy (details below in the ChangeLog
entry).

This bug is observed with 2.03 too, not tested with older bashes.

Repeat-By:
See above.

Fix:

--- ChangeLog~  Tue Mar 23 18:44:35 1993
+++ ChangeLog   Tue Mar 28 13:42:48 2000
@@ -1,3 +1,14 @@
+2000-03-28  Akim Demaille  <[EMAIL PROTECTED]>
+
+       fnmatch ("/tmp", "[/\\\\]*]") fails to match, because when the `/'
+       is matched, when brackmatch tries to skip the end of the
+       characters list, it misses one of the `\', hence skips `\]' and
+       then `*', and stops at `\0'.  Then it tries to fnmatch ("tmp", ""),
+       which fails.
+
+       * fnmatch.c (brackmatch) [matched]: Instead of trying to use the
+       current `c', just step back from one character in `p'.
+
 Thu Oct 29 08:58:12 1992  Brian Fox  (bfox@cubit)
 
        * glob.c (glob_filename): Fix tiny memory leak.  Rework some
--- fnmatch.c~  Wed Sep 22 22:31:02 1999
+++ fnmatch.c   Tue Mar 28 13:28:14 2000
@@ -4,17 +4,17 @@
 /* Copyright (C) 1991, 1997 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
-   
+
    Bash is free software; you can redistribute it and/or modify it under
    the terms of the GNU General Public License as published by the Free
    Software Foundation; either version 2, or (at your option) any later
    version.
-              
+
    Bash is distributed in the hope that it will be useful, but WITHOUT ANY
    WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.
-                         
+
    You should have received a copy of the GNU General Public License along
    with Bash; see the file COPYING.  If not, write to the Free Software
    Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
@@ -22,7 +22,7 @@
 #include <config.h>
 
 #include <stdio.h>     /* for debugging */
-                                
+
 #include "fnmatch.h"
 #include "collsyms.h"
 #include <ctype.h>
@@ -39,7 +39,7 @@
 static int extmatch ();
 static char *patscan ();
 #endif
-  
+
 #if !defined (isascii)
 #  define isascii(c)   ((unsigned int)(c) <= 0177)
 #endif
@@ -222,7 +222,7 @@
        case '*':               /* Match zero or more characters */
          if (p == pe)
            return 0;
-         
+
          if ((flags & FNM_PERIOD) && sc == '.' &&
              (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
            /* `*' cannot match a `.' if it is the first character of the
@@ -339,7 +339,7 @@
   if ((flags & FNM_LEADING_DIR) && *n == '/')
     /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
     return 0;
-          
+
   return (FNM_NOMATCH);
 }
 
@@ -355,7 +355,7 @@
   int val;
 
   p++;                         /* move past the `.' */
-          
+
   for (pc = 0; p[pc]; pc++)
     if (p[pc] == '.' && p[pc+1] == ']')
       break;
@@ -384,7 +384,7 @@
      circumflex (`^') in its role in a `nonmatching list'.  A bracket
      expression starging with an unquoted circumflex character produces
      unspecified results.  This implementation treats the two identically. */
-  if (not = (*p == '!' || *p == '^'))
+  if ((not = (*p == '!' || *p == '^')))
     ++p;
 
   c = *p++;
@@ -460,7 +460,7 @@
              continue;
            }
        }
- 
+
       /* POSIX.2 collating symbols.  See POSIX.2 2.8.3.2.  Find the end of
         the symbol name, make sure it is terminated by `.]', translate
         the name to a character using the external table, and do the
@@ -545,7 +545,8 @@
 
 matched:
   /* Skip the rest of the [...] that already matched.  */
-  brcnt = (c != ']') + (c == '[' && (*p == '=' || *p == ':' || *p == '.'));
+  c = *--p;
+  brcnt = 1;
   while (brcnt > 0)
     {
       /* A `[' without a matching `]' is just another character to match. */
@@ -759,13 +760,13 @@
            {
              pnext = patscan (psub, pe, '|');
              /* If one of the patterns matches, just bail immediately. */
-             if (m1 = (gmatch (s, srest, psub, pnext - 1, flags) == 0))
+             if ((m1 = (gmatch (s, srest, psub, pnext - 1, flags) == 0)))
                break;
              if (pnext == prest)
                break;
            }
          if (m1 == 0 && gmatch (srest, se, prest, pe, flags) == 0)
-           return (0); 
+           return (0);
        }
       return (FNM_NOMATCH);
     }


Comments:
I was wondering why the libc and bash don't share the same source for
fnmatch.  I can see there are extensions which are only in bash, but why
not moving them into glibc too?

        Akim

Reply via email to