1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-21 02:50:18 +03:00

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>
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2013-09-29 14:40:58 +02:00
parent 8083d486d0
commit 893fa014de
Notes: Lennart Poettering 2013-10-04 17:11:46 +02:00
Backport: bugfix
2 changed files with 36 additions and 53 deletions

View File

@ -4412,38 +4412,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))
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)
@ -4455,11 +4448,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;
@ -4469,43 +4460,25 @@ int get_files_in_directory(const char *path, char ***list) {
continue;
if (list) {
if ((unsigned) r >= n) {
char **t;
/* one extra slot is needed for the terminating NULL */
if (!GREEDY_REALLOC(l, bufsize, n + 2))
return -ENOMEM;
n = MAX(16, 2*r);
t = realloc(l, sizeof(char*) * n);
if (!t) {
r = -ENOMEM;
goto finish;
}
l[n] = strdup(de->d_name);
if (!l[n])
return -ENOMEM;
l = t;
}
assert((unsigned) r < n);
l[r] = strdup(de->d_name);
if (!l[r]) {
r = -ENOMEM;
goto finish;
}
l[++r] = NULL;
l[++n] = NULL;
} else
r++;
n++;
}
finish:
if (d)
closedir(d);
if (list) {
*list = l;
l = NULL; /* avoid freeing */
}
if (r >= 0) {
if (list)
*list = l;
} else
strv_free(l);
return r;
return n;
}
char *strjoin(const char *x, ...) {

View File

@ -27,6 +27,7 @@
#include <errno.h>
#include "util.h"
#include "strv.h"
static void test_streq_ptr(void) {
assert_se(streq_ptr(NULL, NULL));
@ -582,6 +583,14 @@ static void test_fstab_node_to_udev_node(void) {
free(n);
}
static void test_get_files_in_directory(void) {
_cleanup_strv_free_ char **l = NULL, **t = NULL;
assert_se(get_files_in_directory("/tmp", &l) >= 0);
assert_se(get_files_in_directory(".", &l) >= 0);
assert_se(get_files_in_directory(".", NULL) >= 0);
}
int main(int argc, char *argv[]) {
test_streq_ptr();
test_first_word();
@ -618,6 +627,7 @@ int main(int argc, char *argv[]) {
test_parse_user_at_host();
test_split_pair();
test_fstab_node_to_udev_node();
test_get_files_in_directory();
return 0;
}