From 893fa014de0f73337ff4a4c9c531d6789b72f5bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= 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 --- src/shared/util.c | 79 +++++++++++++++++----------------------------------- src/test/test-util.c | 10 +++++++ 2 files changed, 36 insertions(+), 53 deletions(-) Index: systemd-207/src/shared/util.c =================================================================== --- systemd-207.orig/src/shared/util.c +++ systemd-207/src/shared/util.c @@ -4435,38 +4435,31 @@ int dirent_ensure_type(DIR *d, struct di } 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)) + return 1; - STRV_FOREACH(i, search) { - if (path_equal(parent, *i)) { - r = 1; - break; - } - } - - free(parent); - - 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) @@ -4478,11 +4471,9 @@ int get_files_in_directory(const char *p 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; @@ -4492,43 +4483,25 @@ int get_files_in_directory(const char *p 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); - - l[r] = strdup(de->d_name); - if (!l[r]) { - r = -ENOMEM; - goto finish; - } + /* one extra slot is needed for the terminating NULL */ + if (!GREEDY_REALLOC(l, bufsize, n + 2)) + return -ENOMEM; + + 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, ...) {