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

--- Comment #2 from David Malcolm <dmalcolm at gcc dot gnu.org> ---
This turns out to be due to differences in the inline implementation of getchar
in <stdio.h> which expose a latent bug in leak-detection.

On my x86_64 Fedora 32 box,
/usr/include/bits/stdio.h is from glibc-headers-2.31-2.fc32.x86_64 and has:

/* Read a character from stdin.  */
__STDIO_INLINE int
getchar (void)
{
  return getc (stdin);
}

On gcc135 in the GCC compile farm,
/usr/include/bits/stdio.h is from glibc-headers-2.17-307.el7.1.ppc64le and has:

/* Read a character from stdin.  */
__STDIO_INLINE int
getchar (void)
{
  return _IO_getc (stdin);
}

The analyzer's sm-file.cc "knows" about "getc" and thus the analyzer treats
getc as having no side-effects.
In contrast, it doesn't "know" about "_IO_getc" and thus treats it as
potentially clobbering curbp, which exposes a latent false-positive bug in leak
detection.

The reported leak seems like a bug where the analyzer doesn't seem to grok that
a pointer written through a clobbered global variable is still live if that
global variable hasn't been clobbered again.  A minimal reproducer for this is:

void **g;

extern void unknown_fn (void);

int test(void)
{
  void *p;
#ifdef CALL_UNKNOWN
  unknown_fn ();
#endif
  p = __builtin_malloc(1024);
  *g = p;
  return 0;
}

Without -DCALL_UNKNOWN:
  ./xgcc -B. -S t.c -fanalyzer
  (no output)

With -DCALL_UNKNOWN:
  ./xgcc -B. -S t.c -fanalyzer -DCALL_UNKNOWN
  t.c: In function ‘test’:
  t.c:13:10: warning: leak of ‘p’ [CWE-401] [-Wanalyzer-malloc-leak]
     13 |   return 0;
        |          ^
    ‘test’: events 1-2
      |
      |   11 |   p = __builtin_malloc(1024);
      |      |       ^~~~~~~~~~~~~~~~~~~~~~
      |      |       |
      |      |       (1) allocated here
      |   12 |   *g = p;
      |   13 |   return 0;
      |      |          ~
      |      |          |
      |      |          (2) ‘p’ leaks here; was allocated at (1)
      |

Reply via email to