https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83150

            Bug ID: 83150
           Summary: GCC's internal use of `abort`is unsafe in several ways
           Product: gcc
           Version: 6.4.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: other
          Assignee: unassigned at gcc dot gnu.org
          Reporter: b.r.longbons at gmail dot com
  Target Milestone: ---

1. if the `fancy_abort` redefinition is used, exit() is called (and thus atexit
handlers), violating the assumptions of both plugins and later system headers
(including macros) that expect abort() to prevent further code execution, since
invariants may be broken.

Either using `_exit` or `abort` would fix this (in
`diagnostic_action_after_output`, on the ICE case).

The only other alternative would be to write your own libc on all platforms.

2. if the real `abort` is used, GCC installs a signal handler, which calls
async-signal-unsafe functions, such as malloc.

For the async latter case, the first offenders are:
(usual case, e.g. LANG=en_US.UTF-8)
#0  __GI___libc_malloc (bytes=50) at malloc.c:2917
#1  0x00007ffff689f4d6 in _nl_make_l10nflist
(l10nfile_list=l10nfile_list@entry=0x7ffff6c07b78 <_nl_loaded_domains>,
dirlist=dirlist@entry=0x7ffff69d7890 <_nl_default_dirname> "/usr/share/locale",
dirlist_len=18, 
    mask=mask@entry=0, language=language@entry=0x7fffffffcac0 "en_US.UTF-8",
territory=territory@entry=0x0, codeset=0x0, normalized_codeset=0x0,
modifier=0x0, filename=0x7fffffffcae0 "LC_MESSAGES/libc.mo", do_allocate=0)
    at ../intl/l10nflist.c:166
#2  0x00007ffff689d2c7 in _nl_find_domain (dirname=dirname@entry=0x7ffff69d7890
<_nl_default_dirname> "/usr/share/locale", locale=locale@entry=0x7fffffffcac0
"en_US.UTF-8", 
    domainname=domainname@entry=0x7fffffffcae0 "LC_MESSAGES/libc.mo",
domainbinding=domainbinding@entry=0x0) at finddomain.c:91
#3  0x00007ffff689cb73 in __dcigettext (domainname=0x7ffff69d0860
<_libc_intl_domainname> "libc", msgid1=0x7ffff69d14c8 "Aborted", msgid2=0x0,
plural=0, n=0, category=5) at dcigettext.c:722
#4  0x0000000000993f01 in ?? ()
#5  <signal handler called>

(LC_ALL=C)
#0  __GI___libc_malloc (bytes=146) at malloc.c:2917
#1  0x0000000001050368 in xmalloc ()
#2  0x0000000001050517 in xvasprintf ()
#3  0x0000000000ff9cbc in build_message_string(char const*, ...) ()
#4  0x000000000084fe4e in lhd_print_error_function(diagnostic_context*, char
const*, diagnostic_info*) ()
#5  0x00000000009d16a1 in ?? ()
#6  0x0000000000ffadbd in diagnostic_report_diagnostic(diagnostic_context*,
diagnostic_info*) ()
#7  0x0000000000ffc2de in internal_error(char const*, ...) ()
#8  0x0000000000993f10 in ?? ()
#9  <signal handler called>


Frankly, writing signal handlers correctly is hard, and usually not worth it
(just `write(2)` a short message, then bail out). Especially since you've got
the driver watching your exit code, *and* most ICEs go through the
`fancy_abort` path anyway.


I did most of my testing against GCC 6.4.0, but visual inspection of trunk
looks like all the relevant code is unchanged.

Reply via email to