Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 1 | From a22a222c8f9299f6c07a0274388ade7d4ab8c28d Mon Sep 17 00:00:00 2001 |
| 2 | From: Paul Gortmaker <paul.gortmaker@windriver.com> |
| 3 | Date: Fri, 20 Jun 2014 16:41:08 -0400 |
| 4 | Subject: [PATCH] gcc: fix segfault from calling free on non-malloc'd area |
| 5 | |
| 6 | We see the following on a 32bit gcc installed on 64 bit host: |
| 7 | |
| 8 | Reading symbols from ./i586-pokymllib32-linux-gcc...done. |
| 9 | (gdb) run |
| 10 | Starting program: x86-pokymllib32-linux/lib32-gcc/4.9.0-r0/image/usr/bin/i586-pokymllib32-linux-gcc |
| 11 | |
| 12 | Program received signal SIGSEGV, Segmentation fault. |
| 13 | 0xf7e957e0 in free () from /lib/i386-linux-gnu/libc.so.6 |
| 14 | (gdb) bt |
| 15 | #0 0xf7e957e0 in free () from /lib/i386-linux-gnu/libc.so.6 |
| 16 | #1 0x0804b73c in set_multilib_dir () at gcc-4.9.0/gcc/gcc.c:7827 |
| 17 | #2 main (argc=1, argv=0xffffd504) at gcc-4.9.0/gcc/gcc.c:6688 |
| 18 | (gdb) |
| 19 | |
| 20 | The problem arises because we conditionally assign the pointer we |
| 21 | eventually free, and the conditional may assign the pointer to the |
| 22 | non-malloc'd internal string "." which fails when we free it here: |
| 23 | |
| 24 | if (multilib_dir == NULL && multilib_os_dir != NULL |
| 25 | && strcmp (multilib_os_dir, ".") == 0) |
| 26 | { |
| 27 | free (CONST_CAST (char *, multilib_os_dir)); |
| 28 | ... |
| 29 | |
| 30 | As suggested by Jakub, ensure the "." case is also malloc'd via |
| 31 | xstrdup() and hence the pointer for the "." case can be freed. |
| 32 | |
| 33 | Cc: Jakub Jelinek <jakub@redhat.com> |
| 34 | Cc: Jeff Law <law@redhat.com> |
| 35 | Cc: Matthias Klose <doko@ubuntu.com> |
| 36 | CC: Tobias Burnus <burnus@net-b.de> |
| 37 | Upstream-Status: Accepted [ https://gcc.gnu.org/ml/gcc-patches/2014-06/msg02069.html ] |
| 38 | Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| 39 | |
| 40 | diff --git a/gcc/gcc.c b/gcc/gcc.c |
| 41 | index 9ac18e60d801..168acf7eb0c9 100644 |
| 42 | --- a/gcc/gcc.c |
| 43 | +++ b/gcc/gcc.c |
| 44 | @@ -7790,10 +7790,15 @@ set_multilib_dir (void) |
| 45 | q2++; |
| 46 | if (*q2 == ':') |
| 47 | ml_end = q2; |
| 48 | - new_multilib_os_dir = XNEWVEC (char, ml_end - q); |
| 49 | - memcpy (new_multilib_os_dir, q + 1, ml_end - q - 1); |
| 50 | - new_multilib_os_dir[ml_end - q - 1] = '\0'; |
| 51 | - multilib_os_dir = *new_multilib_os_dir ? new_multilib_os_dir : "."; |
| 52 | + if (ml_end - q == 1) |
| 53 | + multilib_os_dir = xstrdup ("."); |
| 54 | + else |
| 55 | + { |
| 56 | + new_multilib_os_dir = XNEWVEC (char, ml_end - q); |
| 57 | + memcpy (new_multilib_os_dir, q + 1, ml_end - q - 1); |
| 58 | + new_multilib_os_dir[ml_end - q - 1] = '\0'; |
| 59 | + multilib_os_dir = new_multilib_os_dir; |
| 60 | + } |
| 61 | |
| 62 | if (q2 < end && *q2 == ':') |
| 63 | { |
| 64 | -- |
| 65 | 1.9.2 |
| 66 | |