From a22a222c8f9299f6c07a0274388ade7d4ab8c28d Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 20 Jun 2014 16:41:08 -0400 Subject: [PATCH] gcc: fix segfault from calling free on non-malloc'd area 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 Cc: Jeff Law Cc: Matthias Klose CC: Tobias Burnus Upstream-Status: Accepted [ https://gcc.gnu.org/ml/gcc-patches/2014-06/msg02069.html ] Signed-off-by: Paul Gortmaker 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