Hi,

fuzzing glob.c immediately discovered a leak.

At ~L600 in glob.c, 'dirname' is heap allocated.
It is free'd at label 'out', but some code paths directly return without
jumping there.

Attached is a patch fixing the issue for me, but just take it as a proof of
concept. You might prefer a different approach.

Regards, Tim
From 0b7efcb91485a808edd4a39c58d6dfe267b4097b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tim Rühsen?= <tim.rueh...@gmx.de>
Date: Sat, 1 Jul 2017 20:35:55 +0200
Subject: [PATCH] Fix memleak in glob()

---
 lib/glob.c | 31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/lib/glob.c b/lib/glob.c
index d4fdc1737..ec3cce66f 100644
--- a/lib/glob.c
+++ b/lib/glob.c
@@ -306,6 +306,7 @@ next_brace_sub (const char *cp, int flags)

 #endif /* !defined GLOB_ONLY_P */

+#define RETURNVAL(r) retval=(r); goto out
 /* Do glob searching for PATTERN, placing results in PGLOB.
    The bits defined above may be set in FLAGS.
    If a directory cannot be opened or read and ERRFUNC is not nil,
@@ -1035,7 +1036,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
                 if (flags & GLOB_TILDE_CHECK)
                   /* We have to regard it as an error if we cannot find the
                      home directory.  */
-                  return GLOB_NOMATCH;
+                  RETURNVAL(GLOB_NOMATCH);
               }
           }
         }
@@ -1067,7 +1068,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
               free (pglob->gl_pathv);
               pglob->gl_pathv = NULL;
               pglob->gl_pathc = 0;
-              return GLOB_NOSPACE;
+              RETURNVAL (GLOB_NOSPACE);
             }

           new_gl_pathv = realloc (pglob->gl_pathv,
@@ -1101,11 +1102,11 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
           ++pglob->gl_pathc;
           pglob->gl_flags = flags;

-          return 0;
+          RETURNVAL (0);
         }

       /* Not found.  */
-      return GLOB_NOMATCH;
+      RETURNVAL (GLOB_NOMATCH);
     }

   meta = __glob_pattern_type (dirname, !(flags & GLOB_NOESCAPE));
@@ -1151,7 +1152,9 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
       if (status != 0)
         {
           if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH)
-            return status;
+		    {
+              RETURNVAL (status);
+            }
           goto no_matches;
         }

@@ -1170,7 +1173,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
             if (interrupt_state)
               {
                 globfree (&dirs);
-                return GLOB_ABORTED;
+                RETURNVAL (GLOB_ABORTED);
               }
           }
 #endif /* SHELL.  */
@@ -1189,7 +1192,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
               globfree (&dirs);
               globfree (pglob);
               pglob->gl_pathc = 0;
-              return status;
+              RETURNVAL (status);
             }

           /* Stick the directory on the front of each name.  */
@@ -1200,7 +1203,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
               globfree (&dirs);
               globfree (pglob);
               pglob->gl_pathc = 0;
-              return GLOB_NOSPACE;
+              RETURNVAL (GLOB_NOSPACE);
             }
         }

@@ -1222,7 +1225,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
                 {
                 nospace2:
                   globfree (&dirs);
-                  return GLOB_NOSPACE;
+                  RETURNVAL (GLOB_NOSPACE);
                 }

               new_gl_pathv = realloc (pglob->gl_pathv,
@@ -1237,7 +1240,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
                   globfree (&dirs);
                   globfree (pglob);
                   pglob->gl_pathc = 0;
-                  return GLOB_NOSPACE;
+                  RETURNVAL (GLOB_NOSPACE);
                 }

               ++pglob->gl_pathc;
@@ -1249,7 +1252,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
           else
             {
               globfree (&dirs);
-              return GLOB_NOMATCH;
+              RETURNVAL (GLOB_NOMATCH);
             }
         }

@@ -1295,7 +1298,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
               flags = orig_flags;
               goto no_matches;
             }
-          return status;
+          RETURNVAL (status);
         }

       if (dirlen > 0)
@@ -1307,7 +1310,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
             {
               globfree (pglob);
               pglob->gl_pathc = 0;
-              return GLOB_NOSPACE;
+              RETURNVAL (GLOB_NOSPACE);
             }
         }
     }
@@ -1332,7 +1335,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
               {
                 globfree (pglob);
                 pglob->gl_pathc = 0;
-                return GLOB_NOSPACE;
+                RETURNVAL (GLOB_NOSPACE);
               }
             strcpy (&new[len - 2], "/");
             pglob->gl_pathv[i] = new;
--
2.11.0

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to