[Bug lto/61886] New: [4.8/4.9/4.10 Regression] LTO breaks fread with _FORTIFY_SOURCE=2

rguenth at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Wed Jul 23 10:40:00 GMT 2014


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

            Bug ID: 61886
           Summary: [4.8/4.9/4.10 Regression] LTO breaks fread with
                    _FORTIFY_SOURCE=2
           Product: gcc
           Version: 4.9.1
            Status: UNCONFIRMED
          Keywords: diagnostic, lto, wrong-code
          Severity: normal
          Priority: P3
         Component: lto
          Assignee: unassigned at gcc dot gnu.org
          Reporter: rguenth at gcc dot gnu.org
                CC: hubicka at gcc dot gnu.org

Created attachment 33176
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=33176&action=edit
testcase extracted from cairo test suite

With the attached testcase extracted from the Cairo testsuite (which they build
with -flto ...) you get

> gcc-4.9 create-for-stream.i -O2 -flto -r -nostdlib
In function ‘__fread_alias’,
    inlined from ‘test_surface’ at create-for-stream.c:218:9:
/usr/include/bits/stdio2.h:290:2: warning: call to ‘__fread_chk_warn’ declared
with attribute warning: fread called with bigger size * nmemb than length of
destination buffer
  return __fread_chk (__ptr, __bos0 (__ptr), __size, __n, __stream);
  ^

where we mangle compile-time

  <bb 13>:
  _55 = wc.index;
  _77 = __builtin_constant_p (_55);
  if (_77 == 0)
    goto <bb 15>;
  else
    goto <bb 14>;

  <bb 14>:
  _78 = _55 | 1;
  if (_78 > 4294967295)
    goto <bb 15>;
  else
    goto <bb 16>;

  <bb 15>:
  _79 = __fread_chk (&file_contents, 4096, 1, _55, fp_48);
  goto <bb 19>;

  <bb 16>:
  if (_55 > 4096)
    goto <bb 17>;
  else
    goto <bb 18>;

  <bb 17>:
  _81 = *__fread_chk (&file_contents, 4096, 1, _55, fp_48);
  goto <bb 19>;

  <bb 18>:
  _82 = *fread (&file_contents, 1, _55, fp_48);

  <bb 19>:
  # _83 = PHI <_79(15), _81(17), _82(18)>

into the bogus

  <bb 13>:
  _49 = wc.index;
  _64 = __builtin_constant_p (_49);
  if (_64 == 0)
    goto <bb 15>;
  else
    goto <bb 14>;

  <bb 14>:
  _65 = _49 | 1;
  if (_65 > 4294967295)
    goto <bb 15>;
  else
    goto <bb 16>;

  <bb 15>:
  _66 = __fread_chk_warn (&file_contents, 4096, 1, _49, fp_43);
  goto <bb 19>;

  <bb 16>:
  if (_49 > 4096)
    goto <bb 17>;
  else
    goto <bb 18>;

  <bb 17>:
  _67 = __fread_chk_warn (&file_contents, 4096, 1, _49, fp_43);
  goto <bb 19>;

  <bb 18>:
  _68 = __fread_alias (&file_contents, 1, _49, fp_43);

  <bb 19>:
  # _69 = PHI <_66(15), _67(17), _68(18)>

somehow messing up the aliases game glibc plays:

extern size_t __fread_chk (void *__restrict __ptr, size_t __ptrlen,
                           size_t __size, size_t __n,
                           FILE *__restrict __stream) __wur;
extern size_t __REDIRECT (__fread_alias,
                          (void *__restrict __ptr, size_t __size,
                           size_t __n, FILE *__restrict __stream),
                          fread) __wur;
extern size_t __REDIRECT (__fread_chk_warn,
                          (void *__restrict __ptr, size_t __ptrlen,
                           size_t __size, size_t __n,
                           FILE *__restrict __stream),
                          __fread_chk)
     __wur __warnattr ("fread called with bigger size * nmemb than length "
                       "of destination buffer");

__fortify_function __wur size_t
fread (void *__restrict __ptr, size_t __size, size_t __n,
       FILE *__restrict __stream)
{
  if (__bos0 (__ptr) != (size_t) -1)
    {
      if (!__builtin_constant_p (__size)
          || !__builtin_constant_p (__n)
          || (__size | __n) >= (((size_t) 1) << (8 * sizeof (size_t) / 2)))
        return __fread_chk (__ptr, __bos0 (__ptr), __size, __n, __stream);

      if (__size * __n > __bos0 (__ptr))
        return __fread_chk_warn (__ptr, __bos0 (__ptr), __size, __n, __stream);
    }
  return __fread_alias (__ptr, __size, __n, __stream);
}

Merging nodes for *__fread_chk. Candidates:
*__fread_chk/98 (__fread_chk_warn) @0x7ffff6dc2b80
  Type: function
  Visibility: undef external public
  next sharing asm name: 97
  References:
  Referring:
  Read from file: /tmp/ccu88pge.o
  First run: 0
  Function flags:
  Called by: test_surface/78
  Calls:
__fread_chk/97 (__fread_chk) @0x7ffff6dc2cf0
  Type: function
  Visibility: external public
  previous sharing asm name: 98
  References:
  Referring:
  Read from file: /tmp/ccu88pge.o
  First run: 0
  Function flags:
  Called by: test_surface/78 (0.00 per call)
After resolution:
*__fread_chk/98 (__fread_chk_warn) @0x7ffff6dc2b80
  Type: function
  Visibility: undef external public
  next sharing asm name: 97
  References:
  Referring:
  Read from file: /tmp/ccu88pge.o
  First run: 0
  Function flags:
  Called by: test_surface/78
  Calls:
__fread_chk/97 (__fread_chk) @0x7ffff6dc2cf0
  Type: function
  Visibility: external public
  previous sharing asm name: 98
  References:
  Referring:
  Read from file: /tmp/ccu88pge.o
  First run: 0
  Function flags:
  Called by: test_surface/78 (0.00 per call)
  Calls:

but we obviously shouldn't merge these ...

(I believe we shouldn't drop any aliases at LTO symbol merging time, which
means _not_ merging based on asm-name?)


More information about the Gcc-bugs mailing list