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

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |ice-on-valid-code
             Status|NEW                         |ASSIGNED
           See Also|                            |https://gcc.gnu.org/bugzill
                   |                            |a/show_bug.cgi?id=83642
           Assignee|unassigned at gcc dot gnu.org      |msebor at gcc dot 
gnu.org

--- Comment #5 from Martin Sebor <msebor at gcc dot gnu.org> ---
The ICE is caused by the following assertion which expects the offset into the
destination of the memory access to be in a range whose lower bound is less
than its upper bound:

  gcc_assert (wi::les_p (acs.dstoff[0], acs.dstoff[1]));

The range that is obtained for the test case in comment #4 is that of _9 in the
following VRP dump.  Its lower bound is 2 (corresponding to the length of
string literal) but its upper bound, 9223372036854775808, is equal to
PTRDIFF_MIN when interpreted as a signed integer.   It's the result of
9223372036854775806 + 2, the sum of the length of the longest string plus that
of "*/" (after signed overflow has wrapped it around zero).   The upper bound
should reflect the longest possible resulting string after the call to memcpy
in the dump.  Since no object can be larger than PTRDIFF_MAX - 1 bytes, the
length of no string can be greater than PTRDIFF_MAX - 2, a more accurate upper
bound of the offset is still 9223372036854775806, or still PTRDIFF_MAX - 1.  (I
opened bug 83642 for this optimization opportunity.)

Value ranges after VRP:

c_4: VARYING
_5: [0, 9223372036854775806]   // accurate upper bound of the length of any
string
_6: VARYING
_9: [2, 9223372036854775808]   // excessive upper bound
_10: VARYING
c_11: ~[0B, 0B]  EQUIVALENCES: { c_4 } (1 elements)


bar (char * b, char * c)
{
  long unsigned int _5;
  char * _6;
  long unsigned int _9;
  char * _10;

  <bb 2> [local count: 1073741825]:
  c_4 = foo ();
  _5 = __builtin_strlen (c_4);
  _6 = c_4 + _5;
  __builtin_memcpy (_6, "*/", 2);
  _9 = _5 + 2;
  _10 = c_4 + _9;
  __builtin_strcpy (_10, c_1(D));
  return;

}

Reply via email to