On Mon, 2020-05-18 at 00:05 +0200, Mark Wielaard wrote:
> Hi,
> 
> While trying out -fanalyzer on the bzip2 source code I noticed that
> it
> did warn about some unsafe calls in the signal handler, 

Great.

> but din't warn
> about the exit call:
> https://sourceware.org/pipermail/bzip2-devel/2020q2/000107.html

> It was easy to add exit to the async_signal_unsafe_fns, but since
> there is a signal safe _exit call (which is what you should use in a
> signal handler, so no unsafe calls are made, like to the at_exit
> handlers) I also wanted to add a fixit hint.

I like this idea.

> The fixit hint is emitted, but it is somewhat hard to see. Is there a
> better way to do this for analyzer warnings so that it is a bit more
> prominent?
> 
> This is how it currently looks:
> 
> /opt/local/gcc/bin/gcc -g -O2 -fanalyzer -c bzip2.c
> bzip2.c: In function ‘mySIGSEGVorSIGBUScatcher’:
> bzip2.c:874:4: warning: call to ‘exit’ from within signal handler
> [CWE-479] [-Wanalyzer-unsafe-call-within-signal-handler]
>   874 |    exit(exitValue);
>       |    ^~~~~~~~~~~~~~~
>       |    _exit
>   ‘main’: events 1-2
>     |
>     | 1784 | IntNative main ( IntNative argc, Char *argv[] )
>     |      |           ^~~~
>     |      |           |
>     |      |           (1) entry to ‘main’
>     |......
>     | 1800 |    smallMode               = False;
>     |      |    ~~~~~~~~~
>     |      |    |
>     |      |    (2) registering ‘mySIGSEGVorSIGBUScatcher’ as signal
> handler
>     |
>   event 3
>     |
>     |cc1:
>     | (3): later on, when the signal is delivered to the process
>     |
>     +--> ‘mySIGSEGVorSIGBUScatcher’: events 4-5
>            |
>            |  816 | void mySIGSEGVorSIGBUScatcher ( IntNative n )
>            |      |      ^~~~~~~~~~~~~~~~~~~~~~~~
>            |      |      |
>            |      |      (4) entry to ‘mySIGSEGVorSIGBUScatcher’
>            |......
>            |  874 |    exit(exitValue);
>            |      |    ~~~~~~~~~~~~~~~
>            |      |    |
>            |      |    (5) call to ‘exit’ from within signal handler
>            |
> 
> Thanks,

I think this ought to be implemented as a followup "note" diagnostic
via the "inform" API, so that the followup message is separate from the
initial warning, and thus separate from the path...

[...]

>      diagnostic_metadata m;
>      /* CWE-479: Signal Handler Use of a Non-reentrant Function.  */
>      m.add_cwe (479);
> +    if (m_replacement != NULL)
> +      rich_loc->add_fixit_replace (m_replacement);
>      return warning_meta (rich_loc, m,
>                        OPT_Wanalyzer_unsafe_call_within_signal_handle
> r,
>                        "call to %qD from within signal handler",


How about something like this (though I even haven't checked if it
compiles, and am not 100% sure what the wording should be):

  bool emit (rich_location *rich_loc) FINAL OVERRIDE
  {
    diagnostic_metadata m;
    /* CWE-479: Signal Handler Use of a Non-reentrant Function.  */
    m.add_cwe (479);
    if (warning_meta (rich_loc, m,
                      OPT_Wanalyzer_unsafe_call_within_signal_handler,
                      "call to %qD from within signal handler",
                      m_unsafe_fndecl))
      {
        if (m_replacement)
          {
            gcc_rich_location note_rich_loc (gimple_location (m_unsafe_call));
            note_rich_loc.add_fixit_replace (m_replacement);
            inform (&note_rich_loc, "%qs is a signal-safe replacement for %qD",
                    m_replacement, unsafe_fndecl);
          }
        return true;
      }
    return false;
  }


Dave

Reply via email to