misc/162396: [patch] remove loop in globpexp1()@lib/libc/gen/glob.c

Cheng-Lung Sung clsung at FreeBSD.org
Wed Nov 9 05:10:08 UTC 2011


>Number:         162396
>Category:       misc
>Synopsis:       [patch] remove loop in globpexp1()@lib/libc/gen/glob.c
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Nov 09 05:10:08 UTC 2011
>Closed-Date:
>Last-Modified:
>Originator:     Cheng-Lung Sung
>Release:        FreeBSD 8.2-RELEASE amd64
>Organization:
FreeBSD @ Taiwan
>Environment:
System: FreeBSD going04.iis.sinica.edu.tw 8.2-RELEASE FreeBSD 8.2-RELEASE #0: Tue Mar 8 12:09:34 CST 2011 root at going04.iis.sinica.edu.tw:/usr/obj/amd64/usr/src/sys/GOING04_SMP amd64
>Description:

One can see that globexp1() is called with GLOB_BRACE.
    
In globexp1(), examine the pattern: 
    only "{}" => call glob0()
    no LBRACE => call glob0()
    with LBRACE => call globexp2 to deal with expression inside LBRACE

Take a look in glob0():
    glob0, return 0 if success, otherwise error (except GLOB_NOMATCH)
        => return err
        => return globextend()/GLOB_NOMATCH
        => return 0 

In globexp2()
    => non matched braces
        => call glob0(), return 0
    => matched brace-pair
        => parse brace
            => reach rbrace, call globexp1(), set return value to *rv

    set *rv = 0, return 0

*which implies always return 0 in globexp2*
As a result, the following code block in globexp1 can be reduced from:
-       while ((ptr = g_strchr(ptr, LBRACE)) != NULL)
-               if (!globexp2(ptr, pattern, pglob, &rv, limit))
-                       return rv;
to:
+       if ((ptr = g_strchr(ptr, LBRACE)) != NULL)
+               return globexp2(ptr, pattern, pglob, limit)


Besides, since *rv should indicate the acctual return value, the setting *rv = 0 and return 0 is ambiguous.
So the flow in globexp2() should be:

In globexp2()
    => non matched braces
        => call glob0(), return 0
    => matched brace-pair
        => parse brace
            => reach rbrace, call globexp1(), set return value to *rv
                => if success in glob0
                    return 0
                => if failed in glob0 (but not GLOB_NOMATCH)
                    return err


>How-To-Repeat:
	
>Fix:


diff --git a/lib/libc/gen/glob.c b/lib/libc/gen/glob.c
index c3d9f08..40c5808 100644
--- a/lib/libc/gen/glob.c
+++ b/lib/libc/gen/glob.c
@@ -156,7 +156,7 @@ static int	 globextend(const Char *, glob_t *, size_t *);
 static const Char *	
 		 globtilde(const Char *, Char *, size_t, glob_t *);
 static int	 globexp1(const Char *, glob_t *, size_t *);
-static int	 globexp2(const Char *, const Char *, glob_t *, int *, size_t *);
+static int	 globexp2(const Char *, const Char *, glob_t *, size_t *);
 static int	 match(Char *, Char *, Char *);
 #ifdef DEBUG
 static void	 qprintf(const char *, Char *);
@@ -240,15 +240,13 @@ static int
 globexp1(const Char *pattern, glob_t *pglob, size_t *limit)
 {
 	const Char* ptr = pattern;
-	int rv;
 
 	/* Protect a single {}, for find(1), like csh */
 	if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
 		return glob0(pattern, pglob, limit);
 
-	while ((ptr = g_strchr(ptr, LBRACE)) != NULL)
-		if (!globexp2(ptr, pattern, pglob, &rv, limit))
-			return rv;
+	if ((ptr = g_strchr(ptr, LBRACE)) != NULL)
+		return globexp2(ptr, pattern, pglob, limit)
 
 	return glob0(pattern, pglob, limit);
 }
@@ -260,9 +258,10 @@ globexp1(const Char *pattern, glob_t *pglob, size_t *limit)
  * If it fails then it tries to glob the rest of the pattern and returns.
  */
 static int
-globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, size_t *limit)
+globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, size_t *limit)
 {
 	int     i;
+	int     rv;
 	Char   *lm, *ls;
 	const Char *pe, *pm, *pm1, *pl;
 	Char    patbuf[MAXPATHLEN];
@@ -297,8 +296,7 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, size_t *l
 
 	/* Non matching braces; just glob the pattern */
 	if (i != 0 || *pe == EOS) {
-		*rv = glob0(patbuf, pglob, limit);
-		return 0;
+		return glob0(patbuf, pglob, limit);
 	}
 
 	for (i = 0, pl = pm = ptr; pm <= pe; pm++)
@@ -344,7 +342,9 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, size_t *l
 #ifdef DEBUG
 				qprintf("globexp2:", patbuf);
 #endif
-				*rv = globexp1(patbuf, pglob, limit);
+				rv = globexp1(patbuf, pglob, limit);
+				if (rv && rv != GLOB_NOMATCH) /* if errors occured */
+					return rv;
 
 				/* move after the comma, to the next string */
 				pl = pm + 1;
@@ -354,7 +354,6 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, size_t *l
 		default:
 			break;
 		}
-	*rv = 0;
 	return 0;
 }
 

>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list