Author: madcoder Date: 2007-04-15 00:45:03 +0000 (Sun, 15 Apr 2007) New Revision: 2068
Added: glibc-package/trunk/debian/patches/any/cvs-glob-c.diff Modified: glibc-package/trunk/debian/changelog glibc-package/trunk/debian/patches/series Log: Closes: #234880 (glob) * patches/any/cvs-glob-c.diff: fixes glob wrt \/ escapes (among other fixes). Closes: #234880. Signed-off-by: Pierre Habouzit <[EMAIL PROTECTED]> Modified: glibc-package/trunk/debian/changelog =================================================================== --- glibc-package/trunk/debian/changelog 2007-04-14 23:48:38 UTC (rev 2067) +++ glibc-package/trunk/debian/changelog 2007-04-15 00:45:03 UTC (rev 2068) @@ -2,6 +2,8 @@ * patches/any/submitted-unistd_XOPEN_VERSION.diff: set _XOPEN_VERSION to 600 when __USE_XOPEN2K is set. Closes: #203412. + * patches/any/cvs-glob-c.diff: fixes glob wrt \/ escapes (among other + fixes). Closes: #234880. -- Pierre Habouzit <[EMAIL PROTECTED]> Sun, 15 Apr 2007 01:46:38 +0200 Added: glibc-package/trunk/debian/patches/any/cvs-glob-c.diff =================================================================== --- glibc-package/trunk/debian/patches/any/cvs-glob-c.diff 2007-04-14 23:48:38 UTC (rev 2067) +++ glibc-package/trunk/debian/patches/any/cvs-glob-c.diff 2007-04-15 00:45:03 UTC (rev 2068) @@ -0,0 +1,586 @@ +=================================================================== +RCS file: /cvs/glibc/libc/posix/glob.c,v +retrieving revision 1.72 +retrieving revision 1.73 +Index: glibc-2.5/posix/glob.c +=================================================================== +--- glibc-2.5.orig/posix/glob.c 2007-04-13 13:31:26.629689784 +0200 ++++ glibc-2.5/posix/glob.c 2007-04-15 02:43:02.147008076 +0200 +@@ -1,4 +1,5 @@ +-/* Copyright (C) 1991-2002,2003,2004,2005,2006 Free Software Foundation, Inc. ++/* Copyright (C) 1991-2002, 2003, 2004, 2005, 2006, 2007 ++ Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -192,9 +193,15 @@ + + #endif /* !defined _LIBC || !defined GLOB_ONLY_P */ + ++#ifndef attribute_hidden ++# define attribute_hidden ++#endif ++ + static int glob_in_dir (const char *pattern, const char *directory, + int flags, int (*errfunc) (const char *, int), + glob_t *pglob); ++extern int __glob_pattern_type (const char *pattern, int quote) ++ attribute_hidden; + + #if !defined _LIBC || !defined GLOB_ONLY_P + static int prefix_array (const char *prefix, char **array, size_t n) __THROW; +@@ -250,6 +257,9 @@ + size_t dirlen; + int status; + size_t oldcount; ++ int meta; ++ int dirname_modified; ++ glob_t dirs; + + if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) + { +@@ -418,6 +428,7 @@ + if (filename == NULL) + filename = strchr (pattern, ':'); + #endif /* __MSDOS__ || WINDOWS32 */ ++ dirname_modified = 0; + if (filename == NULL) + { + /* This can mean two things: a simple name or "~name". The latter +@@ -486,10 +497,32 @@ + && dirlen > 1) + /* "pattern/". Expand "pattern", appending slashes. */ + { ++ int orig_flags = flags; ++ if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\') ++ { ++ /* "pattern\\/". Remove the final backslash if it hasn't ++ been quoted. */ ++ char *p = (char *) &dirname[dirlen - 1]; ++ ++ while (p > dirname && p[-1] == '\\') --p; ++ if ((&dirname[dirlen] - p) & 1) ++ { ++ *(char *) &dirname[--dirlen] = '\0'; ++ flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC); ++ } ++ } + int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob); + if (val == 0) + pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) + | (flags & GLOB_MARK)); ++ else if (val == GLOB_NOMATCH && flags != orig_flags) ++ { ++ /* Make sure globfree (&dirs); is a nop. */ ++ dirs.gl_pathv = NULL; ++ flags = orig_flags; ++ oldcount = pglob->gl_pathc + pglob->gl_offs; ++ goto no_matches; ++ } + return val; + } + } +@@ -517,7 +550,9 @@ + #ifndef VMS + if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~') + { +- if (dirname[1] == '\0' || dirname[1] == '/') ++ if (dirname[1] == '\0' || dirname[1] == '/' ++ || (!(flags & GLOB_NOESCAPE) && dirname[1] == '\\' ++ && (dirname[2] == '\0' || dirname[2] == '/'))) + { + /* Look up home directory. */ + const char *home_dir = getenv ("HOME"); +@@ -594,7 +629,10 @@ + # endif + /* Now construct the full directory. */ + if (dirname[1] == '\0') +- dirname = home_dir; ++ { ++ dirname = home_dir; ++ dirlen = strlen (dirname); ++ } + else + { + char *newp; +@@ -603,7 +641,9 @@ + mempcpy (mempcpy (newp, home_dir, home_len), + &dirname[1], dirlen); + dirname = newp; ++ dirlen += home_len - 1; + } ++ dirname_modified = 1; + } + # if !defined _AMIGA && !defined WINDOWS32 + else +@@ -611,15 +651,52 @@ + char *end_name = strchr (dirname, '/'); + const char *user_name; + const char *home_dir; ++ char *unescape = NULL; + ++ if (!(flags & GLOB_NOESCAPE)) ++ { ++ if (end_name == NULL) ++ { ++ unescape = strchr (dirname, '\\'); ++ if (unescape) ++ end_name = strchr (unescape, '\0'); ++ } ++ else ++ unescape = memchr (dirname, '\\', end_name - dirname); ++ } + if (end_name == NULL) + user_name = dirname + 1; + else + { + char *newp; + newp = (char *) __alloca (end_name - dirname); +- *((char *) mempcpy (newp, dirname + 1, end_name - dirname)) +- = '\0'; ++ if (unescape != NULL) ++ { ++ char *p = mempcpy (newp, dirname + 1, ++ unescape - dirname - 1); ++ char *q = unescape; ++ while (*q != '\0') ++ { ++ if (*q == '\\') ++ { ++ if (q[1] == '\0') ++ { ++ /* "~fo\\o\\" unescape to user_name "foo\\", ++ but "~fo\\o\\/" unescape to user_name ++ "foo". */ ++ if (filename == NULL) ++ *p++ = '\\'; ++ break; ++ } ++ ++q; ++ } ++ *p++ = *q++; ++ } ++ *p = '\0'; ++ } ++ else ++ *((char *) mempcpy (newp, dirname + 1, end_name - dirname)) ++ = '\0'; + user_name = newp; + } + +@@ -673,6 +750,8 @@ + *((char *) mempcpy (mempcpy (newp, home_dir, home_len), + end_name, rest_len)) = '\0'; + dirname = newp; ++ dirlen = home_len + rest_len; ++ dirname_modified = 1; + } + else + if (flags & GLOB_TILDE_CHECK) +@@ -714,9 +793,22 @@ + } + pglob->gl_pathv = new_gl_pathv; + +- pglob->gl_pathv[newcount] = strdup (dirname); +- if (pglob->gl_pathv[newcount] == NULL) +- goto nospace; ++ if (flags & GLOB_MARK) ++ { ++ char *p; ++ pglob->gl_pathv[newcount] = malloc (dirlen + 2); ++ if (pglob->gl_pathv[newcount] == NULL) ++ goto nospace; ++ p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen); ++ p[0] = '/'; ++ p[1] = '\0'; ++ } ++ else ++ { ++ pglob->gl_pathv[newcount] = strdup (dirname); ++ if (pglob->gl_pathv[newcount] == NULL) ++ goto nospace; ++ } + pglob->gl_pathv[++newcount] = NULL; + ++pglob->gl_pathc; + pglob->gl_flags = flags; +@@ -728,14 +820,30 @@ + return GLOB_NOMATCH; + } + +- if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE))) ++ meta = __glob_pattern_type (dirname, !(flags & GLOB_NOESCAPE)); ++ /* meta is 1 if correct glob pattern containing metacharacters. ++ If meta has bit (1 << 2) set, it means there was an unterminated ++ [ which we handle the same, using fnmatch. Broken unterminated ++ pattern bracket expressions ought to be rare enough that it is ++ not worth special casing them, fnmatch will do the right thing. */ ++ if (meta & 5) + { + /* The directory name contains metacharacters, so we + have to glob for the directory, and then glob for + the pattern in each directory found. */ +- glob_t dirs; + size_t i; + ++ if (!(flags & GLOB_NOESCAPE) && dirlen > 0 && dirname[dirlen - 1] == '\\') ++ { ++ /* "foo\\/bar". Remove the final backslash from dirname ++ if it has not been quoted. */ ++ char *p = (char *) &dirname[dirlen - 1]; ++ ++ while (p > dirname && p[-1] == '\\') --p; ++ if ((&dirname[dirlen] - p) & 1) ++ *(char *) &dirname[--dirlen] = '\0'; ++ } ++ + if ((flags & GLOB_ALTDIRFUNC) != 0) + { + /* Use the alternative access functions also in the recursive +@@ -748,12 +856,16 @@ + } + + status = glob (dirname, +- ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE ++ ((flags & (GLOB_ERR | GLOB_NOESCAPE + | GLOB_ALTDIRFUNC)) + | GLOB_NOSORT | GLOB_ONLYDIR), + errfunc, &dirs); + if (status != 0) +- return status; ++ { ++ if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH) ++ return status; ++ goto no_matches; ++ } + + /* We have successfully globbed the preceding directory name. + For each name we found, call glob_in_dir on it and FILENAME, +@@ -811,6 +923,7 @@ + flag was set we must return the input pattern itself. */ + if (pglob->gl_pathc + pglob->gl_offs == oldcount) + { ++ no_matches: + /* No matches. */ + if (flags & GLOB_NOCHECK) + { +@@ -854,10 +967,44 @@ + else + { + int old_pathc = pglob->gl_pathc; ++ int orig_flags = flags; + ++ if (meta & 2) ++ { ++ char *p = strchr (dirname, '\\'), *q; ++ /* We need to unescape the dirname string. It is certainly ++ allocated by alloca, as otherwise filename would be NULL ++ or dirname wouldn't contain backslashes. */ ++ q = p; ++ do ++ { ++ if (*p == '\\') ++ { ++ *q = *++p; ++ --dirlen; ++ } ++ else ++ *q = *p; ++ ++q; ++ } ++ while (*p++ != '\0'); ++ dirname_modified = 1; ++ } ++ if (dirname_modified) ++ flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC); + status = glob_in_dir (filename, dirname, flags, errfunc, pglob); + if (status != 0) +- return status; ++ { ++ if (status == GLOB_NOMATCH && flags != orig_flags ++ && pglob->gl_pathc + pglob->gl_offs == oldcount) ++ { ++ /* Make sure globfree (&dirs); is a nop. */ ++ dirs.gl_pathv = NULL; ++ flags = orig_flags; ++ goto no_matches; ++ } ++ return status; ++ } + + if (dirlen > 0) + { +@@ -1015,15 +1162,13 @@ + + /* We must not compile this function twice. */ + #if !defined _LIBC || !defined NO_GLOB_PATTERN_P +-/* Return nonzero if PATTERN contains any metacharacters. +- Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ + int +-__glob_pattern_p (pattern, quote) ++__glob_pattern_type (pattern, quote) + const char *pattern; + int quote; + { + register const char *p; +- int open = 0; ++ int ret = 0; + + for (p = pattern; *p != '\0'; ++p) + switch (*p) +@@ -1033,21 +1178,35 @@ + return 1; + + case '\\': +- if (quote && p[1] != '\0') +- ++p; ++ if (quote) ++ { ++ if (p[1] != '\0') ++ ++p; ++ ret |= 2; ++ } + break; + + case '[': +- open = 1; ++ ret |= 4; + break; + + case ']': +- if (open) ++ if (ret & 4) + return 1; + break; + } + +- return 0; ++ return ret; ++} ++ ++/* Return nonzero if PATTERN contains any metacharacters. ++ Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ ++int ++__glob_pattern_p (pattern, quote) ++ const char *pattern; ++ int quote; ++{ ++ return __glob_pattern_type (pattern, quote) == 1; + } + # ifdef _LIBC + weak_alias (__glob_pattern_p, glob_pattern_p) +@@ -1109,7 +1268,7 @@ + init_names.next = NULL; + init_names.count = INITIAL_COUNT; + +- meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)); ++ meta = __glob_pattern_type (pattern, !(flags & GLOB_NOESCAPE)); + if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) + { + /* We need not do any tests. The PATTERN contains no meta +@@ -1117,8 +1276,7 @@ + result will always contain exactly one name. */ + flags |= GLOB_NOCHECK; + } +- else if (meta == 0 && +- ((flags & GLOB_NOESCAPE) || strchr (pattern, '\\') == NULL)) ++ else if (meta == 0) + { + /* Since we use the normal file functions we can also use stat() + to verify the file is there. */ +@@ -1139,119 +1297,104 @@ + } + else + { +- if (pattern[0] == '\0') ++ stream = ((flags & GLOB_ALTDIRFUNC) ++ ? (*pglob->gl_opendir) (directory) ++ : opendir (directory)); ++ if (stream == NULL) + { +- /* This is a special case for matching directories like in +- "*a/". */ +- names->name[cur] = (char *) malloc (1); +- if (names->name[cur] == NULL) +- goto memory_error; +- *names->name[cur++] = '\0'; +- nfound = 1; +- meta = 0; ++ if (errno != ENOTDIR ++ && ((errfunc != NULL && (*errfunc) (directory, errno)) ++ || (flags & GLOB_ERR))) ++ return GLOB_ABORTED; + } + else + { +- stream = ((flags & GLOB_ALTDIRFUNC) +- ? (*pglob->gl_opendir) (directory) +- : opendir (directory)); +- if (stream == NULL) +- { +- if (errno != ENOTDIR +- && ((errfunc != NULL && (*errfunc) (directory, errno)) +- || (flags & GLOB_ERR))) +- return GLOB_ABORTED; +- meta = 0; +- } +- else +- { +- int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) +- | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) ++ int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) ++ | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) + #if defined _AMIGA || defined VMS +- | FNM_CASEFOLD ++ | FNM_CASEFOLD + #endif +- ); +- flags |= GLOB_MAGCHAR; ++ ); ++ flags |= GLOB_MAGCHAR; + +- while (1) +- { +- const char *name; +- size_t len; ++ while (1) ++ { ++ const char *name; ++ size_t len; + #if defined _LIBC && !defined COMPILE_GLOB64 +- struct dirent64 *d; +- union +- { +- struct dirent64 d64; +- char room [offsetof (struct dirent64, d_name[0]) +- + NAME_MAX + 1]; +- } +- d64buf; ++ struct dirent64 *d; ++ union ++ { ++ struct dirent64 d64; ++ char room [offsetof (struct dirent64, d_name[0]) ++ + NAME_MAX + 1]; ++ } ++ d64buf; + +- if (flags & GLOB_ALTDIRFUNC) ++ if (flags & GLOB_ALTDIRFUNC) ++ { ++ struct dirent *d32 = (*pglob->gl_readdir) (stream); ++ if (d32 != NULL) + { +- struct dirent *d32 = (*pglob->gl_readdir) (stream); +- if (d32 != NULL) +- { +- CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32); +- d = &d64buf.d64; +- } +- else +- d = NULL; ++ CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32); ++ d = &d64buf.d64; + } + else +- d = __readdir64 (stream); ++ d = NULL; ++ } ++ else ++ d = __readdir64 (stream); + #else +- struct dirent *d = ((flags & GLOB_ALTDIRFUNC) +- ? ((struct dirent *) +- (*pglob->gl_readdir) (stream)) +- : __readdir (stream)); ++ struct dirent *d = ((flags & GLOB_ALTDIRFUNC) ++ ? ((struct dirent *) ++ (*pglob->gl_readdir) (stream)) ++ : __readdir (stream)); + #endif +- if (d == NULL) +- break; +- if (! REAL_DIR_ENTRY (d)) +- continue; ++ if (d == NULL) ++ break; ++ if (! REAL_DIR_ENTRY (d)) ++ continue; + +- /* If we shall match only directories use the information +- provided by the dirent call if possible. */ +- if ((flags & GLOB_ONLYDIR) && !DIRENT_MIGHT_BE_DIR (d)) +- continue; ++ /* If we shall match only directories use the information ++ provided by the dirent call if possible. */ ++ if ((flags & GLOB_ONLYDIR) && !DIRENT_MIGHT_BE_DIR (d)) ++ continue; + +- name = d->d_name; ++ name = d->d_name; + +- if (fnmatch (pattern, name, fnm_flags) == 0) ++ if (fnmatch (pattern, name, fnm_flags) == 0) ++ { ++ /* If the file we found is a symlink we have to ++ make sure the target file exists. */ ++ if (!DIRENT_MIGHT_BE_SYMLINK (d) ++ || link_exists_p (directory, dirlen, name, pglob, ++ flags)) + { +- /* If the file we found is a symlink we have to +- make sure the target file exists. */ +- if (!DIRENT_MIGHT_BE_SYMLINK (d) +- || link_exists_p (directory, dirlen, name, pglob, +- flags)) ++ if (cur == names->count) + { +- if (cur == names->count) +- { +- struct globnames *newnames; +- size_t count = names->count * 2; +- size_t size = (sizeof (struct globnames) +- + ((count - INITIAL_COUNT) +- * sizeof (char *))); +- allocasize += size; +- if (__libc_use_alloca (allocasize)) +- newnames = names_alloca = __alloca (size); +- else if ((newnames = malloc (size)) +- == NULL) +- goto memory_error; +- newnames->count = count; +- newnames->next = names; +- names = newnames; +- cur = 0; +- } +- len = NAMLEN (d); +- names->name[cur] = (char *) malloc (len + 1); +- if (names->name[cur] == NULL) ++ struct globnames *newnames; ++ size_t count = names->count * 2; ++ size_t size = (sizeof (struct globnames) ++ + ((count - INITIAL_COUNT) ++ * sizeof (char *))); ++ allocasize += size; ++ if (__libc_use_alloca (allocasize)) ++ newnames = names_alloca = __alloca (size); ++ else if ((newnames = malloc (size)) ++ == NULL) + goto memory_error; +- *((char *) mempcpy (names->name[cur++], name, len)) +- = '\0'; +- ++nfound; ++ newnames->count = count; ++ newnames->next = names; ++ names = newnames; ++ cur = 0; + } ++ len = NAMLEN (d); ++ names->name[cur] = (char *) malloc (len + 1); ++ if (names->name[cur] == NULL) ++ goto memory_error; ++ *((char *) mempcpy (names->name[cur++], name, len)) ++ = '\0'; ++ ++nfound; + } + } + } Modified: glibc-package/trunk/debian/patches/series =================================================================== --- glibc-package/trunk/debian/patches/series 2007-04-14 23:48:38 UTC (rev 2067) +++ glibc-package/trunk/debian/patches/series 2007-04-15 00:45:03 UTC (rev 2068) @@ -138,3 +138,4 @@ any/submitted-clock-settime.diff -p0 any/submitted-date-and-unknown-tz.diff -p0 any/submitted-unistd_XOPEN_VERSION.diff +any/cvs-glob-c.diff -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]