| From aea56f4bcb9948d456f3fae4d044fd3fa2e19706 Mon Sep 17 00:00:00 2001 |
| From: Frank Denis <github@pureftpd.org> |
| Date: Mon, 30 Dec 2019 17:40:04 +0100 |
| Subject: [PATCH] listdir(): reuse a single buffer to store every file name to |
| display |
| |
| Allocating a new buffer for each entry is useless. |
| |
| And as these buffers are allocated on the stack, on systems with a |
| small stack size, with many entries, the limit can easily be reached, |
| causing a stack exhaustion and aborting the user session. |
| |
| Reported by Antonio Morales from the GitHub Security Lab team, thanks! |
| [Retrieved from: |
| https://github.com/jedisct1/pure-ftpd/commit/aea56f4bcb9948d456f3fae4d044fd3fa2e19706] |
| Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com> |
| --- |
| src/ls.c | 15 ++++++++------- |
| 1 file changed, 8 insertions(+), 7 deletions(-) |
| |
| diff --git a/src/ls.c b/src/ls.c |
| index cf804c7..f8a588f 100644 |
| --- a/src/ls.c |
| +++ b/src/ls.c |
| @@ -661,6 +661,8 @@ static void listdir(unsigned int depth, int f, void * const tls_fd, |
| char *names; |
| PureFileInfo *s; |
| PureFileInfo *r; |
| + char *alloca_subdir; |
| + size_t sizeof_subdir; |
| int d; |
| |
| if (depth >= max_ls_depth || matches >= max_ls_files) { |
| @@ -690,14 +692,12 @@ static void listdir(unsigned int depth, int f, void * const tls_fd, |
| } |
| outputfiles(f, tls_fd); |
| r = dir; |
| + sizeof_subdir = PATH_MAX + 1U; |
| + if ((alloca_subdir = ALLOCA(sizeof_subdir)) == NULL) { |
| + goto toomany; |
| + } |
| while (opt_R && r != s) { |
| if (r->name_offset != (size_t) -1 && !chdir(FI_NAME(r))) { |
| - char *alloca_subdir; |
| - const size_t sizeof_subdir = PATH_MAX + 1U; |
| - |
| - if ((alloca_subdir = ALLOCA(sizeof_subdir)) == NULL) { |
| - goto toomany; |
| - } |
| if (SNCHECK(snprintf(alloca_subdir, sizeof_subdir, "%s/%s", |
| name, FI_NAME(r)), sizeof_subdir)) { |
| goto nolist; |
| @@ -706,8 +706,8 @@ static void listdir(unsigned int depth, int f, void * const tls_fd, |
| wrstr(f, tls_fd, alloca_subdir); |
| wrstr(f, tls_fd, ":\r\n\r\n"); |
| listdir(depth + 1U, f, tls_fd, alloca_subdir); |
| + |
| nolist: |
| - ALLOCA_FREE(alloca_subdir); |
| if (matches >= max_ls_files) { |
| goto toomany; |
| } |
| @@ -720,6 +720,7 @@ static void listdir(unsigned int depth, int f, void * const tls_fd, |
| r++; |
| } |
| toomany: |
| + ALLOCA_FREE(alloca_subdir); |
| free(names); |
| free(dir); |
| names = NULL; |