This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH v2] gcc: fix segfault from calling free on non-malloc'd area
- From: Paul Gortmaker <paul dot gortmaker at windriver dot com>
- To: <gcc-patches at gcc dot gnu dot org>
- Cc: Paul Gortmaker <paul dot gortmaker at windriver dot com>, Jakub Jelinek <jakub at redhat dot com>, Jeff Law <law at redhat dot com>, Matthias Klose <doko at ubuntu dot com>, Tobias Burnus <burnus at net-b dot de>
- Date: Tue, 24 Jun 2014 16:05:54 -0400
- Subject: [PATCH v2] gcc: fix segfault from calling free on non-malloc'd area
- Authentication-results: sourceware.org; auth=none
- References: <20140623204241 dot GT31640 at tucnak dot redhat dot com>
We see the following on a 32bit gcc installed on 64 bit host:
Reading symbols from ./i586-pokymllib32-linux-gcc...done.
(gdb) run
Starting program: x86-pokymllib32-linux/lib32-gcc/4.9.0-r0/image/usr/bin/i586-pokymllib32-linux-gcc
Program received signal SIGSEGV, Segmentation fault.
0xf7e957e0 in free () from /lib/i386-linux-gnu/libc.so.6
(gdb) bt
#0 0xf7e957e0 in free () from /lib/i386-linux-gnu/libc.so.6
#1 0x0804b73c in set_multilib_dir () at gcc-4.9.0/gcc/gcc.c:7827
#2 main (argc=1, argv=0xffffd504) at gcc-4.9.0/gcc/gcc.c:6688
(gdb)
The problem arises because we conditionally assign the pointer we
eventually free, and the conditional may assign the pointer to the
non-malloc'd internal string "." which fails when we free it here:
if (multilib_dir == NULL && multilib_os_dir != NULL
&& strcmp (multilib_os_dir, ".") == 0)
{
free (CONST_CAST (char *, multilib_os_dir));
...
As suggested by Jakub, ensure the "." case is also malloc'd via
xstrdup() and hence the pointer for the "." case can be freed.
Cc: Jakub Jelinek <jakub@redhat.com>
Cc: Jeff Law <law@redhat.com>
Cc: Matthias Klose <doko@ubuntu.com>
CC: Tobias Burnus <burnus@net-b.de>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
[v2: don't change the causality of the free() ; instead just make
the "." pointer be malloc'd as well. Note that I was unable to
reproduce the broken-ness of my original (broken) patch with a
direct build of trunk, with "./configure --prefix=/usr/local"
but I also did re-test this new patch still fixed the error that
we saw in yocto with gcc-4.9.0 with the invalid free segfault.]
gcc/gcc.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 9ac18e60d801..168acf7eb0c9 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -7790,10 +7790,15 @@ set_multilib_dir (void)
q2++;
if (*q2 == ':')
ml_end = q2;
- new_multilib_os_dir = XNEWVEC (char, ml_end - q);
- memcpy (new_multilib_os_dir, q + 1, ml_end - q - 1);
- new_multilib_os_dir[ml_end - q - 1] = '\0';
- multilib_os_dir = *new_multilib_os_dir ? new_multilib_os_dir : ".";
+ if (ml_end - q == 1)
+ multilib_os_dir = xstrdup (".");
+ else
+ {
+ new_multilib_os_dir = XNEWVEC (char, ml_end - q);
+ memcpy (new_multilib_os_dir, q + 1, ml_end - q - 1);
+ new_multilib_os_dir[ml_end - q - 1] = '\0';
+ multilib_os_dir = new_multilib_os_dir;
+ }
if (q2 < end && *q2 == ':')
{
--
1.9.2