Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libc/gen Selected fixes from Brian Ginsbach <ginsbach@cr...



details:   https://anonhg.NetBSD.org/src/rev/7716a5ae9c4c
branches:  trunk
changeset: 514693:7716a5ae9c4c
user:      christos <christos%NetBSD.org@localhost>
date:      Sat Sep 08 22:39:21 2001 +0000

description:
Selected fixes from Brian Ginsbach <ginsbach%cray.com@localhost>, modified by me.
- handle globbing of patterns that contain unmatched braces. Globbing
  a pattern "foo{" in a directory that contains "foo{" now works.
- check for MAXPATHLEN overflows during filename generation (security problem).
- Posix/XOpen fixes to always return GLOB_ABORTED when a directory open fails
  or when a file access fails.
- pathc was not initialized to 0 in one case.
Also
- rename err to error, so that it does not conflict with the libc function.

diffstat:

 lib/libc/gen/__glob13.c |  92 +++++++++++++++++++++++++++++++++++-------------
 1 files changed, 67 insertions(+), 25 deletions(-)

diffs (231 lines):

diff -r 2e965e762c95 -r 7716a5ae9c4c lib/libc/gen/__glob13.c
--- a/lib/libc/gen/__glob13.c   Sat Sep 08 18:59:20 2001 +0000
+++ b/lib/libc/gen/__glob13.c   Sat Sep 08 22:39:21 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: __glob13.c,v 1.21 2001/04/03 14:50:37 christos Exp $   */
+/*     $NetBSD: __glob13.c,v 1.22 2001/09/08 22:39:21 christos Exp $   */
 
 /*
  * Copyright (c) 1989, 1993
@@ -41,7 +41,7 @@
 #if 0
 static char sccsid[] = "@(#)glob.c     8.3 (Berkeley) 10/13/93";
 #else
-__RCSID("$NetBSD: __glob13.c,v 1.21 2001/04/03 14:50:37 christos Exp $");
+__RCSID("$NetBSD: __glob13.c,v 1.22 2001/09/08 22:39:21 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -167,8 +167,9 @@
 static int      g_stat __P((Char *, struct STAT *, glob_t *));
 static int      glob0 __P((const Char *, glob_t *));
 static int      glob1 __P((Char *, glob_t *, size_t *));
-static int      glob2 __P((Char *, Char *, Char *, glob_t *, size_t *));
-static int      glob3 __P((Char *, Char *, Char *, Char *, glob_t *,
+static int      glob2 __P((Char *, Char *, Char *, Char *, glob_t *,
+    size_t *));
+static int      glob3 __P((Char *, Char *, Char *, Char *, Char *, glob_t *,
     size_t *));
 static int      globextend __P((const Char *, glob_t *, size_t *));
 static const Char *globtilde __P((const Char *, Char *, size_t, glob_t *));
@@ -306,7 +307,11 @@
 
        /* Non matching braces; just glob the pattern */
        if (i != 0 || *pe == EOS) {
-               *rv = glob0(patbuf, pglob);
+               /*
+                * we use `pattern', not `patbuf' here so that that
+                * unbalanced braces are passed to the match
+                */
+               *rv = glob0(pattern, pglob);
                return 0;
        }
 
@@ -461,7 +466,7 @@
        glob_t *pglob;
 {
        const Char *qpatnext;
-       int c, err, oldpathc;
+       int c, error, oldpathc;
        Char *bufnext, patbuf[MAXPATHLEN+1];
        size_t limit = 0;
 
@@ -526,8 +531,8 @@
        qprintf("glob0:", patbuf);
 #endif
 
-       if ((err = glob1(patbuf, pglob, &limit)) != 0)
-               return(err);
+       if ((error = glob1(patbuf, pglob, &limit)) != 0)
+               return(error);
 
        if (pglob->gl_pathc == oldpathc) {      
                /*
@@ -540,8 +545,7 @@
                if ((pglob->gl_flags & GLOB_NOCHECK) ||
                    ((pglob->gl_flags & (GLOB_NOMAGIC|GLOB_MAGCHAR))
                     == GLOB_NOMAGIC)) {
-                       if ((err = globextend(pattern, pglob, &limit)) != 0)
-                               return (err);
+                       return globextend(pattern, pglob, &limit);
                } else {
                        return (GLOB_NOMATCH);
                }
@@ -579,7 +583,12 @@
        /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
        if (*pattern == EOS)
                return(0);
-       return(glob2(pathbuf, pathbuf, pattern, pglob, limit));
+       /*
+        * we save one character so that we can use ptr >= limit,
+        * in the general case when we are appending non nul chars only.
+        */
+       return(glob2(pathbuf, pathbuf, pathbuf + sizeof(pathbuf) - 1, pattern,
+           pglob, limit));
 }
 
 /*
@@ -588,8 +597,8 @@
  * meta characters.
  */
 static int
-glob2(pathbuf, pathend, pattern, pglob, limit)
-       Char *pathbuf, *pathend, *pattern;
+glob2(pathbuf, pathend, pathlim, pattern, pglob, limit)
+       Char *pathbuf, *pathend, *pathlim, *pattern;
        glob_t *pglob;
        size_t *limit;
 {
@@ -617,6 +626,8 @@
                            (S_ISLNK(sb.st_mode) &&
                            (g_stat(pathbuf, &sb, pglob) == 0) &&
                            S_ISDIR(sb.st_mode)))) {
+                               if (pathend >= pathlim)
+                                       return (GLOB_ABORTED);
                                *pathend++ = SEP;
                                *pathend = EOS;
                        }
@@ -630,30 +641,35 @@
                while (*p != EOS && *p != SEP) {
                        if (ismeta(*p))
                                anymeta = 1;
+                       if (q >= pathlim)
+                               return GLOB_ABORTED;
                        *q++ = *p++;
                }
 
                if (!anymeta) {         /* No expansion, do next segment. */
                        pathend = q;
                        pattern = p;
-                       while (*pattern == SEP)
+                       while (*pattern == SEP) {
+                               if (pathend >= pathlim)
+                                       return GLOB_ABORTED;
                                *pathend++ = *pattern++;
+                       }
                } else                  /* Need expansion, recurse. */
-                       return(glob3(pathbuf, pathend, pattern, p, pglob,
-                           limit));
+                       return(glob3(pathbuf, pathend, pathlim, pattern, p,
+                           pglob, limit));
        }
        /* NOTREACHED */
 }
 
 static int
-glob3(pathbuf, pathend, pattern, restpattern, pglob, limit)
-       Char *pathbuf, *pathend, *pattern, *restpattern;
+glob3(pathbuf, pathend, pathlim, pattern, restpattern, pglob, limit)
+       Char *pathbuf, *pathend, *pathlim, *pattern, *restpattern;
        glob_t *pglob;
        size_t *limit;
 {
        struct dirent *dp;
        DIR *dirp;
-       int err;
+       int error;
        char buf[MAXPATHLEN];
 
        /*
@@ -674,7 +690,6 @@
        errno = 0;
            
        if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
-               /* TODO: don't call for ENOENT or ENOTDIR? */
                if (pglob->gl_errfunc) {
                        if (g_Ctoc(pathbuf, buf, sizeof(buf)))
                                return (GLOB_ABORTED);
@@ -682,10 +697,19 @@
                            pglob->gl_flags & GLOB_ERR)
                                return (GLOB_ABORTED);
                }
+               /*
+                * Posix/XOpen: glob should return when it encounters a
+                * directory that it cannot open or read
+                * XXX: Should we ignore ENOTDIR and ENOENT though?
+                * I think that Posix had in mind EPERM...
+                */
+               if (pglob->gl_flags & GLOB_ERR)
+                       return (GLOB_ABORTED);
+
                return(0);
        }
 
-       err = 0;
+       error = 0;
 
        /* Search directory for matching names. */
        if (pglob->gl_flags & GLOB_ALTDIRFUNC)
@@ -699,15 +723,25 @@
                /* Initial DOT must be matched literally. */
                if (dp->d_name[0] == DOT && *pattern != DOT)
                        continue;
+               /*
+                * The resulting string contains EOS, so we can
+                * use the pathlim character, if it is the nul
+                */
                for (sc = (u_char *) dp->d_name, dc = pathend; 
-                    (*dc++ = *sc++) != EOS;)
+                    dc <= pathlim && (*dc++ = *sc++) != EOS;)
                        continue;
+               /*
+                * we compare to one after pathlim, since the pointer
+                * has been post-incremented.
+                */
+               if (dc > pathlim + 1)
+                       return GLOB_ABORTED;
                if (!match(pathend, pattern, restpattern)) {
                        *pathend = EOS;
                        continue;
                }
-               err = glob2(pathbuf, --dc, restpattern, pglob, limit);
-               if (err)
+               error = glob2(pathbuf, --dc, pathlim, restpattern, pglob, limit);
+               if (error)
                        break;
        }
 
@@ -715,7 +749,14 @@
                (*pglob->gl_closedir)(dirp);
        else
                closedir(dirp);
-       return(err);
+
+       /*
+        * Again Posix X/Open issue with regards to error handling.
+        */
+       if ((error || errno) && (pglob->gl_flags & GLOB_ERR))
+               return (GLOB_ABORTED);
+
+       return(error);
 }
 
 
@@ -856,6 +897,7 @@
                                free(*pp);
                free(pglob->gl_pathv);
                pglob->gl_pathv = NULL;
+               pglob->gl_pathc = 0;
        }
 }
 



Home | Main Index | Thread Index | Old Index