>From 8d5f7d7e43b8830acde4f82b93cc7b970d9ec435 Mon Sep 17 00:00:00 2001
From: Bruno Haible
Date: Fri, 17 Jan 2020 11:51:26 -0800
Subject: [PATCH] glob: Fix use-after-free bug.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Reported by Tim Rühsen in
.
* lib/glob.c (__glob): Delay freeing dirname until after the use of
end_name.
---
ChangeLog | 9 +++++++++
lib/glob.c | 21 +++++++++++++--------
2 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 643dba312..04b139a6a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2020-01-17 Bruno Haible
+ Paul Eggert
+
+ glob: Fix use-after-free bug.
+ Reported by Tim Rühsen in
+ .
+ * lib/glob.c (__glob): Delay freeing dirname until after the use of
+ end_name.
+
2020-01-16 Siddhesh Poyarekar
vcs-to-changelog: Fix parsing of fndecl without args.
diff --git a/lib/glob.c b/lib/glob.c
index a67cbb67e..e0928312a 100644
--- a/lib/glob.c
+++ b/lib/glob.c
@@ -843,24 +843,27 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
size_t home_len = strlen (p->pw_dir);
size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
+ /* dirname contains end_name; we can't free it now. */
+ char *prev_dirname =
+ (__glibc_unlikely (malloc_dirname) ? dirname : NULL);
char *d;
- if (__glibc_unlikely (malloc_dirname))
- free (dirname);
- malloc_dirname = 0;
-
if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
- dirname = alloca_account (home_len + rest_len + 1,
- alloca_used);
+ {
+ dirname = alloca_account (home_len + rest_len + 1,
+ alloca_used);
+ malloc_dirname = 0;
+ }
else
{
- dirname = malloc (home_len + rest_len + 1);
- if (dirname == NULL)
+ char *new_dirname = malloc (home_len + rest_len + 1);
+ if (new_dirname == NULL)
{
scratch_buffer_free (&pwtmpbuf);
retval = GLOB_NOSPACE;
goto out;
}
+ dirname = new_dirname;
malloc_dirname = 1;
}
d = mempcpy (dirname, p->pw_dir, home_len);
@@ -868,6 +871,8 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
d = mempcpy (d, end_name, rest_len);
*d = '\0';
+ free (prev_dirname);
+
dirlen = home_len + rest_len;
dirname_modified = 1;
}
--
2.24.1