An issue was discovered in GNU libiberty, as distributed in GNU Binutils 2.32. It is a heap-based buffer over-read in d_expression_1 in cp-demangle.c after many recursive calls. Reference: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89395
Created binutils tracking bugs for this issue: Affects: fedora-all [bug 1680652]
Segfault on Red Hat Enterprise Linux 6. 7 seems to be okay. ``` Program received signal SIGSEGV, Segmentation fault. 0x00007ffff7ba071a in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2681 2681 if (d_peek_char (di) == 'I') (gdb) bt #0 0x00007ffff7ba071a in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2681 #1 0x00007ffff7ba09f8 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2741 #2 0x00007ffff7ba0990 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2737 #3 0x00007ffff7ba0990 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2737 #4 0x00007ffff7ba0990 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2737 #5 0x00007ffff7ba09f8 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2741 #6 0x00007ffff7ba0990 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2737 #7 0x00007ffff7ba0990 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2737 #8 0x00007ffff7ba0990 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2737 #9 0x00007ffff7ba0990 in d_expression (di=0x7fffffffe030) at ./cp-demangle.c:2737 ```
Red Hat Enterprise Linux 6: ``` │1399 d_source_name (struct d_info *di) │ │1400 { │ │1401 long len; │ │1402 struct demangle_component *ret; │ │1403 │ │1404 len = d_number (di); │ >│1405 if (len <= 0) (gdb) print len $13 = 7550956185914230101 ``` Looks like d_number is returning junk in this case. After this, `ret = d_identifier (di, len);` runs and presumably increments di->n len bytes. ``` (gdb) print di->n $14 = 0xfffffffff85596f2 <Address 0xfffffffff85596f2 out of bounds> ``` Thus, next time di->n is used (as a string ptr I believe), a deference leads to a crash.
Still unclear why I am unable to reproduce on later versions. It looks like the di advance function in RHEL7's version (and up) has support for a "checked" advance. It looks for a NULL character and aborts if it finds one. I didn't see an abort signal raised though, so that doesn't seem to be the solution.