Blob Blame History Raw
From 3e5bd73528675367c70f09cd5a55776bd978ebf0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Sun, 29 Sep 2013 14:40:58 +0200
Subject: [PATCH] Fix buffer overrun when enumerating files

https://bugs.freedesktop.org/show_bug.cgi?id=69887

Based-on-a-patch-by: Hans Petter Jansson <hpj@copyleft.no>

Conflicts:
	src/test/test-util.c
---
 src/shared/util.c | 79 ++++++++++++++++++-------------------------------------
 1 file changed, 26 insertions(+), 53 deletions(-)

diff --git a/src/shared/util.c b/src/shared/util.c
index c9e9b87228..eb9b0f7e92 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -4388,38 +4388,31 @@ int dirent_ensure_type(DIR *d, struct dirent *de) {
 }
 
 int in_search_path(const char *path, char **search) {
-        char **i, *parent;
+        char **i;
+        _cleanup_free_ char *parent = NULL;
         int r;
 
         r = path_get_parent(path, &parent);
         if (r < 0)
                 return r;
 
-        r = 0;
-
-        STRV_FOREACH(i, search) {
-                if (path_equal(parent, *i)) {
-                        r = 1;
-                        break;
-                }
-        }
-
-        free(parent);
+        STRV_FOREACH(i, search)
+                if (path_equal(parent, *i))
+                        return 1;
 
-        return r;
+        return 0;
 }
 
 int get_files_in_directory(const char *path, char ***list) {
-        DIR *d;
-        int r = 0;
-        unsigned n = 0;
-        char **l = NULL;
+        _cleanup_closedir_ DIR *d = NULL;
+        size_t bufsize = 0, n = 0;
+        _cleanup_strv_free_ char **l = NULL;
 
         assert(path);
 
         /* Returns all files in a directory in *list, and the number
          * of files as return value. If list is NULL returns only the
-         * number */
+         * number. */
 
         d = opendir(path);
         if (!d)
@@ -4431,11 +4424,9 @@ int get_files_in_directory(const char *path, char ***list) {
                 int k;
 
                 k = readdir_r(d, &buf.de, &de);
-                if (k != 0) {
-                        r = -k;
-                        goto finish;
-                }
-
+                assert(k >= 0);
+                if (k > 0)
+                        return -k;
                 if (!de)
                         break;
 
@@ -4445,43 +4436,25 @@ int get_files_in_directory(const char *path, char ***list) {
                         continue;
 
                 if (list) {
-                        if ((unsigned) r >= n) {
-                                char **t;
-
-                                n = MAX(16, 2*r);
-                                t = realloc(l, sizeof(char*) * n);
-                                if (!t) {
-                                        r = -ENOMEM;
-                                        goto finish;
-                                }
-
-                                l = t;
-                        }
-
-                        assert((unsigned) r < n);
+                        /* one extra slot is needed for the terminating NULL */
+                        if (!GREEDY_REALLOC(l, bufsize, n + 2))
+                                return -ENOMEM;
 
-                        l[r] = strdup(de->d_name);
-                        if (!l[r]) {
-                                r = -ENOMEM;
-                                goto finish;
-                        }
+                        l[n] = strdup(de->d_name);
+                        if (!l[n])
+                                return -ENOMEM;
 
-                        l[++r] = NULL;
+                        l[++n] = NULL;
                 } else
-                        r++;
+                        n++;
         }
 
-finish:
-        if (d)
-                closedir(d);
-
-        if (r >= 0) {
-                if (list)
-                        *list = l;
-        } else
-                strv_free(l);
+        if (list) {
+                *list = l;
+                l = NULL; /* avoid freeing */
+        }
 
-        return r;
+        return n;
 }
 
 char *strjoin(const char *x, ...) {