[Bug tree-optimization/88973] [8/9 Regression] New -Wrestrict warning since r268048

2019-02-20 Thread msebor at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88973

--- Comment #8 from Martin Sebor  ---
The Asan warning is much clearer because it's based on actually observed
values.  This instance of the -Wrestrict warning is based on a heuristic: "we
think the copy may overlap because it is within the same object and we can't
prove that the offsets and the size assure it doesn't happen."

There may be a way to reword the warning to make things a little bit clearer
but I don't think we can match the Asan form.  When the offsets and the size
are completely unbounded we could just avoid printing them altogether.  That
would make it:

  'strcpy' accessing the same array may overlap [-Werror=restrict]

When the size is known it would give us:

  'strcpy' accessing N bytes of the same array may overlap [-Werror=restrict]

and when the offsets are known but the size isn't:

  'strcpy' accessing the same array at offsets [O1, O2] and [O3, O4] may
overlap [-Werror=restrict]

and so on.

There are many forms of the -Wrestrict warning already: singular size (1 byte)
vs plural size (bytes) vs closed range (between X and Y bytes) vs open range (X
or more bytes), constant offsets vs closed ranges ([X, Y]), definitely overlaps
vs may overlap, and others, and because of internationalization most have to be
hardcoded and can't be easily parameterized, so adding a new form into the mix
isn't completely straightforward.

[Bug tree-optimization/88973] [8/9 Regression] New -Wrestrict warning since r268048

2019-02-20 Thread marxin at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88973

--- Comment #7 from Martin Liška  ---
(In reply to Martin Sebor from comment #4)
> I've created a test case using the canonicalize_pathname function showing
> that it does, in fact, cause an overlap to take place.  The following line
> in the output of the test case
> 

Thank you very much Martin for it! Btw. ASAN prints nice error about
overlapping arguments:

gcc -DPATHNAME='"/home//marxin"'  -Wall canonicalize_pathname.c
-fsanitize=address -g && ./a.out
=
==14653==ERROR: AddressSanitizer: strcpy-param-overlap: memory ranges
[0x60200016,0x6020001d) and [0x60200017, 0x6020001e) overlap
#0 0x772051de  (/usr/lib64/libasan.so.5+0x4b1de)
#1 0x40137c in canonicalize_pathname /tmp/canonicalize_pathname.c:25
#2 0x401857 in main /tmp/canonicalize_pathname.c:64
#3 0x77018b7a in __libc_start_main ../csu/libc-start.c:308
#4 0x4010e9 in _start (/tmp/a.out+0x4010e9)

[Bug tree-optimization/88973] [8/9 Regression] New -Wrestrict warning since r268048

2019-02-20 Thread marxin at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88973

--- Comment #6 from Martin Liška  ---
(In reply to Bruce Korb from comment #5)
> (In reply to Martin Sebor from comment #4)
> 
> > canonicalize_pathname.c: In function ‘canonicalize_pathname’:
> > canonicalize_pathname.c:61:2: warning: ‘strcpy’ accessing 1 byte at offsets
> > [0, 9223372036854775807] and [0, 9223372036854775807] may overlap 1 byte at
> > offset 0 [-Wrestrict]
> >61 |  strcpy( result + start + 1, result + i + 2 );
> >   |  ^~~~
> > strcpy (0x217f265 = "//bar", 0x217f267 = "bar"): 3
> > /foo/bar
> 
> I have a copy of this code in my project, but I haven't been writing code
> for several years now. How was this fixed? The best fix would be to
> determine the string length and do memmove-s, but that's enough fiddling
> that I'd have to clear cobwebs and spend a mess of time. If someone's
> already done that, ... :)

There's an upstream bug:
https://sourceforge.net/p/autogen/bugs/193/
and I'm working on patch candidate.

[Bug tree-optimization/88973] [8/9 Regression] New -Wrestrict warning since r268048

2019-02-19 Thread bkorb at gnu dot org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88973

Bruce Korb  changed:

   What|Removed |Added

 CC||bkorb at gnu dot org

--- Comment #5 from Bruce Korb  ---
(In reply to Martin Sebor from comment #4)

> canonicalize_pathname.c: In function ‘canonicalize_pathname’:
> canonicalize_pathname.c:61:2: warning: ‘strcpy’ accessing 1 byte at offsets
> [0, 9223372036854775807] and [0, 9223372036854775807] may overlap 1 byte at
> offset 0 [-Wrestrict]
>61 |  strcpy( result + start + 1, result + i + 2 );
>   |  ^~~~
> strcpy (0x217f265 = "//bar", 0x217f267 = "bar"): 3
> /foo/bar

I have a copy of this code in my project, but I haven't been writing code for
several years now. How was this fixed? The best fix would be to determine the
string length and do memmove-s, but that's enough fiddling that I'd have to
clear cobwebs and spend a mess of time. If someone's already done that, ... :)

[Bug tree-optimization/88973] [8/9 Regression] New -Wrestrict warning since r268048

2019-01-22 Thread msebor at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88973

Martin Sebor  changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution|--- |INVALID

--- Comment #4 from Martin Sebor  ---
I've created a test case using the canonicalize_pathname function showing that
it does, in fact, cause an overlap to take place.  The following line in the
output of the test case

  strcpy (0x217f265 = "//bar", 0x217f267 = "bar"): 3

shows that strcpy is being called to copy the 4 bytes "bar\0" from 0x217f267 to
0x217f265, with the last two bytes of the copy overlapping its first two bytes.

$ cat canonicalize_pathname.c && gcc -DPATHNAME='"/foo///bar"' -O2 -Wall
canonicalize_pathname.c && ./a.out
char*
strcpy (char *d, const char *s)
{
  unsigned n = __builtin_strlen (s);
  __builtin_printf ("%s (%p = \"%s\", %p = \"%s\"): %u\n",
__func__, d, d, s, s, n);
  __builtin_memcpy (d, s, n + 1);
  return d;
}

char *
canonicalize_pathname (char *path)
{
  int i, start;
  char stub_char, *result;

  result = __builtin_strdup( path );

  stub_char = (*path == '/') ? '/' : '.';

  i = 0;
  while (result[i]) {
while (result[i] != '\0' && result[i] != '/')
  i++;

start = i++;

if (!result[start])
  break;

while (result[i] == '/')
  i++;

if ((start + 1) != i)
  {
strcpy( result + start + 1, result + i );
i = start + 1;
  }

if (start > 0 && result[start - 1] == '\\')
  continue;

if ((start && !result[i])
|| (result[i] == '.' && !result[i+1])) {
  result[--i] = '\0';
  break;
}

if (result[i] == '.') {

  if (result[i + 1] == '/') {
strcpy( result + i, result + i + 1 );
i = (start < 0) ? 0 : start;
continue;
  }

  if (result[i + 1] == '.' &&
  (result[i + 2] == '/' || !result[i + 2])) {
while (--start > -1 && result[start] != '/')
  ;
strcpy( result + start + 1, result + i + 2 );
i = (start < 0) ? 0 : start;
continue;
  }
}
  }

  if (!*result) {
*result = stub_char;
result[1] = '\0';
  }

  return result;
}


int main (void)
{
  char *p = canonicalize_pathname (PATHNAME);
  __builtin_printf ("%s\n", p);
}
canonicalize_pathname.c: In function ‘canonicalize_pathname’:
canonicalize_pathname.c:61:2: warning: ‘strcpy’ accessing 1 byte at offsets [0,
9223372036854775807] and [0, 9223372036854775807] may overlap 1 byte at offset
0 [-Wrestrict]
   61 |  strcpy( result + start + 1, result + i + 2 );
  |  ^~~~
strcpy (0x217f265 = "//bar", 0x217f267 = "bar"): 3
/foo/bar

[Bug tree-optimization/88973] [8/9 Regression] New -Wrestrict warning since r268048

2019-01-22 Thread msebor at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88973

--- Comment #3 from Martin Sebor  ---
Created attachment 45497
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=45497=edit
canonicalize_pathname function extracted from the translation unit.

Attached is the canonicalize_pathname function extracted from the translation
unit that triggers the -Wrestrict warning.

[Bug tree-optimization/88973] [8/9 Regression] New -Wrestrict warning since r268048

2019-01-22 Thread msebor at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88973

Martin Sebor  changed:

   What|Removed |Added

 Blocks||84774

--- Comment #2 from Martin Sebor  ---
I feel like I have seen this translation unit before.  The warning is by
design: for calls to strcpy with the same destination and source arrays, where
the algorithm cannot prove that an overlap doesn't occur it issues a "may
overlap" kind of a warning.  The offset ranges make it clear (to me at least)
that the warning algorithm thinks the overlap is possible but not inevitable. 
For example, this triggers it:

  void f (char *p, int i)
  {
if (i < 0)
  i = 0;

char *q = p + i;

__builtin_strcpy (q, p);
  }

  t.c:10:3: warning: ‘__builtin_strcpy’ accessing 1 byte at offsets [0,
2147483647] and 0 may overlap 1 byte at offset 0 [-Wrestrict]
 10 |   __builtin_strcpy (q, p);
|   ^~~

The logic behind the decision is that since using strcpy to copy within the
same array is only safe when one knows the length of the source string (in
addition to the distance between the offsets into the array), using a "bounded"
function such as memcpy or even strncpy would be more appropriate: it would
make the constraints explicit without sacrificing efficiency or readability.

GCC 8 doesn't issue the warning here because the bug fixed in r268048 on the
trunk but not yet backported to gcc-8-branch gets in the way: the offset in the
POINTER_PLUS_EXPR is in the anti-range ~[INT_MAX + 1, INT_MIN] which GCC 8
doesn't handle correctly.  I haven't backported r268048 to GCC 8 yet but I
don't think this warning is a reason not to.  Richard, let me know if you feel
otherwise.


Referenced Bugs:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84774
[Bug 84774] [meta-bug] bogus/missing -Wrestrict

[Bug tree-optimization/88973] [8/9 Regression] New -Wrestrict warning since r268048

2019-01-22 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88973

Richard Biener  changed:

   What|Removed |Added

   Keywords||diagnostic
   Priority|P3  |P2
  Known to work||8.2.0
   Target Milestone|--- |8.3
Summary|New -Wrestrict warning  |[8/9 Regression] New
   |since r268048   |-Wrestrict warning since
   ||r268048
  Known to fail||8.2.1

--- Comment #1 from Richard Biener  ---
I believe the change was backported as well.